<?php
/**
* Quicksilver Forums
* Copyright (c) 2005-2011 The Quicksilver Forums Development Team
* http://code.google.com/p/quicksilverforums/
*
* Based on MercuryBoard
* Copyright (c) 2001-2005 The Mercury Development Team
* http://www.mercuryboard.com/
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
**/
if (!defined('QUICKSILVERFORUMS')) {
header('HTTP/1.0 403 Forbidden');
die;
}
/**
* Simplified version of ZipLib
*
* @author Bouchon <hide@address.com>
* @link http://maxg.info
* @since 1.0.2
**/
class qsf_zip
{
var $datasec = array();
var $ctrl_dir = array();
var $old_offset = 0;
function add($files, $name = '.')
{
if (!is_array($files)) {
$files = array($files);
}
foreach ($files as $file)
{
if (is_dir($file)) {
$this->add_dir($name);
$this->spider($file, $name);
} else {
$fp = fopen($file, 'r');
$this->add_file(fread($fp, filesize($file)), $file);
fclose($fp);
}
}
}
function spider($dir, $name)
{
$dp = opendir($dir);
while (($file = readdir($dp)) !== false)
{
if (($file == '.') || ($file == '..') || ($file == 'CVS') || ($file{0} == '.')) {
continue;
}
$real_path = $dir . '/' . $file;
$zip_path = $name . '/' . $file;
if (is_dir($real_path)) {
$this->add_dir($zip_path);
$this->spider($real_path, $zip_path);
} else {
$fp = fopen($real_path, 'r');
if (0 == ($tmp = filesize($real_path))) {
$this->add_file('', $zip_path);
} else {
$this->add_file(fread($fp, $tmp), $zip_path);
}
fclose($fp);
}
}
closedir($dp);
}
function get_file()
{
$data = implode('', $this->datasec);
$ctrl = implode('', $this->ctrl_dir);
return
$data .
$ctrl .
"\x50\x4b\x05\x06" .
"\x00\x00" .
"\x00\x00" .
pack('v', count($this->ctrl_dir)) .
pack('v', count($this->ctrl_dir)) .
pack('V', strlen($ctrl)) .
pack('V', strlen($data)) .
"\x00\x00";
}
function add_dir($name)
{
$name = str_replace('\\', '/', $name);
if (substr($name, -1) != '/') {
$name .= '/';
}
$local_header = "\x50\x4b\x03\x04"; // local file header signature
$local_header .= "\x0a\x00"; // version needed to extract
$local_header .= "\x00\x00"; // general purpose bit flag
$local_header .= "\x00\x00"; // compression method
$local_header .= "\x00\x00"; // last mod file time
$local_header .= "\x00\x00"; // last mod file date
$local_header .= pack('V', 0); // crc-32
$local_header .= pack('V', 0); // compressed size
$local_header .= pack('V', 0); // uncompressed size
$local_header .= pack('v', strlen($name)); // file name length
$local_header .= pack('v', 0); // extra field length
$local_header .= $name; // file name
$central_header = "\x50\x4b\x01\x02"; // central file header signature
$central_header .= "\x00\x00"; // version made by
$central_header .= "\x0a\x00"; // version needed to extract
$central_header .= "\x00\x00"; // general purpose bit flag
$central_header .= "\x00\x00"; // compression method
$central_header .= "\x00\x00"; // last mod file time
$central_header .= "\x00\x00"; // last mod file date
$central_header .= pack('V', 0); // crc-32
$central_header .= pack('V', 0); // compressed size
$central_header .= pack('V', 0); // uncompressed size
$central_header .= pack('v', strlen($name)); // file name length
$central_header .= pack('v', 0); // extra field length
$central_header .= pack('v', 0); // file comment length
$central_header .= pack('v', 0); // disk number start
$central_header .= pack('v', 0); // internal file attributes
$central_header .= pack('V', 16); // external file attributes
$central_header .= pack('V', $this->old_offset); // relative offset of local header
$central_header .= $name; // file name
$this->old_offset += strlen($local_header);
$this->datasec[] = $local_header;
$this->ctrl_dir[] = $central_header;
}
function add_file($data, $name)
{
$name = str_replace('\\', '/', $name);
$len = strlen($data);
$crc = crc32($data);
$local_header = "\x50\x4b\x03\x04"; // local file header signature
$local_header .= "\x14\x00"; // version needed to extract
$local_header .= "\x00\x00"; // general purpose bit flag
$local_header .= "\x08\x00"; // compression method
$local_header .= "\x00\x00"; // last mod file time
$local_header .= "\x00\x00"; // last mod file date
$local_header .= pack('V', $crc); // crc-32
$local_header .= pack('V', $len); // compressed size
$local_header .= pack('V', $len); // uncompressed size
$local_header .= pack('v', strlen($name)); // file name length
$local_header .= pack('v', 0); // extra field length
$local_header .= $name; // file name
$local_header .= $data; // file data
$central_header = "\x50\x4b\x01\x02"; // central file header signature
$central_header .= "\x00\x00"; // version made by
$central_header .= "\x14\x00"; // version needed to extract
$central_header .= "\x00\x00"; // general purpose bit flag
$central_header .= "\x08\x00"; // compression method
$central_header .= "\x00\x00"; // last mod file time
$central_header .= "\x00\x00"; // last mod file date
$central_header .= pack('V', $crc); // crc-32
$central_header .= pack('V', $len); // compressed size
$central_header .= pack('V', $len); // uncompressed size
$central_header .= pack('v', strlen($name)); // file name length
$central_header .= pack('v', 0); // extra field length
$central_header .= pack('v', 0); // file comment length
$central_header .= pack('v', 0); // disk number start
$central_header .= pack('v', 32); // internal file attributes
$central_header .= pack('V', 0); // external file attributes
$central_header .= pack('V', $this->old_offset); // relative offset of local header
$central_header .= $name; // file name
$this->old_offset += strlen($local_header);
$this->datasec[] = $local_header;
$this->ctrl_dir[] = $central_header;
}
/**
* Attempts to CHMOD a directory or file
*
* @param string $path Path to CHMOD
* @param int $mode New CHMOD value
* @param bool $recursive True for recursive
* @author Jason Warner <hide@address.com>
* @since 1.1.5
* @return void
**/
function chmod($path, $mode, $recursive = false)
{
if (!$recursive || !is_dir($path)) {
@chmod($path, $mode);
return;
}
$dir = opendir($path);
while (($file = readdir($dir)) !== false)
{
if(($file == '.') || ($file == '..')) {
continue;
}
$fullpath = $path . '/' . $file;
if(!is_dir($fullpath)) {
@chmod($fullpath, $mode);
} else {
$this->chmod($fullpath, $mode, true);
}
}
closedir($dir);
@chmod($path, $mode);
}
function extract($zip_name, $to)
{
if (substr($to, -1) != '/') {
$to .= '/';
}
if (!is_dir($to)) {
@mkdir($to,0777);
@chmod($to,0777);
}
$zip = fopen($zip_name, 'rb');
$size = filesize($zip_name);
fseek($zip, $size - 22);
// End of central dir record
$data = unpack('Vsig/vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcommentsize', fread($zip, 22));
rewind($zip);
for ($i = 0; $i < $data['entries']; $i++)
{
// Local file header
$header = unpack('Vsig/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', fread($zip, 30));
$header['filename'] = fread($zip, $header['filename_len']);
if ($header['mdate'] && $header['mtime']) {
$hour = ($header['mtime'] & 0xF800) >> 11;
$minute = ($header['mtime'] & 0x07E0) >> 5;
$seconde = ($header['mtime'] & 0x001F) * 2;
$year = (($header['mdate'] & 0xFE00) >> 9) + 1980;
$month = ($header['mdate'] & 0x01E0) >> 5;
$day = $header['mdate'] & 0x001F;
$header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
} else {
$header['mtime'] = time();
}
if ((substr($header['filename'], -1) == '/') || ($header['filename'] == '.') || ($header['filename'] == '..')) {
if (!is_dir($to . $header['filename'])) {
mkdir($to . $header['filename']);
$this->chmod($to . $header['filename'],0777);
}
continue;
}
$this->chmod($to . $header['filename'], 0777);
$fp = fopen($to . $header['filename'], 'wb');
while ($header['compressed_size'])
{
if ($header['compressed_size'] < 2048) {
$read_size = $header['compressed_size'];
} else {
$read_size = 2048;
}
$binary_data = pack('a' . $read_size, fread($zip, $read_size));
fwrite($fp, $binary_data, $read_size);
$header['compressed_size'] -= $read_size;
}
fclose($fp);
touch($to . $header['filename'], $header['mtime']);
}
fclose($zip);
}
function write_zip($destination)
{
$fp = fopen($destination, 'wb');
fwrite($fp, $this->get_file());
fclose($fp);
}
}
?>