ocPortal Developer's Guide: TAR
» Return to Contents
ocPortal implements TAR support for use by the modification and backup modules, and other modules that wish to draw upon the functionality.
The same goes for ZIP support, although unzipping relies on PHP functions or an 'unzip' program being on the server.
It has been purposely implemented to act in the same way as standard PHP file IO.
sources/tar.php
Global_functions_tar.php
Function summary
|
array
|
tar_open (PATH path, string mode)
|
|
?array
|
tar_get_directory (array resource, boolean tolerate_errors)
|
|
integer
|
file_size_to_tar_block_size (integer size)
|
|
array
|
tar_add_folder_incremental (array resource, ?resource logfile, PATH path, TIME threshold, ?integer max_size, PATH subpath, boolean all_files)
|
|
void
|
tar_add_folder (array resource, ?resource logfile, PATH path, ?integer max_size, PATH subpath, ?array avoid_backing_up, ?array root_only_dirs, boolean tick, boolean all_files)
|
|
void
|
tar_extract_to_folder (array resource, PATH path, boolean use_afm, ?array files, boolean comcode_backups)
|
|
?array
|
tar_get_file (array resource, PATH path, boolean tolerate_errors, ?PATH write_data_to)
|
|
void
|
tar_add_file (array resource, PATH target_path, string data, integer _mode, TIME _mtime, boolean data_is_path)
|
|
integer
|
tar_crc (string header)
|
|
void
|
tar_close (array resource)
|
array tar_open(PATH path, string mode)
Open up a TAR archive, and return the resource.
Parameters…
| Name |
path |
| Description |
The path to the TAR archive |
| Type |
PATH |
| Name |
mode |
| Description |
The mode to open the TAR archive (rb=read, wb=write) |
| Type |
string |
| Values restricted to |
rb wb w+b |
Returns…
| Description |
The TAR file handle |
| Type |
array |
function tar_open($path,$mode)
{
$exists=file_exists($path) && (strpos($mode,'a')!==false);
$myfile=@fopen($path,$mode);
if ($myfile===false)
{
if (substr($mode,0,1)=='r')
warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
else
intelligent_write_error($path);
}
$resource=array();
$resource['new']=!$exists;
$resource['myfile']=$myfile;
$resource['full']=$path;
$resource['already_at_end']=false;
if (((!$exists) || (!(filesize($path)>0))) && (strpos($mode,'r')===false))
{
$chunk=pack('a512','');
if (fwrite($myfile,$chunk)<strlen($chunk)) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
$resource['directory']=array();
$resource['end']=0;
}
return $resource;
}
?array tar_get_directory(array resource, boolean tolerate_errors)
Return the root directory from the specified TAR file. Note that there are folders in here, and they will end '/'.
Parameters…
| Name |
resource |
| Description |
The TAR file handle |
| Type |
array |
| Name |
tolerate_errors |
| Description |
Whether to tolerate errors (returns NULL if error) |
| Default value |
boolean-false |
| Type |
boolean |
Returns…
| Description |
A list of maps that stores 'path', 'mode', 'size' and 'mtime', for each file in the archive (NULL: error) |
| Type |
?array |
function tar_get_directory(&$resource,$tolerate_errors=false)
{
if (array_key_exists('directory',$resource)) return $resource['directory'];
$myfile=$resource['myfile'];
$finished=false;
fseek($myfile,0,SEEK_SET);
$resource['already_at_end']=false;
$directory=array();
do
{
if (feof($myfile))
{
if ($tolerate_errors) return NULL;
warn_exit(do_lang_tempcode('CORRUPT_TAR'));
}
$offset=ftell($myfile);
$header=fread($myfile,512);
if (strlen($header)<512)
{
if ($tolerate_errors) return NULL;
warn_exit(do_lang_tempcode('CORRUPT_TAR'));
}
if (ord(substr($header,0,1))==0)
{
$finished=true;
$resource['end']=$offset;
} else
{
$path=str_replace('\\','/',substr($header,345,min(512,strpos($header,chr(0),345)-345)).substr($header,0,min(100,strpos($header,chr(0),0))));
$mode=octdec(substr($header,100,8));
$size=octdec(trim(substr($header,124,12)));
$mtime=octdec(trim(substr($header,136,12)));
$chksum=octdec(trim(substr($header,148,8)));
$block_size=file_size_to_tar_block_size($size);
// $is_ok=substr($header,156,1)=='0';
$header2=substr($header,0,148);
$header2.=' ';
$header2.=substr($header,156);
if ($chksum!=tar_crc($header2))
{
if ($tolerate_errors) return NULL;
warn_exit(do_lang_tempcode('CORRUPT_TAR'));
}
// if ($is_ok)
{
$directory[$offset]=array('path'=>$path,'mode'=>$mode,'size'=>$size,'mtime'=>$mtime);
}
fseek($myfile,$block_size,SEEK_CUR);
$resource['already_at_end']=false;
}
}
while (!$finished);
$resource['directory']=$directory;
return $directory;
}
integer file_size_to_tar_block_size(integer size)
Return the output from the conversion between filesize and TAR block size.
Parameters…
| Name |
size |
| Description |
The file size of a file that would be inside the TAR archive |
| Type |
integer |
Returns…
| Description |
The block size TAR would use to store this file |
| Type |
integer |
function file_size_to_tar_block_size($size)
{
return ($size%512==0)?$size:(intval($size/512)+1)*512;
}
array tar_add_folder_incremental(array resource, ?resource logfile, PATH path, TIME threshold, ?integer max_size, PATH subpath, boolean all_files)
Add a folder to the TAR archive, however only store files modifed after a threshold time. It is incremental (incremental backup), by comparing against a threshold before adding a file (threshold being time of last backup)
Parameters…
| Name |
resource |
| Description |
The TAR file handle |
| Type |
array |
| Name |
logfile |
| Description |
The logfile to write to (NULL: no logging) |
| Type |
?resource |
| Name |
path |
| Description |
The full path to the folder to add |
| Type |
PATH |
| Name |
threshold |
| Description |
The threshold time |
| Type |
TIME |
| Name |
max_size |
| Description |
The maximum file size to add (NULL: no limit) |
| Type |
?integer |
| Name |
subpath |
| Description |
The subpath relative to the path (should be left as the default '', as this is used for the recursion to distinguish the adding base path from where it's currently looking) |
| Default value |
|
| Type |
PATH |
| Name |
all_files |
| Description |
Whether to not skip "special files" (ones not normally archive) |
| Default value |
boolean-false |
| Type |
boolean |
Returns…
| Description |
A list of maps that stores 'path', 'mode' and 'size', for each newly added file in the archive |
| Type |
array |
function tar_add_folder_incremental(&$resource,$logfile,$path,$threshold,$max_size,$subpath='',$all_files=false)
{
require_code('files');
$_full=($path=='')?$subpath:($path.'/'.$subpath);
if ($_full=='') $_full='.';
$info=array();
$dh=opendir($_full);
if ($dh!==false)
{
while (($entry=readdir($dh))!==false)
{
if (($entry=='.') || ($entry=='..')) continue;
$_subpath=($subpath=='')?$entry:($subpath.'/'.$entry);
if ((($all_files) || (!should_ignore_file($_subpath))) && ($entry!='backups'))
{
$full=($path=='')?$_subpath:($path.'/'.$_subpath);
if (!is_readable($full)) continue;
if (is_dir($full))
{
$info2=tar_add_folder_incremental($resource,$logfile,$path,$threshold,$max_size,$_subpath,$all_files);
$info=array_merge($info,$info2);
}
else
{
if (($full!=$resource['full']) && ($full!='DIRECTORY'))
{
$ctime=filectime($full);
$mtime=filemtime($full);
if ((($mtime>$threshold || $ctime>$threshold)) && ((is_null($max_size)) || (filesize($full)<$max_size*1024*1024)))
{
tar_add_file($resource,$_subpath,$full,fileperms($full),filemtime($full),true);
if (!is_null($logfile) && fwrite($logfile,'Backed up file '.$full.' ('.clean_file_size(filesize($full)).')'."\n")==0) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
}
/* $owner=fileowner($full);
$group=filegroup($full);
if (function_exists('posix_getpwuid')) $owner=posix_getpwuid($owner);
if (function_exists('posix_getgrgid')) $group=posix_getgrgid($group);*/
$perms=fileperms($full);
$info[]=array('path'=>$full,'size'=>filesize($full),/*'owner'=>$owner,'group'=>$group,*/'perms'=>$perms,'ctime'=>$ctime,'mtime'=>$mtime);
}
}
}
}
closedir($dh);
}
return $info;
}
void tar_add_folder(array resource, ?resource logfile, PATH path, ?integer max_size, PATH subpath, ?array avoid_backing_up, ?array root_only_dirs, boolean tick, boolean all_files)
Add a folder to the TAR archive
Parameters…
| Name |
resource |
| Description |
The TAR file handle |
| Type |
array |
| Name |
logfile |
| Description |
The logfile to write to (NULL: no logging) |
| Type |
?resource |
| Name |
path |
| Description |
The full path to the folder to add |
| Type |
PATH |
| Name |
max_size |
| Description |
The maximum file size to add (NULL: no limit) |
| Default value |
|
| Type |
?integer |
| Name |
subpath |
| Description |
The subpath relative to the path (should be left as the default '', as this is used for the recursion to distinguish the adding base path from where it's currently looking) |
| Default value |
|
| Type |
PATH |
| Name |
avoid_backing_up |
| Description |
A map (filename=>1) of files to not back up (NULL: none) |
| Default value |
|
| Type |
?array |
| Name |
root_only_dirs |
| Description |
A list of directories ONLY to back up from the root (NULL: no restriction) |
| Default value |
|
| Type |
?array |
| Name |
tick |
| Description |
Whether to output spaces as we go to keep the connection alive |
| Default value |
boolean-false |
| Type |
boolean |
| Name |
all_files |
| Description |
Whether to not skip "special files" (ones not normally archive) |
| Default value |
boolean-false |
| Type |
boolean |
(No return value)
function tar_add_folder(&$resource,$logfile,$path,$max_size=NULL,$subpath='',$avoid_backing_up=NULL,$root_only_dirs=NULL,$tick=false,$all_files=false) // Note we cannot modify $resource unless we pass it by reference
{
require_code('files');
$_full=($path=='')?$subpath:($path.'/'.$subpath);
if ($_full=='') $_full='.';
$dh=opendir($_full);
if ($dh!==false)
{
while (($entry=readdir($dh))!==false)
{
if (($entry=='.') || ($entry=='..')) continue;
if ($tick) @print(' ');
$_subpath=($subpath=='')?$entry:($subpath.'/'.$entry);
if ((($all_files) || (!should_ignore_file($_subpath))) && ($entry!='backups'))
{
$full=($path=='')?$_subpath:($path.'/'.$_subpath);
if (!is_readable($full)) continue;
if (is_dir($full))
{
if ((is_null($root_only_dirs)) || (in_array($entry,$root_only_dirs)))
{
tar_add_folder($resource,$logfile,$path,$max_size,$_subpath,$avoid_backing_up,NULL,$tick,$all_files);
}
} else
{
if ((($full!=$resource['full']) && ((is_null($max_size)) || (filesize($full)<$max_size*1024*1024))) && ((is_null($avoid_backing_up)) || (!array_key_exists($_subpath,$avoid_backing_up))))
{
//echo $_subpath.'<br />';
tar_add_file($resource,$_subpath,$full,fileperms($full),filemtime($full),true);
if (!is_null($logfile) && fwrite($logfile,'Backed up file '.$full.' ('.clean_file_size(filesize($full)).')'."\n")==0) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
}
}
}
}
closedir($dh);
}
}
void tar_extract_to_folder(array resource, PATH path, boolean use_afm, ?array files, boolean comcode_backups)
Extract all the files in the specified TAR file to the specified path.
Parameters…
| Name |
resource |
| Description |
The TAR file handle |
| Type |
array |
| Name |
path |
| Description |
The full path to the folder to extract to |
| Type |
PATH |
| Name |
use_afm |
| Description |
Whether to extract via the AFM (assumes AFM has been set up prior to this function call) |
| Default value |
boolean-false |
| Type |
boolean |
| Name |
files |
| Description |
The files to extract (NULL: all) |
| Default value |
|
| Type |
?array |
| Name |
comcode_backups |
| Description |
Whether to take backups of Comcode pages |
| Default value |
boolean-false |
| Type |
boolean |
(No return value)
?array tar_get_file(array resource, PATH path, boolean tolerate_errors, ?PATH write_data_to)
Get the contents of the specified file in the specified TAR.
Parameters…
| Name |
resource |
| Description |
The TAR file handle |
| Type |
array |
| Name |
path |
| Description |
The full path to the file we want to get |
| Type |
PATH |
| Name |
tolerate_errors |
| Description |
Whether to tolerate errors (returns NULL if error) |
| Default value |
boolean-false |
| Type |
boolean |
| Name |
write_data_to |
| Description |
Write data to here (NULL: return within array) |
| Default value |
|
| Type |
?PATH |
Returns…
| Description |
A map, containing 'data' (the file), 'size' (the filesize), 'mtime' (the modification timestamp), and 'mode' (the permissions) (NULL: not found / TAR possibly corrupt if we turned tolerate errors on) |
| Type |
?array |
function tar_get_file(&$resource,$path,$tolerate_errors=false,$write_data_to=NULL)
{
if (!array_key_exists('directory',$resource))
{
$ret=tar_get_directory($resource,$tolerate_errors);
if (is_null($ret)) return NULL;
}
$directory=$resource['directory'];
foreach ($directory as $offset=>$stuff)
{
if ($stuff['path']==$path)
{
if (!is_null($write_data_to))
{
$outfile=fopen($write_data_to,'wb');
}
if ($stuff['size']==0)
{
$data='';
} else
{
fseek($resource['myfile'],$offset+512,SEEK_SET);
$resource['already_at_end']=false;
$data='';
while (strlen($data)<$stuff['size'])
{
$read_amount=min(4096,$stuff['size']-strlen($data));
$data.=fread($resource['myfile'],$read_amount);
if (!is_null($write_data_to))
{
if (fwrite($outfile,$data)<strlen($data)) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
$data='';
}
}
}
if (!is_null($write_data_to))
{
fclose($outfile);
fix_permissions($path);
sync_file($path);
}
return array('data'=>&$data,'size'=>$stuff['size'],'mode'=>$stuff['mode'],'mtime'=>$stuff['mtime']);
}
}
return NULL;
}
void tar_add_file(array resource, PATH target_path, string data, integer _mode, TIME _mtime, boolean data_is_path)
Add a file to the specified TAR file.
Parameters…
| Name |
resource |
| Description |
The TAR file handle |
| Type |
array |
| Name |
target_path |
| Description |
The relative path to where we wish to add the file to the archive (including filename) |
| Type |
PATH |
| Name |
data |
| Description |
The data of the file to add |
| Type |
string |
| Name |
_mode |
| Description |
The file mode (permissions) |
| Type |
integer |
| Name |
_mtime |
| Description |
The modification time we wish for our file |
| Type |
TIME |
| Name |
data_is_path |
| Description |
Whether the $data variable is actually a full file path |
| Default value |
boolean-false |
| Type |
boolean |
(No return value)
function tar_add_file(&$resource,$target_path,$data,$_mode,$_mtime,$data_is_path=false)
{
if (!array_key_exists('directory',$resource)) tar_get_directory($resource);
if (substr($target_path,0,1)=='/') $target_path=substr($target_path,1);
$directory=$resource['directory'];
foreach ($directory as $entry) // Make sure it does not exist
{
if ($entry['path']==$target_path)
{
warn_exit(do_lang_tempcode('FILE_IN_ARCHIVE_TWICE',escape_html($target_path)));
}
}
$myfile=$resource['myfile'];
// if (!$resource['already_at_end'])
{
fseek($myfile,$resource['end'],SEEK_SET);
$resource['already_at_end']=true;
}
$resource['directory'][$resource['end']]=array('path'=>$target_path,'mode'=>$_mode,'size'=>$data_is_path?filesize($data):strlen($data));
if (strlen($target_path)>100)
{
$prefix_length=strlen($target_path)-100;
$prefix=pack('a155',substr($target_path,0,$prefix_length));
$name=pack('a100',substr($target_path,$prefix_length));
} else
{
$name=pack('a100',$target_path);
$prefix=pack('a155','');
}
$mode=sprintf('%7s ',decoct($_mode));
$uid=sprintf('%7s ',decoct(fileowner(get_file_base().'/index.php')));
if (strlen($uid)>8) $uid=' ';
$gid=sprintf('%7s ',decoct(filegroup(get_file_base().'/index.php')));
if (strlen($gid)>8) $gid=' ';
$size=sprintf('%11s ',decoct($data_is_path?filesize($data):strlen($data)));
$mtime=sprintf('%11s ',decoct($_mtime));
$chksum=' ';
$typeflag=pack('a1','');
$linkname=pack('a100','');
$magic=pack('a6','ustar');
$version=pack('a2','');
$uname=pack('a8','');
$gname=pack('a8','');
$devmajor=pack('a8','');
$devminor=pack('a8','');
$whole=pack('a512',$name.$mode.$uid.$gid.$size.$mtime.$chksum.$typeflag.$linkname.$magic.$version.$uname.$gname.$devmajor.$devminor.$prefix);
$checksum=tar_crc($whole);
$chksum=pack('a8',decoct($checksum).' ');
$whole=pack('a512',$name.$mode.$uid.$gid.$size.$mtime.$chksum.$typeflag.$linkname.$magic.$version.$uname.$gname.$devmajor.$devminor.$prefix);
$chunk=pack('a512',$whole);
if (fwrite($myfile,$chunk)<strlen($chunk)) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
$block_size=file_size_to_tar_block_size($data_is_path?filesize($data):strlen($data));
if ($data_is_path)
{
$infile=fopen($data,'rb');
while (!feof($infile))
{
$in=fread($infile,8000);
if (fwrite($myfile,$in)<strlen($in)) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
}
fclose($infile);
$extra_to_write=$block_size-filesize($data);
if ($extra_to_write!=0)
if (fwrite($myfile,pack('a'.strval($extra_to_write),''))==0) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
} else
{
$chunk=pack('a'.strval($block_size),$data);
if (fwrite($myfile,$chunk)<strlen($chunk)) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
}
$chunk=pack('a512','');
if (fwrite($myfile,$chunk)<strlen($chunk)) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
$resource['end']+=512+$block_size;
}
integer tar_crc(string header)
Find the checksum specified in a TAR header
Parameters…
| Name |
header |
| Description |
The header from a TAR file |
| Type |
string |
Returns…
| Description |
The checksum |
| Type |
integer |
function tar_crc($header)
{
$checksum=0;
for ($i=0;$i<512;$i++)
{
$checksum+=ord(substr($header,$i,1));
}
return $checksum;
}
void tar_close(array resource)
Close an open TAR resource.
Parameters…
| Name |
resource |
| Description |
The TAR file handle to close |
| Type |
array |
(No return value)
function tar_close($resource)
{
fclose($resource['myfile']);
fix_permissions($resource['full']);
}
sources/m_zip.php
Global_functions_m_zip.php
void init__m_zip()
Standard code module initialisation function.
Parameters…
(No return value)
function init__m_zip()
{
$ud=get_option('unzip_dir');
if (substr($ud,-1)=='/') $ud=substr($ud,0,strlen($ud)-1);
define('UNZIP_DIR',$ud);
define('UNZIP_CMD',get_option('unzip_cmd'));
if (!function_exists('zip_open'))
{
if (substr(phpversion(),0,2)!='4.') eval("class ZIPARCHIVE
{
const ER_OK=0; /* N No error */
const ER_MULTIDISK=1; /* N Multi-disk zip archives not supported */
const ER_RENAME=2; /* S Renaming temporary file failed */
const ER_CLOSE=3; /* S Closing zip archive failed */
const ER_SEEK=4; /* S Seek error */
const ER_READ=5; /* S Read error */
const ER_WRITE=6; /* S Write error */
const ER_CRC=7; /* N CRC error */
const ER_ZIPCLOSED=8; /* N Containing zip archive was closed */
const ER_NOENT=9; /* N No such file */
const ER_EXISTS=10; /* N File already exists */
const ER_OPEN=11; /* S Can't open file */
const ER_TMPOPEN=12; /* S Failure to create temporary file */
const ER_ZLIB=13; /* Z Zlib error */
const ER_MEMORY=14; /* N Malloc failure */
const ER_CHANGED=15; /* N Entry has been changed */
const ER_COMPNOTSUPP=16; /* N Compression method not supported */
const ER_EOF=17; /* N Premature EOF */
const ER_INVAL=18; /* N Invalid argument */
const ER_NOZIP=19; /* N Not a zip archive */
const ER_INTERNAL=20; /* N Internal error */
const ER_INCONS=21; /* N Zip archive inconsistent */
const ER_REMOVE=22; /* S Can't remove file */
const ER_DELETED=23; /* N Entry has been deleted */
}
mixed zip_open(PATH zip_file)
Open a zip file for reading.
Parameters…
| Name |
zip_file |
| Description |
The zip file path |
| Type |
PATH |
Returns…
| Description |
The zip file resource (number if error) |
| Type |
mixed |
function zip_open($zip_file)
{
global $M_ZIP_DIR_HANDLES,$M_ZIP_DIR_OPEN_PATHS;
if (function_exists('set_time_limit')) @set_time_limit(200);
list($usec,$sec)=explode(' ',microtime(false));
$id=strval(intval($sec)-1007700000).str_pad(strval(intval($usec)*1000000),6,'0',STR_PAD_LEFT).str_pad(strval(mt_rand(0,999)),3,'0',STR_PAD_LEFT);
$_m_zip_open_file=explode('/',str_replace("\\",'/',$zip_file));
$m_zip_open_file='Z'.$id.$_m_zip_open_file[count($_m_zip_open_file)-1];
$zip_dir=UNZIP_DIR.'/'.$m_zip_open_file.'/';
mkdir($zip_dir,0777);
$unzip_cmd=UNZIP_CMD;
$unzip_cmd=str_replace('@_SRC_@','"'.$zip_file.'"',$unzip_cmd);
$unzip_cmd=str_replace('@_DST_@','"'.$zip_dir.'"',$unzip_cmd);
$bits=explode(' ',UNZIP_CMD);
if (!@file_exists(array_shift($bits)))
{
$_config_url=build_url(array('page'=>'admin_config','type'=>'category','id'=>'SITE'),get_module_zone('admin_config'));
$config_url=$_config_url->evaluate();
$config_url.='#group_ARCHIVES';
attach_message(do_lang_tempcode('NO_SHELL_ZIP_POSSIBLE2',escape_html($config_url)),'warn');
return constant('ZIPARCHIVE::ER_INTERNAL');
}
$res=-1; // any nonzero value
$unused_array_result=array();
if (strpos(@ini_get('disable_functions'),'exec')!==false)
{
attach_message(do_lang_tempcode('NO_SHELL_ZIP_POSSIBLE'),'warn');
return constant('ZIPARCHIVE::ER_INTERNAL');
}
exec($unzip_cmd,$unused_array_result,$res);
unset($unused_array_result);
// IT IS IMPORTANT THAT YOUR COMMANDLINE ZUNZIP TOOL CORRECTLY SETS RESULT CODE
// result code 0 == NO ERROR as in:
if ($res!=0)
{
m_deldir($zip_dir);
return constant('ZIPARCHIVE::ER_INTERNAL');
}
// OTHERWISE, you still have the option of parsing $unused_array_result to find clues of errors
// (lines starting with or "inflating" mean no error)
$m_zip_open_dirs=array(opendir($zip_dir));
$m_zip_dir_paths=array($zip_dir);
$M_ZIP_DIR_HANDLES[$zip_file]=false;
unset($M_ZIP_DIR_HANDLES[$zip_file]);
$M_ZIP_DIR_OPEN_PATHS[$zip_file]=false;
unset($M_ZIP_DIR_OPEN_PATHS[$zip_file]);
return array($zip_file,$m_zip_open_file,$m_zip_open_dirs,$m_zip_dir_paths);
}
boolean zip_close(array open_zip_file)
Close a zip file.
Parameters…
| Name |
open_zip_file |
| Description |
The zip file resource |
| Type |
array |
Returns…
| Description |
Whether the file closed correctly |
| Type |
boolean |
function zip_close($open_zip_file)
{
global $M_ZIP_DIR_HANDLES,$M_ZIP_DIR_OPEN_PATHS;
$m_zip_original_file=$open_zip_file[0];
$m_zip_open_file=$open_zip_file[1];
$m_zip_open_dirs=$open_zip_file[2];
$zip_dir=UNZIP_DIR.'/'.$m_zip_open_file.'/';
$M_ZIP_DIR_HANDLES[$m_zip_original_file]=false;
unset($M_ZIP_DIR_HANDLES[$m_zip_original_file]);
$M_ZIP_DIR_OPEN_PATHS[$m_zip_original_file]=false;
unset($M_ZIP_DIR_OPEN_PATHS[$m_zip_original_file]);
if (is_dir($zip_dir))
{
foreach ($m_zip_open_dirs as $opendir) closedir($opendir);
m_deldir($zip_dir);
}
$m_zip_open_file='';
return true;
}
~array zip_read(array open_zip_file)
Reads the next entry in a zip file archive.
Parameters…
| Name |
open_zip_file |
| Description |
The zip file resource |
| Type |
array |
Returns…
| Description |
A directory entry resource for later use with the m_zip_entry_…() functions (false: if there's no more entries to read). |
| Type |
~array |
function zip_read($open_zip_file)
{
global $M_ZIP_DIR_HANDLES,$M_ZIP_DIR_OPEN_PATHS;
$m_zip_original_file=$open_zip_file[0];
$m_zip_open_file=$open_zip_file[1];
// LOAD FILEHANDLES AND PATHS ARRAYS IF AVAILABLE
if (array_key_exists($m_zip_original_file,$M_ZIP_DIR_HANDLES)) $m_zip_open_dirs=$M_ZIP_DIR_HANDLES[$m_zip_original_file];
else $m_zip_open_dirs=$open_zip_file[2];
if (array_key_exists($m_zip_original_file,$M_ZIP_DIR_OPEN_PATHS)) $m_zip_dir_paths=$M_ZIP_DIR_OPEN_PATHS[$m_zip_original_file];
else $m_zip_dir_paths=$open_zip_file[3];
$zip_dir=UNZIP_DIR.'/'.$m_zip_open_file.'/';
$m_zip_last_open_dir=$m_zip_open_dirs[count($m_zip_open_dirs)-1];
$m_zip_last_dir_path=$m_zip_dir_paths[count($m_zip_dir_paths)-1];
$exit=false;
do
{
$entryname=readdir($m_zip_last_open_dir);
$exit=true;
if ($entryname!==false)
{
$entrypath=$m_zip_last_dir_path.$entryname;
if ($entryname=='.' || $entryname=='..')
{
$exit=false;
} elseif (($entryname!==false) && is_dir($entrypath) )
{
$exit=false;
$new_dir_path=$entrypath.'/';
$new_open_dir=opendir($new_dir_path);
if ($new_open_dir)
{
array_push($m_zip_dir_paths,$new_dir_path);
array_push($m_zip_open_dirs,$new_open_dir);
$m_zip_last_open_dir=$m_zip_open_dirs[count($m_zip_open_dirs)-1];
$m_zip_last_dir_path=$m_zip_dir_paths[count($m_zip_dir_paths)-1];
}
}
}
elseif (($entryname===false) && (count($m_zip_open_dirs)>1))
{
$exit=false;
closedir($m_zip_last_open_dir);
array_pop($m_zip_open_dirs);
array_pop($m_zip_dir_paths);
$m_zip_last_open_dir=$m_zip_open_dirs[count($m_zip_open_dirs)-1];
$m_zip_last_dir_path=$m_zip_dir_paths[count($m_zip_dir_paths)-1];
}
}
while (!$exit);
if ($entryname===false)
{
// NO MORE FILES CLEAR FILEHANDLES AND PATHS ARRAYS
$M_ZIP_DIR_HANDLES[$m_zip_original_file]=false;
unset($M_ZIP_DIR_HANDLES[$m_zip_original_file]);
$M_ZIP_DIR_OPEN_PATHS[$m_zip_original_file]=false;
unset($M_ZIP_DIR_OPEN_PATHS[$m_zip_original_file]);
return false;
}
// SAVE FILEHANDLES AND PATHS ARRAYS FOR NEXT RUN
$M_ZIP_DIR_HANDLES[$m_zip_original_file]=$m_zip_open_dirs;
$M_ZIP_DIR_OPEN_PATHS[$m_zip_original_file]=$m_zip_dir_paths;
return array($entryname,_m_zip_RelPath($zip_dir,$m_zip_last_dir_path),$m_zip_last_dir_path);
}
PATH _m_zip_RelPath(PATH base_path, PATH path)
Make a path relative.
Parameters…
| Name |
base_path |
| Description |
The base path (path to make relative to) |
| Type |
PATH |
| Name |
path |
| Description |
The path to make relative |
| Type |
PATH |
Returns…
| Description |
The relative path |
| Type |
PATH |
function _m_zip_RelPath($base_path,$path)
{
//echo("BasePath:$base_path,Path;$path");
if ($path==$base_path) return '';
if (strpos($path,$base_path)===0) return substr($path,strlen($base_path));
else return $path;
}
boolean zip_entry_open(array zip, array zip_entry, string mode)
Opens a directory entry in a zip file for reading.
Parameters…
| Name |
zip |
| Description |
The zip file resource |
| Type |
array |
| Name |
zip_entry |
| Description |
Directory entry resource returned by m_zip_read() |
| Type |
array |
| Name |
mode |
| Description |
The file access mode |
| Default value |
rb |
| Type |
string |
| Values restricted to |
rb |
Returns…
| Description |
Whether the operation was succesful |
| Type |
boolean |
function zip_entry_open($zip,$zip_entry,$mode='rb')
{
unset($mode);
global $M_ZIP_FILE_HANDLES;
$m_zip_file_handle=fopen($zip_entry[2].$zip_entry[0],'rb');
if ($m_zip_file_handle!==false)
{
$M_ZIP_FILE_HANDLES[$zip_entry[0]]=$m_zip_file_handle;
return true;
}
return false;
}
boolean zip_entry_close(array zip_entry)
Closes a directory entry previously opened for reading.
Parameters…
| Name |
zip_entry |
| Description |
Directory entry resource returned by m_zip_read() |
| Type |
array |
Returns…
| Description |
Whether the operation was succesful |
| Type |
boolean |
function zip_entry_close($zip_entry)
{
global $M_ZIP_FILE_HANDLES;
if ($M_ZIP_FILE_HANDLES[$zip_entry[0]])
{
fclose($M_ZIP_FILE_HANDLES[$zip_entry[0]]);
$M_ZIP_FILE_HANDLES[$zip_entry[0]]=false;
unset($M_ZIP_FILE_HANDLES[$zip_entry[0]]);
}
return true;
}
string zip_entry_name(array zip_entry)
Returns the name of the directory entry specified in the given entry.
Parameters…
| Name |
zip_entry |
| Description |
Directory entry resource returned by m_zip_read() |
| Type |
array |
Returns…
| Description |
The entry name |
| Type |
string |
function zip_entry_name($zip_entry)
{
return $zip_entry[1].$zip_entry[0];
}
integer zip_entry_filesize(array zip_entry)
Returns the filesize of the directory entry specified in the given entry.
Parameters…
| Name |
zip_entry |
| Description |
Directory entry resource returned by m_zip_read() |
| Type |
array |
Returns…
| Description |
The file size |
| Type |
integer |
function zip_entry_filesize($zip_entry)
{
clearstatcache();
return filesize($zip_entry[2].$zip_entry[0]);
}
~string zip_entry_read(array zip_entry, integer zip_entry_file_size)
Returns the file data of the directory entry specified in the given entry.
Parameters…
| Name |
zip_entry |
| Description |
Directory entry resource returned by m_zip_read() |
| Type |
array |
| Name |
zip_entry_file_size |
| Description |
The maximum returned data size |
| Default value |
1024 |
| Type |
integer |
Returns…
| Description |
The data (false: failure) |
| Type |
~string |
function zip_entry_read($zip_entry,$zip_entry_file_size=1024)
{
// Chris: Changed $zip_entry_file_size to default to 1024 as the proper zip_entry_read does -- no parameter does not mean read the whole file
global $M_ZIP_FILE_HANDLES;
// UNCOMMENT THIS TO SPEEDUP. WILL REQUIRE MORE RAM AND FAIL FOR BIG-BIG FILES
//if (/*$zip_entry_file_size==0 ||*/ $zip_entry_file_size==filesize($TheFile)) return implode('',file($TheFile));
$FH=$M_ZIP_FILE_HANDLES[$zip_entry[0]];
if ($FH)
{
$res='';
while ((strlen($res)<$zip_entry_file_size) && (!feof($FH)))
{
$read_amount=min(4096,$zip_entry_file_size-strlen($res));
$res.=fread($FH,$read_amount);
}
if ($res=='') return false;
else return $res;
}
return false; // Boh? (that in italian means who-knows-if-it-is-right-or-wrong-,-anyway-I-have-serious-perplexities-about-it-all)
}
void m_deldir(PATH a_dir)
Delete a directory of files.From "User Contributed Notes" at PHP: rmdir - Manual. Thanks flexer at cutephp dot com
Parameters…
| Name |
a_dir |
| Description |
The path to the directory |
| Type |
PATH |
(No return value)
function m_deldir($a_dir)
{
// echo('<p>Deleting:'.$a_dir);
// return; // uncomment to skip deletion (leave things)
// added support for trailing slash
if ((substr($a_dir,-1)=='/') || (substr($a_dir,-1)=='\\'))
{
$a_dir=substr($a_dir,0,-1);
}
if (is_dir($a_dir))
{
$current_dir=opendir($a_dir);
while (false!==($entryname=readdir($current_dir)))
{
//echo("<br>removing $a_dir/$entryname");
if (is_dir($a_dir.'/'.$entryname) && ($entryname!='.' && $entryname!='..'))
{
//echo("<ul>");
m_deldir($a_dir.'/'.$entryname);
//echo("</ul>");
} elseif ($entryname!='.' && $entryname!='..')
{
unlink($a_dir.'/'.$entryname);
}
}
closedir($current_dir);
rmdir($a_dir);
} else
{
// uncomment this if you want to delete files (use m_deldir on anything)
// unlink($a_dir);
// comment this if you want to skip warning
error_log('m_deldir() -- <b>Warning!</b> Not a directory: '.$a_dir);
}
}
sources/zip.php
Global_functions_zip.php
array zip_scan_folder(PATH path, PATH subpath)
Find file meta information for adding to a zip file
Parameters…
| Name |
path |
| Description |
The full path to the folder to add |
| Type |
PATH |
| Name |
subpath |
| Description |
The subpath relative to the path (should be left as the default '', as this is used for the recursion to distinguish the adding base path from where it's currently looking) |
| Default value |
|
| Type |
PATH |
Returns…
| Description |
A list of maps that stores time,full_path,name, for each file |
| Type |
array |
function zip_scan_folder($path,$subpath='')
{
$_full=($path=='')?$subpath:($path.'/'.$subpath);
if ($_full=='') $_full='.';
$info=array();
$dh=@opendir($_full);
if ($dh!==false)
{
while (($entry=readdir($dh))!==false)
{
$_subpath=($subpath=='')?$entry:($subpath.'/'.$entry);
if ((!should_ignore_file($_subpath)) && ($entry!='backups'))
{
$full=($path=='')?$_subpath:($path.'/'.$_subpath);
if (!is_readable($full)) continue;
if (is_dir($full))
{
$info2=zip_scan_folder($path,$_subpath);
$info=array_merge($info,$info2);
}
else
{
$mtime=filemtime($full);
$info[]=array('full_path'=>$full,'name'=>$_subpath,'time'=>$mtime);
}
}
}
closedir($dh);
}
return $info;
}
?integer crc32_file(PATH filename)
Calculate CRC32 for a file. Based on a function in the PHP docs.
Parameters…
| Name |
filename |
| Description |
The file |
| Type |
PATH |
Returns…
| Description |
The CRC (NULL: error) |
| Type |
?integer |
function crc32_file($filename)
{
if (function_exists('hash_file'))
{
$crc=hash_file('crc32b',$filename);
// Detect PHP bug http://bugs.php.net/bug.php?id=45028
$reverse=false;
$tempnam=ocp_tempnam('crctest');
$myfile=fopen($tempnam,'wb');
fwrite($myfile,'test');
fclose($myfile);
$crc_test=hash_file('crc32b',$tempnam);
unlink($tempnam);
if ($crc_test=='0c7e7fd8') $reverse=true;
if (!$reverse) return hexdec($crc);
return hexdec(substr($crc,6,2).substr($crc,4,2).substr($crc,2,2).substr($crc,0,2));
}
return crc32(file_get_contents($filename));
/* The below code is not 64-bit compatible :( */
/* $f = @fopen($filename,'rb');
if ($f===false) return NULL;
static $crc32table=array();
static $reflect8table=array();
if ($crc32table==array())
{
$polynomial = 0x04c11db7;
$top_bit = 1 << 31;
for($i = 0; $i < 256; $i++)
{
$remainder = $i << 24;
for ($j = 0; $j < 8; $j++)
{
if ($remainder & $top_bit)
$remainder = ($remainder << 1) ^ $polynomial;
else $remainder = $remainder << 1;
}
$crc32table[$i] = $remainder;
if (isset($reflect8table[$i])) continue;
$str = str_pad(decbin($i), 8, '0', STR_PAD_LEFT);
$num = bindec(strrev($str));
$reflect8table[$i] = $num;
$reflect8table[$num] = $i;
}
}
$remainder = 0xffffffff;
do
{
$data = fread($f,1024);
if ($data===false) break;
$len = strlen($data);
if ($len==0) break;
for ($i = 0; $i < $len; $i++)
{
$byte = $reflect8table[ord($data[$i])];
$index = @(($remainder >> 24) & 0xff) ^ $byte;
$crc = $crc32table[$index];
$remainder = @($remainder << 8) ^ $crc;
}
}
while (true);
$str = decbin($remainder);
$str = str_pad($str, 32, '0', STR_PAD_LEFT);
$remainder = bindec(strrev($str));
$crc=@($remainder ^ 0xffffffff);
if(@($crc & 0x80000000))
return $crc;*/
}
mixed create_zip_file(array file_array, boolean stream, boolean get_offsets)
Create a zip file.
Parameters…
| Name |
file_array |
| Description |
A list of maps (time,data/full_path,name) covering everything to zip up |
| Type |
array |
| Name |
stream |
| Description |
Whether to stream the output direct to the browser |
| Default value |
boolean-false |
| Type |
boolean |
| Name |
get_offsets |
| Description |
Whether to return the tuple |
| Default value |
boolean-false |
| Type |
boolean |
Returns…
| Description |
The data for the zip file OR a tuple: data, offsets, sizes |
| Type |
mixed |
function create_zip_file($file_array,$stream=false,$get_offsets=false)
{
if ($stream)
{
ini_set('ocproducts.xss_detect','0');
flush(); // Works around weird PHP bug that sends data before headers, on some PHP versions
}
$out='';
$offset=0;
$offsets=array();
$sizes=array();
// Write files
foreach ($file_array as $i=>$file)
{
$file_array[$i]['offset']=$offset;
$date=getdate($file['time']);
if ((!array_key_exists('data',$file)) || (is_null($file['data'])))
{
$crc=crc32_file($file['full_path']);
$uncompressed_size=filesize($file['full_path']);
} else
{
$crc=crc32($file['data']);
$uncompressed_size=strlen($file['data']);
}
$file_array[$i]['crc']=$crc;
$compressed_size=$uncompressed_size;
$now_date=(($date['year']-1980)<<25)|($date['mon']<<21)|($date['mday']<<16)|($date['hours']<<11)|($date['minutes']<<5)|($date['seconds']>>1);
$file_array[$i]['date']=$now_date;
$offsets[$file['name']]=$offset+30+strlen($file['name']);
$out.=pack('VvvvVVVVvv',0x04034b50,10,0,0,$now_date,$crc,$compressed_size,$uncompressed_size,strlen($file['name']),0);
$out.=$file['name'];
if ($stream)
{
echo $out;
$offset+=strlen($out)+$uncompressed_size;
if ((!array_key_exists('data',$file)) || (is_null($file['data'])))
{
readfile($file['full_path']);
} else
{
echo $file['data'];
}
$out='';
} else
{
if ((!array_key_exists('data',$file)) || (is_null($file['data'])))
{
$out.=file_get_contents($file['full_path'],FILE_BINARY);
} else
{
$out.=$file['data'];
}
$offset=strlen($out);
}
if ((!array_key_exists('data',$file)) || (is_null($file['data'])))
{
$sizes[$file['name']]=filesize($file['full_path']);
} else
{
$sizes[$file['name']]=strlen($file['data']);
}
}
// Write directory
$size=0;
foreach ($file_array as $file)
{
if ((!array_key_exists('data',$file)) || (is_null($file['data'])))
{
$uncompressed_size=filesize($file['full_path']);
} else
{
$uncompressed_size=strlen($file['data']);
}
$compressed_size=$uncompressed_size;
$packed=pack('VvvvvVVVVvvvvvVV',0x02014b50,20,10,0,0,$file['date'],$file['crc'],$compressed_size,$uncompressed_size,strlen($file['name']),0,0,0,0,32,$file['offset']);
$size+=strlen($packed)+strlen($file['name']);
$out.=$packed;
$out.=$file['name'];
if ($stream)
{
echo $out;
$out='';
}
}
// End of file data
$out.=pack('VvvvvVVv',0x06054b50,0,0,count($file_array),count($file_array),$size,$offset,0); // =46 bytes
if ($stream)
{
echo $out;
$out='';
}
if ($get_offsets) return array($out,$offsets,$sizes);
return $out;
}
0 reviews: Unrated (average)
There have been no comments yet