http://www.discuz.net/thread-751331-1-1.html
計劃任務-數據庫自動定期備份 For D6.0(v0.33 修復不會在預定時間執行與若干問題)
插件名稱:計劃任務-數據庫自動定期備份 For Discuz 6.0
適用版本:Discuz 6.0 (初步測試D5.5亦可運行)
插件作者: esyc
更新:部分數據庫太大時會Timeout,加入程序執行時間的timeout時間設定 (2007.09.26 11:17 V0.2)
更新:加入論壇關閉設定,可自行設定備份期間是否關閉論壇 (2007.09.26 23:43 V0.3)
修正:修正計劃任務不會在預定的時間執行,優化部份程序代碼 (2007.09.29 19:20 V0.31)
修正:修正由前台觸發任務時,zip壓縮出錯的問題以及部分小問題 (2007.09.29 20:30 V0.33)
說明:
與後台數據庫備份的效果相同,亦可選擇是否將文件壓縮成ZIP,16進製備份等等
1. 下載附件,解壓出 dbackupnolog.inc.php 。
2. 打開 dbackupnolog.inc.php 配置設定。
編輯好設定後儲存,將文件上傳到 include\crons 中
3. 到後台 "其它設置" -> "計劃任務"
4. 到最下面新增一筆 "數據庫定期備份" 並提交
5. 按 "數據庫定期備份" 後面的 "[編輯]" ,任務腳本 請輸入 dbackupnolog.inc.php
其它部分的設定則依照要備份的時間來設定。設定完畢後提交。
例如:每天早上6點備份 -> 小時設定為"6" , 分鐘設定為 "00"
每個禮拜天早上6點備份 -> 星期設定為"星期日",小時設定為"6" , 分鐘設定為 "00"
6. 回到計劃任務將 "數據庫定期備份" 的 "可用" 打勾並提交。
完畢
有任何問題請響應告知,若要轉貼請保留作者信息,謝謝。
dbackupnolog.inc.php 內容<?
/*
[Discuz!] (C)2001-2007 Comsenz Inc.
This is NOT a freeware, use is subject to license terms
Powered by Discuz! 6.0
$Id: dbackupnolog.inc.php 0.33 2007-09-29 20:30:00 esyc $
*/
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
//---------------備份設定,請在使用前,務必配置好下面的設置---------------------------
$timelimit = 300;
//執行時間設定,目前設定為超過300秒(5分鐘)才 Timeout,PHP運行於安全模式下無效
$allowclosebb = 1;
//備份期間是否關閉論壇? 可用值 0(不關閉論壇),1(關閉論壇)。若選擇關閉論壇,備份完畢後會自動重新開啟論壇。
$type = 'discuz';
//備份的類型,可用的為 discuz(完全備份), discuzsupesite(完全備份含SuperSite), custom(自定義,請自行修改備份的表)
$method = 'multivol';
//資料備份方式,可用的為multivol(Discuz! 分卷備份),shell(系統 MySQL Dump (Shell) 備份)
$sizelimit = 2048;
//選擇分卷備份時才有效,單一檔案長度限制(kb)。
$filename = date('ymd').'_'.random(8);
//備份檔名,一般無須修改。
$num = 200;
//生成的分卷檔案數目,請按照一般的情況的1.5倍左右數量填寫。
$extendins = 0;
//使用擴展插入(Extended Insert)方式,預設為否。可用值為 1(是),0(否)
$sqlcompat = '';
//建表語句格式,留空使用系統預設。可用值為 MYSQL40(MySQL 3.23/4.0.x),MYSQL41(MySQL 4.1.x/5.x)
$sqlcharset = '';
//強制字符集,留空使用系統預設字符集,可用的為 utf8。
$usehex = 1;
//十六進制方式,預設為是。可用值 0(否),1(是)
$usezip = 1;
//壓縮備份檔案,預設不壓縮。可用值為 0(不壓縮),1(多分卷壓縮成一個檔案),2(每個分卷壓縮成單獨檔案)。
$customtables = array('cdb_access', 'cdb_activities', 'cdb_activityapplies', 'cdb_adminactions',
'cdb_admingroups', 'cdb_adminnotes', 'cdb_advertisements',
'cdb_announcements', 'cdb_attachments', 'cdb_attachpaymentlog', 'cdb_attachtypes',
'cdb_banned', 'cdb_bbcodes', 'cdb_buddys', 'cdb_caches', 'cdb_campaigns',
'cdb_creditslog', 'cdb_crons', 'cdb_debateposts', 'cdb_debates', 'cdb_failedlogins',
'cdb_faqs', 'cdb_favorites', 'cdb_forumfields', 'cdb_forumlinks', 'cdb_forumrecommend',
'cdb_forums', 'cdb_imagetypes', 'cdb_invites', 'cdb_itempool', 'cdb_magiclog',
'cdb_magicmarket', 'cdb_magics', 'cdb_medals', 'cdb_memberfields', 'cdb_membermagics',
'cdb_members', 'cdb_memberspaces', 'cdb_moderators', 'cdb_modworks', 'cdb_myposts',
'cdb_mythreads', 'cdb_onlinelist', 'cdb_onlinetime', 'cdb_orders', 'cdb_paymentlog',
'cdb_pluginhooks', 'cdb_plugins', 'cdb_pluginvars', 'cdb_pms', 'cdb_pmsearchindex',
'cdb_polloptions', 'cdb_polls', 'cdb_posts', 'cdb_profilefields', 'cdb_projects',
'cdb_promotions', 'cdb_ranks', 'cdb_ratelog', 'cdb_regips', 'cdb_relatedthreads',
'cdb_rewardlog', 'cdb_rsscaches', 'cdb_searchindex', 'cdb_settings',
'cdb_smilies', 'cdb_spacecaches', 'cdb_stats', 'cdb_statvars', 'cdb_styles',
'cdb_stylevars', 'cdb_subscriptions', 'cdb_tags', 'cdb_templates', 'cdb_threads',
'cdb_threadsmod', 'cdb_threadtags', 'cdb_threadtypes', 'cdb_tradecomments', 'cdb_tradelog',
'cdb_tradeoptionvars', 'cdb_trades', 'cdb_typemodels', 'cdb_typeoptions',
'cdb_typeoptionvars', 'cdb_typevars', 'cdb_usergroups', 'cdb_validating', 'cdb_videos',
'cdb_videotags', 'cdb_words');
//自定義備份資料表設定
//---------------設定完畢-------------------------------------------------
if($allowclosebb) {
require_once DISCUZ_ROOT.'./include/cache.func.php';
$db->query("UPDATE {$tablepre}settings SET `value` = '1' WHERE `variable` = 'bbclosed' LIMIT 1");
updatecache('settings');
}
@set_time_limit($timelimit);
$excepttables = array_merge(array($tablepre.'adminsessions', $tablepre.'failedlogins', $tablepre.'pmsearchindex', $tablepre.'relatedthreads', $tablepre.'rsscaches', $tablepre.'searchindex', $tablepre.'spacecaches', $tablepre.'sessions'),
($supe['status'] ? array($supe['tablepre'].'cache', $supe['tablepre'].'corpus', $supe['tablepre'].'rss', $supe['tablepre'].'spacecache', $supe['tablepre'].'tagcache') : array()));
if(!$backupdir = $db->result($db->query("SELECT value FROM {$tablepre}settings WHERE variable='backupdir'"), 0)) {
$backupdir = random(6);
@mkdir('./forumdata/backup_'.$backupdir, 0777);
$db->query("REPLACE INTO {$tablepre}settings (variable, value) values ('backupdir', '$backupdir')");
}
$backupdir = 'backup_'.$backupdir;
if(!is_dir('./forumdata/'.$backupdir)) {
mkdir('./forumdata/'.$backupdir, 0777);
}
$db->query('SET SQL_QUOTE_SHOW_CREATE=0', 'SILENT');
$time = gmdate("$dateformat $timeformat", $timestamp + $timeoffset * 3600);
if($type == 'discuz') {
$tables = arraykeys2(fetchtablelist($tablepre), 'Name');
} elseif($type == 'discuzsupesite') {
$tables = arraykeys2(array_merge(fetchtablelist($tablepre), ($supe['tablepre'] ? fetchtablelist($supe['tablepre']) : array())), 'Name');
} elseif($type == 'custom') {
$tables = array();
if(empty($setup)) {
$query = $db->query("SELECT value FROM {$tablepre}settings WHERE variable='custombackup'");
if($tables = $db->fetch_array($query)) {
$tables = unserialize($tables['value']);
}
} else {
$customtables= array_merge(empty($customtables) ? array() : $customtables, empty($supetables) ? array() : $supetables);
$customtablesnew = empty($customtables)? '' : addslashes(serialize($customtables));
$db->query("REPLACE INTO {$tablepre}settings (variable, value) VALUES ('custombackup', '$customtablesnew')");
$tables = & $customtables;
}
}
$query = $db->query("SELECT datatables FROM {$tablepre}plugins WHERE datatables<>''");
while($plugin = $db->fetch_array($query)) {
foreach(explode(',', $plugin['datatables']) as $table) {
if($table = trim($table)) {
$tables[] = $table;
}
}
}
$dumpcharset = $sqlcharset ? $sqlcharset : str_replace('-', '', $GLOBALS['charset']);
$setnames = ($sqlcharset && $db->version() > '4.1' && (!$sqlcompat || $sqlcompat == 'MYSQL41')) ? "SET NAMES '$dumpcharset';\n\n" : '';
$backupfilename = './forumdata/'.$backupdir.'/'.str_replace(array('/', '\\', '.'), '', $filename);
$idstring = '# Identify: '.base64_encode("$timestamp,$version,$type,$method,$volume")."\n";
if($db->version() > '4.1') {
if($sqlcharset) {
$db->query("SET NAMES '".$sqlcharset."';\n\n");
}
if($sqlcompat == 'MYSQL40') {
$db->query("SET SQL_MODE='MYSQL40'");
} elseif($sqlcompat == 'MYSQL41') {
$db->query("SET SQL_MODE=''");
}
}
if($method == 'multivol') {
for($volcount = 0; $volcount < $num; $volcount++) {
$volume = intval($volume) + 1;
$idstring = '# Identify: '.base64_encode("$timestamp,$version,$type,$method,$volume")."\n";
$sqldump = $tabledump = '';
$tableid = intval($tableid);
$startfrom = intval($startfrom);
$complete = TRUE;
for(; $complete && $tableid < count($tables) && strlen($sqldump) + 500 < $sizelimit * 1000; $tableid++) {
$currsize = strlen($sqldump);
$table = $tables[$tableid];
$offset = 300;
$tabledump = '';
$tablefields = array();
$query = $db->query("SHOW FULL COLUMNS FROM $table", 'SILENT');
$qerrorno = $db->errno();
$existas = strexists($table, 'adminsessions');
if(!$startfrom){
$startfrom = 0;
$createtable = $db->query("SHOW CREATE TABLE $table", 'SILENT');
$ctablerror = $db->errno();
}
if(!$currsize){
$currsize = 0;
}
if($existas) {
$tabledump = '';
} elseif(!$query && $qerrorno == 1146) {
$tabledump = '';
} else {
if(!$query && !$existas && $qerrorno != 1146) {
$usehex = FALSE;
} else {
while($fieldrow = $db->fetch_array($query)) {
$tablefields[] = $fieldrow;
}
}
if(!$startfrom && !$ctablerror) {
$tabledump = "DROP TABLE IF EXISTS $table;\n";
$create = $db->fetch_row($createtable);
if(strpos($table, '.') !== FALSE) {
$tablename = substr($table, strpos($table, '.') + 1);
$create[1] = str_replace("CREATE TABLE $tablename", 'CREATE TABLE '.$table, $create[1]);
}
$tabledump .= $create[1];
if($sqlcompat == 'MYSQL41' && $db->version() < '4.1') {
$tabledump = preg_replace("/TYPE\=(.+)/", "ENGINE=\\1 DEFAULT CHARSET=".$dumpcharset, $tabledump);
}
if($db->version() > '4.1' && $sqlcharset) {
$tabledump = preg_replace("/(DEFAULT)*\s*CHARSET=.+/", "DEFAULT CHARSET=".$sqlcharset, $tabledump);
}
$query = $db->query("SHOW TABLE STATUS LIKE '$table'");
$tablestatus = $db->fetch_array($query);
$tabledump .= ($tablestatus['Auto_increment'] ? " AUTO_INCREMENT=$tablestatus[Auto_increment]" : '').";\n\n";
if($sqlcompat == 'MYSQL40' && $db->version() >= '4.1' && $db->version() < '5.1') {
if($tablestatus['Auto_increment'] <> '') {
$temppos = strpos($tabledump, ',');
$tabledump = substr($tabledump, 0, $temppos).' auto_increment'.substr($tabledump, $temppos);
}
if($tablestatus['Engine'] == 'MEMORY') {
$tabledump = str_replace('TYPE=MEMORY', 'TYPE=HEAP', $tabledump);
}
}
}
if(!in_array($table, $excepttables)) {
$tabledumped = 0;
$numrows = $offset;
$firstfield = $tablefields[0];
if($extendins == '0') {
while($currsize + strlen($tabledump) + 500 < $sizelimit * 1000 && $numrows == $offset) {
if($firstfield['Extra'] == 'auto_increment') {
$selectsql = "SELECT * FROM $table WHERE $firstfield[Field] > $startfrom LIMIT $offset";
} else {
$selectsql = "SELECT * FROM $table LIMIT $startfrom, $offset";
}
$tabledumped = 1;
$rows = $db->query($selectsql);
$numfields = $db->num_fields($rows);
$numrows = $db->num_rows($rows);
while($row = $db->fetch_row($rows)) {
$comma = $t = '';
for($i = 0; $i < $numfields; $i++) {
$t .= $comma.($usehex && !empty($row[$i]) && (strexists($tablefields[$i]['Type'], 'char') || strexists($tablefields[$i]['Type'], 'text')) ? '0x'.bin2hex($row[$i]) : '\''.mysql_escape_string($row[$i]).'\'');
$comma = ',';
}
if(strlen($t) + $currsize + strlen($tabledump) + 500 < $sizelimit * 1000) {
if($firstfield['Extra'] == 'auto_increment') {
$startfrom = $row[0];
} else {
$startfrom++;
}
$tabledump .= "INSERT INTO $table VALUES ($t);\n";
} else {
$complete = FALSE;
break 2;
}
}
}
} else {
while($currsize + strlen($tabledump) + 500 < $sizelimit * 1000 && $numrows == $offset) {
if($firstfield['Extra'] == 'auto_increment') {
$selectsql = "SELECT * FROM $table WHERE $firstfield[Field] > $startfrom LIMIT $offset";
} else {
$selectsql = "SELECT * FROM $table LIMIT $startfrom, $offset";
}
$tabledumped = 1;
$rows = $db->query($selectsql);
$numfields = $db->num_fields($rows);
if($numrows = $db->num_rows($rows)) {
$t1 = $comma1 = '';
while($row = $db->fetch_row($rows)) {
$t2 = $comma2 = '';
for($i = 0; $i < $numfields; $i++) {
$t2 .= $comma2.($usehex && !empty($row[$i]) && (strexists($tablefields[$i]['Type'], 'char') || strexists($tablefields[$i]['Type'], 'text'))? '0x'.bin2hex($row[$i]) : '\''.mysql_escape_string($row[$i]).'\'');
$comma2 = ',';
}
if(strlen($t1) + $currsize + strlen($tabledump) + 500 < $sizelimit * 1000) {
if($firstfield['Extra'] == 'auto_increment') {
$startfrom = $row[0];
} else {
$startfrom++;
}
$t1 .= "$comma1 ($t2)";
$comma1 = ',';
} else {
$tabledump .= "INSERT INTO $table VALUES $t1;\n";
$complete = FALSE;
break 2;
}
}
$tabledump .= "INSERT INTO $table VALUES $t1;\n";
}
}
}
$startrow = $startfrom;
$tabledump .= "\n";
}
}
$sqldump .= $tabledump;
if($complete) {
$startfrom = 0;
}
}
$dumpfile = $backupfilename."-%s".'.sql';
!$complete && $tableid--;
if(trim($sqldump)) {
$sqldump = "$idstring".
"# <?exit();?>\n".
"# Discuz! Multi-Volume Data Dump Vol.$volume\n".
"# Version: Discuz! $version\n".
"# Time: $time\n".
"# Type: $type\n".
"# Table Prefix: $tablepre\n".
"#\n".
"# Discuz! Home: http://www.discuz.com\n".
"# Please visit our website for newest infomation about Discuz!\n".
"# --------------------------------------------------------\n\n\n".
"$setnames".
$sqldump;
$dumpfilename = sprintf($dumpfile, $volume);
@$fp = fopen($dumpfilename, 'wb');
@flock($fp, 2);
if(@!fwrite($fp, $sqldump)) {
@fclose($fp);
unset($sqldump);
}
}
}
$startfrom = $startrow;
}
if($method == 'shell') {
$tablesstr = '';
foreach($tables as $table) {
$tablesstr .= '"'.$table.'" ';
}
require './config.inc.php';
list($dbhost, $dbport) = explode(':', $dbhost);
$query = $db->query("SHOW VARIABLES LIKE 'basedir'");
list(, $mysql_base) = $db->fetch_array($query, MYSQL_NUM);
$dumpfile = addslashes(dirname(dirname(__FILE__))).'/../'.$backupfilename.'.sql';
@unlink($dumpfile);
$mysqlbin = $mysql_base == '/' ? '' : addslashes($mysql_base).'bin/';
@shell_exec($mysqlbin.'mysqldump --force --quick '.($db->version() > '4.1' ? '--skip-opt --create-options' : '-all').' --add-drop-table'.($extendins == 1 ? ' --extended-insert' : '').''.($db->version() > '4.1' && $sqlcompat == 'MYSQL40' ? ' --compatible=mysql40' : '').' --host="'.$dbhost.($dbport ? (is_numeric($dbport) ? ' --port='.$dbport : ' --socket="'.$dbport.'"') : '').'" --user="'.$dbuser.'" --password="'.$dbpw.'" "'.$dbname.'" '.$tablesstr.' > '.$dumpfile);
if(@file_exists($dumpfile)) {
if(@is_writeable($dumpfile)) {
$fp = fopen($dumpfile, 'rb+');
@fwrite($fp, $idstring."# <?exit();?>\n ".$setnames."\n #");
fclose($fp);
}
@touch('./forumdata/'.$backupdir.'/index.htm');
}
}
/*
if ($usezip) {
require_once DISCUZ_ROOT.'./admin/zip.func.php';
}
*/
$matchstring = '/^'.$filename.'(.*).sql$/';
if($method == 'multivol') {
$zipfilename = '';
if ($usezip == 2) {
$handle=opendir('./forumdata/'.$backupdir);
chdir('./forumdata/'.$backupdir);
while ($files = readdir($handle)) {
if (preg_match($matchstring, $files)) {
$zip = new zipfile();
$zipfilenames = explode(".", $files);
$zipfilename = $zipfilenames[0];
$fp = fopen($files, "r");
$content = fread($fp, filesize($files));
fclose($fp);
$zip->addFile($content, basename($files));
$fp = fopen(sprintf($zipfilename.'.zip'), 'w');
if(@fwrite($fp, $zip->file()) !== FALSE) {
@unlink($files);
}
fclose($fp);
@touch('./forumdata/'.$backupdir.'/index.htm');
unset($zip, $content);
}
}
} elseif ($usezip == 1) {
$handle=opendir('./forumdata/'.$backupdir);
chdir('./forumdata/'.$backupdir);
$unlinks = '';
$filecount = 0;
while ($files = readdir($handle)) {
if (preg_match($matchstring, $files)) {
$filecount++;
$backfile = $files;
}
}
$zip = new zipfile();
$zipfilenames = explode("-", $backfile);
$zipfilename = $zipfilenames[0];
for($i = 1; $i <= $filecount; $i++) {
$filename = sprintf($zipfilename."-%s".'.sql', $i);
$fp = fopen($filename, "r");
$content = @fread($fp, filesize($filename));
fclose($fp);
$zip->addFile($content, basename($filename));
$unlinks .= "@unlink('$filename');";
}
$fp = fopen($zipfilename.".zip", 'w');
if(@fwrite($fp, $zip->file()) !== FALSE) {
eval($unlinks);
}
fclose($fp);
unset($zip, $content);
}
} elseif ($method == 'shell') {
if ($usezip) {
$handle=opendir('./forumdata/'.$backupdir);
chdir('./forumdata/'.$backupdir);
while ($files = readdir($handle)) {
if (preg_match($matchstring, $files)) {
$zip = new zipfile();
$zipfilenames = explode(".", $files);
$zipfilename = $zipfilenames[0];
$fp = fopen($files, "r");
$content = @fread($fp, filesize($files));
fclose($fp);
$zip->addFile($idstring."# <?exit();?>\n ".$setnames."\n #".$content, basename($files));
$fp = fopen(sprintf($zipfilename.'.zip'), 'w');
if(@fwrite($fp, $zip->file()) !== FALSE) {
@unlink($files);
}
fclose($fp);
@touch('./forumdata/'.$backupdir.'/index.htm');
unset($zip, $content);
}
}
}
}
if($allowclosebb) {
$db->query("UPDATE {$tablepre}settings SET `value` = '0' WHERE `variable` = 'bbclosed' LIMIT 1");
updatecache('settings');
}
function fetchtablelist($tablepre = '') {
global $db;
$arr = explode('.', $tablepre);
$dbname = $arr[1] ? $arr[0] : '';
$sqladd = $dbname ? " FROM $dbname LIKE '$arr[1]%'" : "LIKE '$tablepre%'";
!$tablepre && $tablepre = '*';
$tables = $table = array();
$query = $db->query("SHOW TABLE STATUS $sqladd");
while($table = $db->fetch_array($query)) {
$table['Name'] = ($dbname ? "$dbname." : '').$table['Name'];
$tables[] = $table;
}
return $tables;
}
function arraykeys2($array, $key2) {
$return = array();
foreach($array as $val) {
$return[] = $val[$key2];
}
return $return;
}
function syntablestruct($sql, $version, $dbcharset) {
if(strpos(trim(substr($sql, 0, 18)), 'CREATE TABLE') === FALSE) {
return $sql;
}
$sqlversion = strpos($sql, 'ENGINE=') === FALSE ? FALSE : TRUE;
if($sqlversion === $version) {
return $sqlversion && $dbcharset ? preg_replace(array('/ character set \w+/i', '/ collate \w+/i', "/DEFAULT CHARSET=\w+/is"), array('', '', "DEFAULT CHARSET=$dbcharset"), $sql) : $sql;
}
if($version) {
return preg_replace(array('/TYPE=HEAP/i', '/TYPE=(\w+)/is'), array("ENGINE=MEMORY DEFAULT CHARSET=$dbcharset", "ENGINE=\\1 DEFAULT CHARSET=$dbcharset"), $sql);
} else {
return preg_replace(array('/character set \w+/i', '/collate \w+/i', '/ENGINE=MEMORY/i', '/\s*DEFAULT CHARSET=\w+/is', '/\s*COLLATE=\w+/is', '/ENGINE=(\w+)(.*)/is'), array('', '', 'ENGINE=HEAP', '', '', 'TYPE=\\1\\2'), $sql);
}
}
class zipfile {
var $datasec = array();
var $ctrl_dir = array();
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
var $old_offset = 0;
function unix2DosTime($unixtime = 0) {
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
if($timearray['year'] < 1980) {
$timearray['year'] = 1980;
$timearray['mon'] = 1;
$timearray['mday'] = 1;
$timearray['hours'] = 0;
$timearray['minutes'] = 0;
$timearray['seconds'] = 0;
} // end if
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
} // end of the 'unix2DosTime()' method
function addFile($data, $name, $time = 0) {
$name = str_replace('\\', '/', $name);
$dtime = dechex($this->unix2DosTime($time));
$hexdtime = '\x' . $dtime[6] . $dtime[7]
. '\x' . $dtime[4] . $dtime[5]
. '\x' . $dtime[2] . $dtime[3]
. '\x' . $dtime[0] . $dtime[1];
eval('$hexdtime = "' . $hexdtime . '";');
$fr = "\x50\x4b\x03\x04";
$fr .= "\x14\x00"; // ver needed to extract
$fr .= "\x00\x00"; // gen purpose bit flag
$fr .= "\x08\x00"; // compression method
$fr .= $hexdtime; // last mod time and date
// "local file header" segment
$unc_len = strlen($data);
$crc = crc32($data);
$zdata = gzcompress($data);
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
$c_len = strlen($zdata);
$fr .= pack('V', $crc); // crc32
$fr .= pack('V', $c_len); // compressed filesize
$fr .= pack('V', $unc_len); // uncompressed filesize
$fr .= pack('v', strlen($name)); // length of filename
$fr .= pack('v', 0); // extra field length
$fr .= $name;
// "file data" segment
$fr .= $zdata;
// "data descriptor" segment (optional but necessary if archive is not
// served as file)
// nijel(2004-10-19): this seems not to be needed at all and causes
// problems in some cases (bug #1037737)
//$fr .= pack('V', $crc); // crc32
//$fr .= pack('V', $c_len); // compressed filesize
//$fr .= pack('V', $unc_len); // uncompressed filesize
// add this entry to array
$this -> datasec[] = $fr;
// now add to central directory record
$cdrec = "\x50\x4b\x01\x02";
$cdrec .= "\x00\x00"; // version made by
$cdrec .= "\x14\x00"; // version needed to extract
$cdrec .= "\x00\x00"; // gen purpose bit flag
$cdrec .= "\x08\x00"; // compression method
$cdrec .= $hexdtime; // last mod time & date
$cdrec .= pack('V', $crc); // crc32
$cdrec .= pack('V', $c_len); // compressed filesize
$cdrec .= pack('V', $unc_len); // uncompressed filesize
$cdrec .= pack('v', strlen($name) ); // length of filename
$cdrec .= pack('v', 0 ); // extra field length
$cdrec .= pack('v', 0 ); // file comment length
$cdrec .= pack('v', 0 ); // disk number start
$cdrec .= pack('v', 0 ); // internal file attributes
$cdrec .= pack('V', 32 ); // external file attributes - 'archive' bit set
$cdrec .= pack('V', $this -> old_offset ); // relative offset of local header
$this -> old_offset += strlen($fr);
$cdrec .= $name;
// optional extra field, file comment goes here
// save to central directory
$this -> ctrl_dir[] = $cdrec;
} // end of the 'addFile()' method
function file() {
$data = implode('', $this -> datasec);
$ctrldir = implode('', $this -> ctrl_dir);
return
$data .
$ctrldir .
$this -> eof_ctrl_dir .
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk"
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall
pack('V', strlen($ctrldir)) . // size of central dir
pack('V', strlen($data)) . // offset to start of central dir
"\x00\x00"; // .zip file comment length
} // end of the 'file()' method
} // end of the 'zipfile' class
?>
|