Thursday 28 June 2012

Captcha in simple php


When we build websites with forms their emerge situation where we want to include captcha to prevent it from spammers. here iam including a captcha file which can be used in simple php:-
create a catptcha.php and include the following code in this:-
<?php

session_start();
$text = rand(10000,99999);
$_SESSION["vercode"] = $text;
$height = 25;
$width = 65;

$image_p = imagecreate($width, $height);
$black = imagecolorallocate($image_p, 0, 0, 0);
$white = imagecolorallocate($image_p, 255, 255, 255);
$font_size = 14;

imagestring($image_p, $font_size, 5, 5, $text, $white);
imagejpeg($image_p, null, 80);
?>
and now for calling this capcha in your website call like this:-
<img src="captcha.php" alt="captchaimage">

and now for getting value of this captcha to check get the value by this:-
$text=$_SESSION["vercode"] ;
unset($_SESSION["vercode"]);
and now get the captcha entered by user by
$captcha        = $_POST['captcha'];

now check the values and do validation.

Captcha in cakephp



When we build websites with forms their emerge situatiion where we want to include captcha to prevent it from spammers. here iam including a captcha controller which can be used in cakephp.
<?php

class CaptchaController extends AppController{

public $uses = array('SessionManager','Validator','Captcha','Flash');
public $components=array('Session');

function init(){
$this->SessionManager->Session=$this->Session;
}
function index(){
$this->init();
/*
$text = $this->SessionManager->get('captchaText');
$height = 25;
$width = 65;

$image_p = imagecreate($width, $height);
$black = imagecolorallocate($image_p, 0, 0, 0);
$white = imagecolorallocate($image_p, 255, 255, 255);
$font_size = 14;
ob_start();
imagestring($image_p, $font_size, 5, 5, $text, $white);
imagejpeg($image_p, null, 80);
exit;*/

$urlRoot=Router::url('/',false);
$image_width = 120;
$image_height = 35;
$characters_on_image = 6;
$dir = Configure::read('FondDir');
$font = $dir.'/monofont.ttf';
$possible_letters = '23456789bcdfghjkmnpqrstvwxyz';
$random_dots = 0;
$random_lines = 20;
$captcha_text_color="0x142864";
$captcha_noice_color = "0x142864";
$code = '';
$i = 0;
ob_start();
while ($i < $characters_on_image) {
$code .= substr($possible_letters, mt_rand(0, strlen($possible_letters)-1), 1);
$i++;
}
$this->SessionManager->set('captcha',$code);
$this->Session->write('captcha',$code);
$font_size = $image_height * 0.75;
$image      = @imagecreate($image_width, $image_height);


/* setting the background, text and noise colours here */
$background_color = imagecolorallocate($image, 255, 255, 255);

$arr_text_color = $this->hexrgb($captcha_text_color);
$text_color = imagecolorallocate($image, $arr_text_color['red'],
$arr_text_color['green'], $arr_text_color['blue']);

$arr_noice_color = $this->hexrgb($captcha_noice_color);
$image_noise_color = imagecolorallocate($image, $arr_noice_color['red'],
$arr_noice_color['green'], $arr_noice_color['blue']);


/* generating the dots randomly in background */
for( $i=0; $i<$random_dots; $i++ ) {
imagefilledellipse($image, mt_rand(0,$image_width),
mt_rand(0,$image_height), 2, 3, $image_noise_color);
}


/* generating lines randomly in background of image */
for( $i=0; $i<$random_lines; $i++ ) {
imageline($image, mt_rand(0,$image_width), mt_rand(0,$image_height),
mt_rand(0,$image_width), mt_rand(0,$image_height), $image_noise_color);
}


/* create a text box and add 6 letters code in it */
$textbox = imagettfbbox($font_size, 0, $font, $code);
$x = ($image_width - $textbox[4])/2;
$y = ($image_height - $textbox[5])/2;
imagettftext($image, $font_size, 0, $x, $y, $text_color, $font , $code);


/* Show captcha image in the page html page */
header('Content-Type: image/jpeg');// defining the image type to be shown in browser widow
imagejpeg($image);//showing the image
imagedestroy($image);//destroying the image instance


exit;
}

function hexrgb ($hexstr)
{
 $int = hexdec($hexstr);

 return array("red" => 0xFF & ($int >> 0x10),
  "green" => 0xFF & ($int >> 0x8),
  "blue" => 0xFF & $int);
}


}

?>
and after including this in your controller page .. so after that you have to call captchja somewhere so you can call like this
img src="<?php echo  $urlRoot;?>captcha/" alt="Captcha Security Code" class="captcha" />


and in the action file where you want to get this value,simply call like this
$captcha = $this->SessionManager->get('captcha');

and you can check the captcha value with the user entered captcha value and can submit the form..

Inserting images from customized usergallery in tinymiceeditor


when developing a large web interface site, there araise situation where we had to use certain text editors in our forms. generally when our project is something like blogs, we have to insert images from user gallery itself. but in tiny mice editor it doesn't have feautre for adding images from our customized gallery by default. there is lot of plugins available for doing this in tiny miceeditor,but it is costly. so we have to include it by externally. so here iam explaining of including an image inserter for tinymice editor in cakephp. first you downlad the tiny mice editor from their site and include in your  app/webroot/js folder. then create a form like this:-

<a href="javascript:void(0)" id="imageButton" class="imageButton" onclick="return openGallery(this);">INSERT IMAGE</a>
<div class="col150">Content:- <span class="required">*</span></div>
<div class="col30 txtCenter">:</div></div>
<div class="rows"><textarea name="postcontent" tabindex="6" maxlength="90" id="postcontent">
</textarea></div>

please include the following js code under your form:-
<script type="text/javascript">
var urlRoot='<?php echo $urlRoot;  ?>';
function openGallery(obj){// this is the function called by the insert image link

contentBox(obj);// sets the content box
showImages(1); // calls the function show images
return false;
}

function contentBox(obj){

var id = obj.id;
var it = $('#'+id);
var pos = it.position();
if($("#editLayerBox")){
$("#editLayerBox").remove();
}
var div='';
var elim = 'editLayerBox';
div='<div id="editLayerBox" class="editLayerBox"></div>';
$(document.body).append(div);
//$("#"+elim).css("position","fixed");
var left=Number(pos.left)-140;
var top = Number(pos.top)-500;
    $("#"+elim).css("top", pos.top+'px');
    $("#"+elim).css("left",left+'px');
$("#"+elim).html('Loading');
}
function showImages(start){// it calls an action written in the userreg controller called image gallery.this function will be explained later

$.post(urlRoot+'userreg/imagegallery/',{start:start},function(data){
$("#editLayerBox").html(data);
});
}
function insertImage(){// function to insert image to the tiny mce editor
var width = $('#imgWidth').val();
var height = $('#imgHeight').val();
var image = $('#imgSelected').val();
var path = $('#imgPath').val();

if(image==''){
alert("You did't select any picture !");
}else{
var html='<img src="'+path+''+image+'"  width="'+width+'" height="'+height+'" class="innerImageFile"  />';

tinyMCE.execCommand('mceInsertContent',false,html);
closeEditBox();
}
}
function fillSize(w,h,id,t){// setting the file sizesand image selected
$('#imgWidth').val(w);
$('#imgHeight').val(h);

$('#imgSelected').val(id);
}
function closeEditBox(){// closing the edit box
if($("#editLayerBox")){
$("#editLayerBox").remove();
}
return false;
}
</script>

Here you see that some classes are called in js function .don't forget to include those styles in css. because the image should be displayed in a popup box and it completely depends on tghe css you include. just add these lines to css:-
.editLayerBox{ width:680px; height:auto;background:#FFFFFF; position:absolute; left:0px; top:0px; text-align:center;}
.layerOuter{ height:auto; overflow:hidden; border:1px solid #999999; padding:5px; text-align:left;}
.layerOuter .topRow{  height:24px; line-height:24px ; border:1px solid #f0f0f0; border-top:0px; padding:2px;}
.layerOuter .topRow .close{ border:0px; width:20px; height:20px; background:url(../img/close.jpg) no-repeat; float:right; border:1px solid #f0f0f0;}
.layerOuter .contBox{ height:auto; overflow:hidden; margin:2px 0px; padding:5px; border:1px solid #f0f0f0;}
.editorHelper{ height:25px;padding:3px 0px; border:1px dotted #e0e0e0; background:#FFFFFF;}
.editorHelper .imageButton{ height:24px; line-height:24px; padding-left:30px; float:left; font-weight:500; background:url(../img/icon-gallery.jpg) no-repeat #FFFFFF; margin-left:10px; border:1px dotted #e0e0e0;}
.editorHelper .linkButton{ height:24px; line-height:24px; padding-left:30px; float:left; font-weight:500; background:url(../img/icon-links.jpg) no-repeat #FFFFFF; margin-left:10px;}
.editorHelper a{ color:#FF0000; font-weight:600; border:1px dotted #e0e0e0; padding:0px 10px


now it's time to talk about the action and view fo the image displaying. just include this code in your usercontroller and customize the path as you required. here is the imagegallery action in usercontroller:-
function imagegallery(){
$this->init();
$this->layout='layer';
$data = $this->data;
$page = $data['start'];



$this->set('userid',$user_id);
$urlRoot=Router::url('/',false);
$this->set('urlRoot',$urlRoot);
$limit = 10;
$order = 'Image.image_id ASC';
$cond = array('Album.user_id'=>$user_id);
$this->Image->belongsTo=array('Album'=>array('className'=>'Album','foreignKey'=>'album_id'));
$total = $this->Image->find('count',array('conditions'=>$cond));
$records = $this->Image->find('all',array('conditions'=>$cond,'order'=>$order,'page'=>$page,'limit'=>$limit));

$cnt = ceil($total/$limit);
$pages = $this->Pages->getPages($page,$cnt,$limit);
$next = $this->Pages->getNext($page,$cnt,$limit);
$prev = $this->Pages->getPrev($page,$cnt,$limit);
$first = $this->Pages->getFirst($page,$cnt,$limit);
$last = $this->Pages->getLast($page,$cnt,$limit);
$uploadDir =WWW_APP_MAIN_ROOT.'/store/';
         $uploadDir.='user-'.$user_id.'/gallery/';//here you have to set the path of file
         $this->set('filepath',$uploadDir);
          $uploadDir1 =$url.'/store/';
         $uploadDir1.='user-'.$user_id.'/gallery/';
         $this->set('filepath2',$uploadDir1);

$mediaBaseDir = Configure::read('Albumdir');
$uploadDir=$mediaBaseDir;

$this->set('pages',$pages);
$this->set('first',$first);
$this->set('last',$last);
$this->set('next',$next);
$this->set('prev',$prev);
$this->set('page',$page);
$this->set('limit',$limit);
$this->set('total',$total);
$this->set('records',$records);
$this->set('util',$this->Utility);
$this->set('rootUrl',$this->rootUrl);
$this->set('uploadDir',$uploadDir);
}
next is the view file . here include this code in your imagegallery.ctp
<?php
 $rootUrl=Router::url('/',false);
 $filepath1='http://'.$_SERVER['SERVER_NAME'].$filepath2;
?>
<div class="rows">

<ul class="imagesLayer">

<?php


for($i=0;$i<count($records);$i++){

$imageSize = getimagesize($filepath.$records[$i]['Image']['imagename']);
$w = $imageSize[0];
$h = $imageSize[1];

?>
<li>
<div class="row1">
<img src="<?php echo $urlRoot;?>thumb2/album/?uid=<?php echo $userid;?>&img=<?php echo $records[$i]['Image']['imagename'];?>&width=140&height=100"  alt="THUMB" title="" />
</div>
<div class="row2">
<input type="radio" name="radImage" value="<?php echo $records[$i]['Image']['imagename'];?>" onclick="fillSize('<?php echo $w;?>','<?php echo $h;?>','<?php echo $records[$i]['Image']['imagename'];?>','<?php echo addslashes(htmlentities($records[$i]['Image']['imagename']));?>')" /> SELECT IMAGE
</div>

</li>
<?php
}
?>
</ul>
<?php
if($total>0){
?>
<div class="rows imgSelectionRow">
Width <input type="text" size="10" id="imgWidth" value="120" />
Height <input type="text" size="10" id="imgHeight" value="120" />
<input type="button" name="imgAdd" class="button" value="ADD IMAGE" onclick="insertImage();" />
<input type="hidden" name="imgSelected" id="imgSelected" value="" />
<input type="hidden" name="imgPath" id="imgPath" value="<?php echo $filepath1;?>" />
</div>

<ul class="pagination">
<li>
<a href="javascript:void();" onclick="return showImages('<?php echo $first;?>')">First</a>
<a href="javascript:void();" onclick="return showImages('<?php echo $prev;?>')">Prev</a>
<?php
for($i=0;$i<count($pages);$i++){

?>
<a href="javascript:void();" onclick="return showImages('<?php echo $pages[$i]?>')" <?php if($page==$pages[$i]){?> class="visited"<?php }?>><?php echo $pages[$i]?></a>
<?php
}
?>
<a href="javascript:void();" onclick="return showImages('<?php echo $next;?>')">Next</a>
<a href="javascript:void();" onclick="return showImages('<?php echo $last;?>')">Last</a>
</li>
<li>
Total : <?php echo $total;?> records
</li>
</ul>
<?php } else{
?>
<span class="required">Sorry no records found !</span>
<?php
}?>
</div>
Hope you suceed in it.................

Submiting data with jquery to database without page reloading




When working with large number of forms,the main problem araises will be the time required for submitting a data to server and returing result from server which takes a large time. so it makes our site more slower.IIn this modern world where people want things to be done just in less than a second. so here iam explaining how we can submit a page without any page reloading. You know that as php is a sever side scripting language we cannot do without a refresh using php. but with the help of jquery we can do it in a better way.so the main thing is that you should have the jquery library included in your page then do like this what i explain:-

consider a form like tihis:-
<form action="" method="post" enctype="multipart/form-data">

<input type="text" name="postname" size="25" maxlength="90" tabindex="2" value="" id="postname" /></div>

<label class="error" for="title" id="postname_error">This field is required.</label>

Conent:-<textarea name="postcontent" tabindex="6" maxlength="90" id="postcontent">

</textarea>
<label class="error" for="content" id="postcontent_error">This field is required.</label>
<textarea name="tags" tabindex="6" maxlength="90" rows="5" cols="40" id="tags">

</textarea>
<label class="error" for="tags" id="tags_error">This field is required.</label>
status:-<input type="radio" id="publish1" name="radPublish" value="0" tabindex="12"/>
à´µേà´£ം <input type="radio" name="radPublish" id="publish2" value="1" checked="checked"  tabindex="13"/>
<div class="col350"><input type="submit" class="button" name="saveForm" value="Save" />
</form>
make sure that form action is specified as null and all the fields hae id's corresponding to it. so we can retrieve the values of this fields using id by javascript.
so then please add the following js code under the file:-

<script type='text/javascript'>
$(function() {;
  $('.error').hide();// hiding all error labels
  $('input.text-input').css({backgroundColor:"#FFFFFF"});
  $('input.text-input').focus(function(){
    $(this).css({backgroundColor:"#FFDDAA"});
  });
  $('input.text-input').blur(function(){
    $(this).css({backgroundColor:"#FFFFFF"});
  });

  $(".button").click(function() {// this activates when class button is clicked
// validate and process form
// first hide any error messages
    $('.error').hide();
var postcontent =  $("input#postcontent").val();//getting value of post content

 var postname = $("input#postname").val();//getting value of postname
if (postname == "") {
      $("label#postname_error").show();
      $("input#postname").focus();
      return false;
    }

var tags = $("#tags").val();//getting value of tags
if (tags == "") {
      $("label#tags_error").show();
      $("#tags").focus();
      return false;
    }


var publish=0;
  if(document.getElementById('publish1').checked){// getting whether published or not
    publish=0;
  }else{
     publish=1;
  }
 


var dataString = 'postname='+ postname + '&postcontent=' + postcontent + '&tags=' + tags + '&publish=' + publish ;// concatinating to datasting

$.ajax({// ajax method of post and specify whether this data to go in the argument url .
      type: "POST",
      url: urlRoot+"user/submitposts",
      data: dataString,
      success: function() {
        $('#contact_form1').html("<div id='message'></div>");// if posted success then it will give a message like this
        $('#message').html("<h2><span style='color:black; background:green'>Post created!</span></h2>")
       
        .hide()
        .fadeIn(1500, function() {
         $('#MyDynamicDiv').load(urlRoot'+'allposts');//reloading page
          $('#message').append("");
        });
      }
     });
    return false;
});
});
// runOnLoad(function(){
//   $("input#name").select().focus();
// });

</script>
so after this it's time to add posts to databse so in the submit post.php.. write like this
function submitposts(){
$this->init();
$this->layout ='';
$postname=trim(strip_tags($_POST['postname']));

$postcontent=trim($_POST['postcontent']);
$tags=trim(strip_tags($_POST['tags']));
$publish=$_POST['publish'];
$postid=$_POST['blogid1'];
$userid1=$_POST['userid1'];
$tdate=date('y-m-d h-i-s');
$year=date("Y");
$month=date("M");
$save['Post']=array('blog_id'=>$postid,'name'=>$postname,'content'=>$postcontent,'tags'=>$tags,'published'=>$publish,'date_add'=>$tdate,'views'=>0,'month'=>$month,'year'=>$year);
$f=$this->Post->save($save);
exit;



}
here it will be saved in database

Wednesday 13 June 2012

Generating thumbnail in simple php

When we are doing a website with gallery options,their araise situation where we want to generate thumbnails of images. This is neccessry because it helps in loading images fast and also wecvan specify the size of the image we want to see. just include this code in your project. copy the below code and paste in a file named thumb.php.
<?php

$site_config['document_root'] = $_SERVER['DOCUMENT_ROOT'].'/dadmin/';
$thumb_size = 128; //all thumbnails are this maximum width or height if not specified via get
$site_config['absolute_uri']=str_replace('///','//',str_replace('thumb.php?'.$_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI']));
$site_config['path_thumbnail']=$site_config['absolute_uri'].'/cache/'; //where to cache thumbnails on the server, relative to the DOCUMENT_ROOT
$image_error=$site_config['document_root'].$site_config['absolute_uri'].'/images/icons/image_error.png'; // used if no image could be found, or a gif image is specified

$thumb_size_x = 0;
$thumb_size_y = 0;

# Define quality of image
if (@$_GET["quality"]<>0) {
$quality = $_GET["quality"];
} else {
$quality = 80;
}

# Define size of image (maximum width or height)- if specified via get.
if (@$_GET["size"]<>0) {
$thumb_size=intval($_GET["size"]);
}
if (intval(@$_GET["sizex"])>0)
{
$thumb_size_x=intval($_GET["sizex"]);
if (intval(@$_GET["sizey"])>0)
{
$thumb_size_y=intval($_GET["sizey"]);
} else {
$thumb_size_y=$thumb_size_x;
}
}

if (file_exists($_GET['file']))
{
$filename=$_GET['file'];
} else {
$filename=str_replace('//','/',$site_config['document_root'].$site_config['absolute_uri'].'/'.$_GET["file"]);
}

# If calling an external image, remove document_root
if (substr_count($filename, "http://")>0)

{
$filename=str_replace($site_config['document_root'].$site_config['absolute_uri'].'/','',$filename);
}

$filename=str_replace("\'","'",$filename);
$filename=rtrim($filename);
$filename=str_replace("//","/",$filename);
$fileextension=substr($filename, strrpos ($filename, ".") + 1);

$cache_file=str_replace('//','/',$site_config['document_root'].$site_config['path_thumbnail'].md5($filename.@$thumb_size.@$thumb_size_x.@$thumb_size_y.@$quality).'.'.$fileextension);

# remove cache thumbnail?
if (@$_GET['nocache']==1)
{
if (file_exists($cache_file))
{
#remove the cached thumbnail
unlink($cache_file);
}
}

if ((file_exists($cache_file)) && (@filemtime($cache_file)>@filemtime($filename)))
{
header('Content-type: image/'.$fileextension);
header("Expires: Mon, 26 Jul 2030 05:00:00 GMT");
header('Content-Disposition: inline; filename='.str_replace('/','',md5($filename.$thumb_size.$thumb_size_x.$thumb_size_y.$quality).'.'.$fileextension));
echo (join('', file( $cache_file )));
exit; # no need to create thumbnail - it already exists in the cache
}

# determine php and gd versions
$ver=intval(str_replace(".","",phpversion()));
if ($ver>=430)
{
$gd_version=@gd_info();
}

# define the right function for the right image types
if (!$image_type_arr = @getimagesize($filename))
{
header('Content-type: image/png');
if(@$_GET['noerror'])
{
exit;
} else {
echo (join('', file( $site_config['document_root'].$image_error )));
exit;
}
}
$image_type=$image_type_arr[2];

switch ($image_type)
{
case 2: # JPG
if (!$image = @imagecreatefromjpeg ($filename))
{
# not a valid jpeg file
$image = imagecreatefrompng ($image_error);
$file_type="png";
if (file_exists($cache_file))
{
# remove the cached thumbnail
unlink($cache_file);
}
}
break;

case 3: # PNG
if (!$image = @imagecreatefrompng ($filename))
{
# not a valid png file
$image = imagecreatefrompng ($image_error);
$file_type="png";
if (file_exists($cache_file))
{
# remove the cached thumbnail
unlink($cache_file);
}
}
break;

case 1: # GIF
if (!$image = @imagecreatefromgif ($filename))
{
# not a valid gif file
$image = imagecreatefrompng ($image_error);
$file_type="png";
if (file_exists($cache_file))
{
# remove the cached thumbnail
unlink($cache_file);
}
}
break;
default:
$image = imagecreatefrompng($image_error);
break;

}

# define size of original image
$image_width = imagesx($image);
$image_height = imagesy($image);

# define size of the thumbnail
if (@$thumb_size_x>0)
{
# define images x AND y
$thumb_width = $thumb_size_x;
$factor = $image_width/$thumb_size_x;
$thumb_height = intval($image_height / $factor);
if ($thumb_height>$thumb_size_y)
{
$thumb_height = $thumb_size_y;
$factor = $image_height/$thumb_size_y;
$thumb_width = intval($image_width / $factor);
}
} else {
# define images x OR y
$thumb_width = $thumb_size;
$factor = $image_width/$thumb_size;
$thumb_height = intval($image_height / $factor);
if ($thumb_height>$thumb_size)
{
$thumb_height = $thumb_size;
$factor = $image_height/$thumb_size;
$thumb_width = intval($image_width / $factor);
}
}

# create the thumbnail
if ($image_width < 4000) //no point in resampling images larger than 4000 pixels wide - too much server processing overhead - a resize is more economical
{
if (substr_count(strtolower($gd_version['GD Version']), "2.")>0)
{
//GD 2.0
$thumbnail = ImageCreateTrueColor($thumb_width, $thumb_height);
imagecopyresampled($thumbnail, $image, 0, 0, 0, 0, $thumb_width, $thumb_height, $image_width, $image_height);
} else {
//GD 1.0
$thumbnail = imagecreate($thumb_width, $thumb_height);
imagecopyresized($thumbnail, $image, 0, 0, 0, 0, $thumb_width, $thumb_height, $image_width, $image_height);
}
} else {
if (substr_count(strtolower($gd_version['GD Version']), "2.")>0)
{
# GD 2.0
$thumbnail = ImageCreateTrueColor($thumb_width, $thumb_height);
imagecopyresized($thumbnail, $image, 0, 0, 0, 0, $thumb_width, $thumb_height, $image_width, $image_height);
} else {
# GD 1.0
$thumbnail = imagecreate($thumb_width, $thumb_height);
imagecopyresized($thumbnail, $image, 0, 0, 0, 0, $thumb_width, $thumb_height, $image_width, $image_height);
}
}

# insert string
if (@$_GET['tag']<>"")
{
$font=1;
$string= $_GET['tag'];
$white = imagecolorallocate ($thumbnail, 255, 255, 255);
$black = imagecolorallocate ($thumbnail, 0, 0, 0);
imagestring ($thumbnail, $font, 3, $thumb_height-9, $string, $black);
imagestring ($thumbnail, $font, 2, $thumb_height-10, $string, $white);
}

switch ($image_type)
{
case 2: # JPG
header('Content-type: image/jpeg');
header('Content-Disposition: inline; filename='.str_replace('/','',md5($filename.$thumb_size.$thumb_size_x.$thumb_size_y.$quality).'.jpeg'));
@imagejpeg($thumbnail,$cache_file, $quality);
imagejpeg($thumbnail,'',$quality);

break;
case 3: # PNG
header('Content-type: image/png');
header('Content-Disposition: inline; filename='.str_replace('/','',md5($filename.$thumb_size.$thumb_size_x.$thumb_size_y.$quality).'.png'));
@imagepng($thumbnail,$cache_file);
imagepng($thumbnail);
break;

case 1: # GIF
if (function_exists('imagegif'))
{
header('Content-type: image/gif');
header('Content-Disposition: inline; filename='.str_replace('/','',md5($filename.$thumb_size.$thumb_size_x.$thumb_size_y.$quality).'.gif'));
@imagegif($thumbnail,$cache_file);
imagegif($thumbnail);
} else {
header('Content-type: image/jpeg');
header('Content-Disposition: inline; filename='.str_replace('/','',md5($filename.$thumb_size.$thumb_size_x.$thumb_size_y.$quality).'.jpg'));
@imagejpeg($thumbnail,$cache_file);
imagejpeg($thumbnail);
}
break;
}

//clear memory
imagedestroy ($image);
imagedestroy ($thumbnail);

?>

and now in the place where you want to view thumbnail image...put this code
<a href="../uploads/<?php echo $records[$i]['img_loc'];?>" target="_blank">
<img src="thumb.php?file=../uploads/<?php echo $records[$i]['img_loc'];?>&size=50px" alt="<?php echo $records[$i]["img_loc"];?>" class="thumb"></a>

specify image and size here...

Tuesday 12 June 2012

Extracting zipped file in cakephp

Everyone is familiar with extraction of zip files.Here iam explaining about extracting zip files in php. for this we need a library file called PCLZIP.  below is the code copy it and place in a file named PclZip.php and put it in /app/model
<?php


// --------------------------------------------------------------------------------
// PhpConcept Library - Zip Module 1.3
// --------------------------------------------------------------------------------
// License GNU/LGPL - Vincent Blavet - January 2003
// http://www.phpconcept.net
// --------------------------------------------------------------------------------
//
// Presentation :
// PclZip is a PHP library that manage ZIP archives.
// So far tests show that archives generated by PclZip are readable by
// WinZip application and other tools.
//
// Description :
// See readme.txt and http://www.phpconcept.net
//
// Warning :
// This library and the associated files are non commercial, non professional
// work.
// It should not have unexpected results. However if any damage is caused by
// this software the author can not be responsible.
// The use of this software is at the risk of the user.
//
// --------------------------------------------------------------------------------
// $Id: pclzip.lib.php,v 1.13 2003/02/07 20:44:09 vblavet Exp $
// --------------------------------------------------------------------------------

// ----- Constants
define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );

// ----- Error configuration
// 0 : PclZip Class integrated error handling
// 1 : PclError external library error handling. By enabling this
// you must ensure that you have included PclError library.
// [2,...] : reserved for futur use
define( 'PCLZIP_ERROR_EXTERNAL', 0 );

// ----- Optional static temporary directory
// By default temporary files are generated in the script current
// path.
// If defined :
// - MUST BE terminated by a '/'.
// - MUST be a valid, already created directory
// Samples :
// define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
// define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
define( 'PCLZIP_TEMPORARY_DIR', '' );

// --------------------------------------------------------------------------------
// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
// --------------------------------------------------------------------------------

// ----- Global variables
$g_pclzip_version = "1.3";

// ----- Error codes
// -1 : Unable to open file in binary write mode
// -2 : Unable to open file in binary read mode
// -3 : Invalid parameters
// -4 : File does not exist
// -5 : Filename is too long (max. 255)
// -6 : Not a valid zip file
// -7 : Invalid extracted file size
// -8 : Unable to create directory
// -9 : Invalid archive extension
// -10 : Invalid archive format
// -11 : Unable to delete file (unlink)
// -12 : Unable to rename file (rename)
// -13 : Invalid header checksum
// -14 : Invalid archive size
define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
define( 'PCLZIP_ERR_MISSING_FILE', -4 );
define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );

// ----- Options values
define( 'PCLZIP_OPT_PATH', 77001 );
define( 'PCLZIP_OPT_ADD_PATH', 77002 );
define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
define( 'PCLZIP_OPT_SET_CHMOD', 77005 );

// ----- Call backs values
define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
define( 'PCLZIP_CB_PRE_ADD', 78003 );
define( 'PCLZIP_CB_POST_ADD', 78004 );
/* For futur use
define( 'PCLZIP_CB_PRE_LIST', 78005 );
define( 'PCLZIP_CB_POST_LIST', 78006 );
define( 'PCLZIP_CB_PRE_DELETE', 78007 );
define( 'PCLZIP_CB_POST_DELETE', 78008 );
*/

// --------------------------------------------------------------------------------
// Class : PclZip
// Description :
// PclZip is the class that represent a Zip archive.
// The public methods allow the manipulation of the archive.
// Attributes :
// Attributes must not be accessed directly.
// Methods :
// PclZip() : Object creator
// create() : Creates the Zip archive
// listContent() : List the content of the Zip archive
// extract() : Extract the content of the archive
// properties() : List the properties of the archive
// --------------------------------------------------------------------------------
class PclZip
{
// ----- Filename of the zip file
var $zipname = '';

// ----- File descriptor of the zip file
var $zip_fd = 0;

// ----- Internal error handling
var $error_code = 1;
var $error_string = '';

// --------------------------------------------------------------------------------
// Function : PclZip()
// Description :
// Creates a PclZip object and set the name of the associated Zip archive
// filename.
// Note that no real action is taken, if the archive does not exist it is not
// created. Use create() for that.
// --------------------------------------------------------------------------------
function PclZip($p_zipname)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::PclZip', "zipname=$p_zipname");

// ----- Tests the zlib
if (!function_exists('gzopen'))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 1, "zlib extension seems to be missing");
die('Abort '.basename(__FILE__).' : Missing zlib extensions');
}

// ----- Set the attributes
$this->zipname = $p_zipname;
$this->zip_fd = 0;

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 1);
return;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function :
// create($p_filelist, $p_add_dir="", $p_remove_dir="")
// create($p_filelist, $p_option, $p_option_value, ...)
// Description :
// This method supports two different synopsis. The first one is historical.
// This method creates a Zip Archive. The Zip file is created in the
// filesystem. The files and directories indicated in $p_filelist
// are added in the archive. See the parameters description for the
// supported format of $p_filelist.
// When a directory is in the list, the directory and its content is added
// in the archive.
// In this synopsis, the function takes an optional variable list of
// options. See bellow the supported options.
// Parameters :
// $p_filelist : An array containing file or directory names, or
// a string containing one filename or one directory name, or
// a string containing a list of filenames and/or directory
// names separated by spaces.
// $p_add_dir : A path to add before the real path of the archived file,
// in order to have it memorized in the archive.
// $p_remove_dir : A path to remove from the real path of the file to archive,
// in order to have a shorter path memorized in the archive.
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir
// is removed first, before $p_add_dir is added.
// Options :
// PCLZIP_OPT_ADD_PATH :
// PCLZIP_OPT_REMOVE_PATH :
// PCLZIP_OPT_REMOVE_ALL_PATH :
// PCLZIP_CB_PRE_ADD :
// PCLZIP_CB_POST_ADD :
// Return Values :
// 0 on failure,
// The list of the added files, with a status of the add action.
// (see PclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
// function create($p_filelist, $p_add_dir="", $p_remove_dir="")
function create($p_filelist /*, options */)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::create', "filelist='$p_filelist', ...");
$v_result=1;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Set default values
$v_options = array();
$v_add_path = "";
$v_remove_path = "";
$v_remove_all_path = false;

// ----- Look for variable options arguments
$v_size = func_num_args();
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");

// ----- Look for arguments
if ($v_size > 1) {
// ----- Get the arguments
$v_arg_list = &func_get_args();

// ----- Remove form the options list the first argument
array_shift($v_arg_list);
$v_size--;

// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");

// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (PCLZIP_OPT_REMOVE_PATH => 'optional',
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
PCLZIP_OPT_ADD_PATH => 'optional',
PCLZIP_CB_PRE_ADD => 'optional',
PCLZIP_CB_POST_ADD => 'optional' ));
if ($v_result != 1) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}

// ----- Set the arguments
if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
$v_add_path = $v_options[PCLZIP_OPT_ADD_PATH];
}
if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
$v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
}
if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
$v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
}
}

// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");

// ----- Get the first argument
$v_add_path = $v_arg_list[0];

// ----- Look for the optional second argument
if ($v_size == 2) {
$v_remove_path = $v_arg_list[1];
}
else if ($v_size > 2) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return 0;
}
}
}

// ----- Trace
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "add_path='$v_add_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_all_path?'true':'false')."'");

// ----- Look if the $p_filelist is really an array
$p_result_list = array();
if (is_array($p_filelist))
{
// ----- Call the create fct
$v_result = $this->privCreate($p_filelist, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
}

// ----- Look if the $p_filelist is a string
else if (is_string($p_filelist))
{
// ----- Create a list with the elements from the string
$v_list = explode(" ", $p_filelist);

// ----- Call the create fct
$v_result = $this->privCreate($v_list, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
}

// ----- Invalid variable
else
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
$v_result = PCLZIP_ERR_INVALID_PARAMETER;
}

if ($v_result != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
return $p_result_list;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function :
// add($p_filelist, $p_add_dir="", $p_remove_dir="")
// add($p_filelist, $p_option, $p_option_value, ...)
// Description :
// This method supports two synopsis. The first one is historical.
// This methods add the list of files in an existing archive.
// If a file with the same name already exists, it is added at the end of the
// archive, the first one is still present.
// If the archive does not exist, it is created.
// Parameters :
// $p_filelist : An array containing file or directory names, or
// a string containing one filename or one directory name, or
// a string containing a list of filenames and/or directory
// names separated by spaces.
// $p_add_dir : A path to add before the real path of the archived file,
// in order to have it memorized in the archive.
// $p_remove_dir : A path to remove from the real path of the file to archive,
// in order to have a shorter path memorized in the archive.
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir
// is removed first, before $p_add_dir is added.
// Options :
// PCLZIP_OPT_ADD_PATH :
// PCLZIP_OPT_REMOVE_PATH :
// PCLZIP_OPT_REMOVE_ALL_PATH :
// PCLZIP_CB_PRE_ADD :
// PCLZIP_CB_POST_ADD :
// Return Values :
// 0 on failure,
// The list of the added files, with a status of the add action.
// (see PclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
// function add($p_filelist, $p_add_dir="", $p_remove_dir="")
function add($p_filelist /* options */)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::add', "filelist='$p_filelist', ...");
$v_result=1;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Set default values
$v_options = array();
$v_add_path = "";
$v_remove_path = "";
$v_remove_all_path = false;

// ----- Look for variable options arguments
$v_size = func_num_args();
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");

// ----- Look for arguments
if ($v_size > 1) {
// ----- Get the arguments
$v_arg_list = &func_get_args();

// ----- Remove form the options list the first argument
array_shift($v_arg_list);
$v_size--;

// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");

// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (PCLZIP_OPT_REMOVE_PATH => 'optional',
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
PCLZIP_OPT_ADD_PATH => 'optional',
PCLZIP_CB_PRE_ADD => 'optional',
PCLZIP_CB_POST_ADD => 'optional' ));
if ($v_result != 1) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}

// ----- Set the arguments
if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
$v_add_path = $v_options[PCLZIP_OPT_ADD_PATH];
}
if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
$v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
}
if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
$v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
}
}

// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");

// ----- Get the first argument
$v_add_path = $v_arg_list[0];

// ----- Look for the optional second argument
if ($v_size == 2) {
$v_remove_path = $v_arg_list[1];
}
else if ($v_size > 2) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return 0;
}
}
}

// ----- Trace
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "add_path='$v_add_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_all_path?'true':'false')."'");

// ----- Look if the $p_filelist is really an array
$p_result_list = array();
if (is_array($p_filelist))
{
// ----- Call the create fct
$v_result = $this->privAdd($p_filelist, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
}

// ----- Look if the $p_filelist is a string
else if (is_string($p_filelist))
{
// ----- Create a list with the elements from the string
$v_list = explode(" ", $p_filelist);

// ----- Call the create fct
$v_result = $this->privAdd($v_list, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
}

// ----- Invalid variable
else
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
$v_result = PCLZIP_ERR_INVALID_PARAMETER;
}

if ($v_result != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
return $p_result_list;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : listContent()
// Description :
// This public method, gives the list of the files and directories, with their
// properties.
// The properties of each entries in the list are (used also in other functions) :
// filename : Name of the file. For a create or add action it is the filename
// given by the user. For an extract function it is the filename
// of the extracted file.
// stored_filename : Name of the file / directory stored in the archive.
// size : Size of the stored file.
// compressed_size : Size of the file's data compressed in the archive
// (without the headers overhead)
// mtime : Last known modification date of the file (UNIX timestamp)
// comment : Comment associated with the file
// folder : true | false
// index : index of the file in the archive
// status : status of the action (depending of the action) :
// Values are :
// ok : OK !
// filtered : the file / dir is not extracted (filtered by user)
// already_a_directory : the file can not be extracted because a
// directory with the same name already exists
// write_protected : the file can not be extracted because a file
// with the same name already exists and is
// write protected
// newer_exist : the file was not extracted because a newer file exists
// path_creation_fail : the file is not extracted because the folder
// does not exists and can not be created
// write_error : the file was not extracted because there was a
// error while writing the file
// read_error : the file was not extracted because there was a error
// while reading the file
// invalid_header : the file was not extracted because of an archive
// format error (bad file header)
// Note that each time a method can continue operating when there
// is an action error on a file, the error is only logged in the file status.
// Return Values :
// 0 on an unrecoverable failure,
// The list of the files in the archive.
// --------------------------------------------------------------------------------
function listContent()
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::listContent', "");
$v_result=1;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Check archive
if (!$this->privCheckFormat()) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}

// ----- Call the extracting fct
$p_list = array();
if (($v_result = $this->privList($p_list)) != 1)
{
unset($p_list);
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
return $p_list;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function :
// extract($p_path="./", $p_remove_path="")
// extract([$p_option, $p_option_value, ...])
// Description :
// This method supports two synopsis. The first one is historical.
// This method extract all the files / directories from the archive to the
// folder indicated in $p_path.
// If you want to ignore the 'root' part of path of the memorized files
// you can indicate this in the optional $p_remove_path parameter.
// By default, if a newer file with the same name already exists, the
// file is not extracted.
//
// If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
// are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
// at the end of the path value of PCLZIP_OPT_PATH.
// Parameters :
// $p_path : Path where the files and directories are to be extracted
// $p_remove_path : First part ('root' part) of the memorized path
// (if any similar) to remove while extracting.
// Options :
// PCLZIP_OPT_PATH :
// PCLZIP_OPT_ADD_PATH :
// PCLZIP_OPT_REMOVE_PATH :
// PCLZIP_OPT_REMOVE_ALL_PATH :
// PCLZIP_CB_PRE_EXTRACT :
// PCLZIP_CB_POST_EXTRACT :
// Return Values :
// 0 or a negative value on failure,
// The list of the extracted files, with a status of the action.
// (see PclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
//function extract($p_path="./", $p_remove_path="")
function extract(/* options */)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip:extract", "");
$v_result=1;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Check archive
if (!$this->privCheckFormat()) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}

// ----- Set default values
$v_options = array();
$v_path = "./";
$v_remove_path = "";
$v_remove_all_path = false;

// ----- Look for variable options arguments
$v_size = func_num_args();
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");

// ----- Look for arguments
if ($v_size > 0) {
// ----- Get the arguments
$v_arg_list = &func_get_args();

// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");

// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (PCLZIP_OPT_PATH => 'optional',
PCLZIP_OPT_REMOVE_PATH => 'optional',
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
PCLZIP_OPT_ADD_PATH => 'optional',
PCLZIP_CB_PRE_EXTRACT => 'optional',
PCLZIP_CB_POST_EXTRACT => 'optional',
PCLZIP_OPT_SET_CHMOD => 'optional' ));
if ($v_result != 1) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}

// ----- Set the arguments
if (isset($v_options[PCLZIP_OPT_PATH])) {
$v_path = $v_options[PCLZIP_OPT_PATH];
}
if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
$v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
}
if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
$v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
}
if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
// ----- Check for '/' in last path char
if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
$v_path .= '/';
}
$v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
}
}

// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");

// ----- Get the first argument
$v_path = $v_arg_list[0];

// ----- Look for the optional second argument
if ($v_size == 2) {
$v_remove_path = $v_arg_list[1];
}
else if ($v_size > 2) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return 0;
}
}
}

// ----- Trace
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");

// ----- Call the extracting fct
$p_list = array();
if (($v_result = $this->privExtract($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) != 1)
{
unset($p_list);
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
return $p_list;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function :
// extractByIndex($p_index, $p_path="./", $p_remove_path="")
// extractByIndex($p_index, [$p_option, $p_option_value, ...])
// Description :
// This method supports two synopsis. The first one is historical.
// This method is doing a partial extract of the archive.
// The extracted files or folders are identified by their index in the
// archive (from 0 to n).
// Note that if the index identify a folder, only the folder entry is
// extracted, not all the files included in the archive.
// Parameters :
// $p_index : A single index (integer) or a string of indexes of files to
// extract. The form of the string is "0,4-6,8-12" with only numbers
// and '-' for range or ',' to separate ranges. No spaces or ';'
// are allowed.
// $p_path : Path where the files and directories are to be extracted
// $p_remove_path : First part ('root' part) of the memorized path
// (if any similar) to remove while extracting.
// Options :
// PCLZIP_OPT_PATH :
// PCLZIP_OPT_ADD_PATH :
// PCLZIP_OPT_REMOVE_PATH :
// PCLZIP_OPT_REMOVE_ALL_PATH :
// PCLZIP_CB_PRE_EXTRACT :
// PCLZIP_CB_POST_EXTRACT :
// Return Values :
// 0 on failure,
// The list of the extracted files, with a status of the action.
// (see PclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
// function extractByIndex($p_index, $p_path="./", $p_remove_path="")
function extractByIndex($p_index /* $options */)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extractByIndex", "index='$p_index', ...");
$v_result=1;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Check archive
if (!$this->privCheckFormat()) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}

// ----- Set default values
$v_options = array();
$v_path = "./";
$v_remove_path = "";
$v_remove_all_path = false;

// ----- Look for variable options arguments
$v_size = func_num_args();
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");

// ----- Look for arguments
if ($v_size > 1) {
// ----- Get the arguments
$v_arg_list = &func_get_args();

// ----- Remove form the options list the first argument
array_shift($v_arg_list);
$v_size--;

// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");

// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (PCLZIP_OPT_PATH => 'optional',
PCLZIP_OPT_REMOVE_PATH => 'optional',
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
PCLZIP_OPT_ADD_PATH => 'optional',
PCLZIP_CB_PRE_EXTRACT => 'optional',
PCLZIP_CB_POST_EXTRACT => 'optional',
PCLZIP_OPT_SET_CHMOD => 'optional' ));
if ($v_result != 1) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}

// ----- Set the arguments
if (isset($v_options[PCLZIP_OPT_PATH])) {
$v_path = $v_options[PCLZIP_OPT_PATH];
}
if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
$v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
}
if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
$v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
}
if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
// ----- Check for '/' in last path char
if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
$v_path .= '/';
}
$v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
}
}

// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");

// ----- Get the first argument
$v_path = $v_arg_list[0];

// ----- Look for the optional second argument
if ($v_size == 2) {
$v_remove_path = $v_arg_list[1];
}
else if ($v_size > 2) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return 0;
}
}
}

// ----- Trace
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "index='$p_index', path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");

// ----- Look if the $p_index is really an integer
if (is_integer($p_index))
{
// ----- Call the extracting fct
if (($v_result = $this->privExtractByIndex($p_list, "$p_index", $v_path, $v_remove_path, $v_remove_all_path, $v_options)) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}
}

// ----- Look if the index is a string
else if (is_string($p_index))
{
// ----- Call the extracting fct
if (($v_result = $this->privExtractByIndex($p_list, $p_index, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}
}

// ----- Invalid variable
else
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type $p_index");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return 0;
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
return $p_list;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : deleteByIndex()
// Description :
// This method delete somes files or folder entries from the zip archive.
// The entries (files or folders) are identified by their index in the
// archive (0-n).
// Note that if the index identify a folder entry, only the folder entry
// is deleted, and not all the files included in the folder.
// Parameters :
// $p_index : A single index (integer) or a string of indexes of files to
// delete. The form of the string is "0,4-6,8-12" with only numbers
// and '-' for range or ',' to separate ranges. No spaces or ';'
// are allowed.
// Return Values :
// 0 on failure,
// The list of the files which are still present in the archive.
// (see PclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
function deleteByIndex($p_index)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::deleteByIndex", "index='$p_index'");
$v_result=1;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Check archive
if (!$this->privCheckFormat()) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}

// ----- Look if the $p_index is really an integer
if (is_integer($p_index))
{
// ----- Call the delete fct
if (($v_result = $this->privDeleteByIndex("$p_index", $p_list)) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}
}

// ----- Look if the index is a string
else if (is_string($p_index))
{
// ----- Call the delete fct
if (($v_result = $this->privDeleteByIndex($p_index, $p_list)) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}
}

// ----- Invalid variable
else
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type $p_index");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return 0;
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
return $p_list;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : properties()
// Description :
// This method gives the properties of the archive.
// The properties are :
// nb : Number of files in the archive
// comment : Comment associated with the archive file
// status : not_exist, ok
// Parameters :
// None
// Return Values :
// 0 on failure,
// An array with the archive properties.
// --------------------------------------------------------------------------------
function properties()
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::properties", "");

// ----- Reset the error handler
$this->privErrorReset();

// ----- Check archive
if (!$this->privCheckFormat()) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}

// ----- Default properties
$v_prop = array();
$v_prop['comment'] = '';
$v_prop['nb'] = 0;
$v_prop['status'] = 'not_exist';

// ----- Look if file exists
if (@is_file($this->zipname))
{
// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), 0);
return 0;
}

// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}

// ----- Close the zip file
$this->privCloseFd();

// ----- Set the user attributes
$v_prop['comment'] = $v_central_dir['comment'];
$v_prop['nb'] = $v_central_dir['entries'];
$v_prop['status'] = 'ok';
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_prop);
return $v_prop;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : duplicate()
// Description :
// This method creates an archive by copying the content of an other one. If
// the archive already exist, it is replaced by the new one without any warning.
// Parameters :
// $p_archive : The filename of a valid archive, or
// a valid PclZip object.
// Return Values :
// 1 on success.
// 0 or a negative value on error (error code).
// --------------------------------------------------------------------------------
function duplicate($p_archive)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::duplicate", "");
$v_result = 1;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Look if the $p_archive is a PclZip object
if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is valid PclZip object '".$p_archive->zipname."'");

// ----- Duplicate the archive
$v_result = $this->privDuplicate($p_archive->zipname);
}

// ----- Look if the $p_archive is a string (so a filename)
else if (is_string($p_archive))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is a filename '$p_archive'");

// ----- Check that $p_archive is a valid zip file
// TBC : Should also check the archive format
if (!is_file($p_archive)) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
$v_result = PCLZIP_ERR_MISSING_FILE;
}
else {
// ----- Duplicate the archive
$v_result = $this->privDuplicate($p_archive);
}
}

// ----- Invalid variable
else
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
$v_result = PCLZIP_ERR_INVALID_PARAMETER;
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : merge()
// Description :
// This method merge the $p_archive_to_add archive at the end of the current
// one ($this).
// If the archive ($this) does not exist, the merge becomes a duplicate.
// If the $p_archive_to_add archive does not exist, the merge is a success.
// Parameters :
// $p_archive_to_add : It can be directly the filename of a valid zip archive,
// or a PclZip object archive.
// Return Values :
// 1 on success,
// 0 or negative values on error (see below).
// --------------------------------------------------------------------------------
function merge($p_archive_to_add)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::merge", "");
$v_result = 1;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Check archive
if (!$this->privCheckFormat()) {
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}

// ----- Look if the $p_archive_to_add is a PclZip object
if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is valid PclZip object");

// ----- Merge the archive
$v_result = $this->privMerge($p_archive_to_add);
}

// ----- Look if the $p_archive_to_add is a string (so a filename)
else if (is_string($p_archive_to_add))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is a filename");

// ----- Create a temporary archive
$v_object_archive = new PclZip($p_archive_to_add);

// ----- Merge the archive
$v_result = $this->privMerge($v_object_archive);
}

// ----- Invalid variable
else
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
$v_result = PCLZIP_ERR_INVALID_PARAMETER;
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------



// --------------------------------------------------------------------------------
// Function : errorCode()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function errorCode()
{
if (PCLZIP_ERROR_EXTERNAL == 1) {
return(PclErrorCode());
}
else {
return($this->error_code);
}
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : errorName()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function errorName($p_with_code=false)
{
$v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE' );

if (isset($v_name[$this->error_code])) {
$v_value = $v_name[$this->error_code];
}
else {
$v_value = 'NoName';
}

if ($p_with_code) {
return($v_value.' ('.$this->error_code.')');
}
else {
return($v_value);
}
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : errorInfo()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function errorInfo($p_full=false)
{
if (PCLZIP_ERROR_EXTERNAL == 1) {
return(PclErrorString());
}
else {
if ($p_full) {
return($this->errorName(true)." : ".$this->error_string);
}
else {
return($this->error_string." [code ".$this->error_code."]");
}
}
}
// --------------------------------------------------------------------------------


// --------------------------------------------------------------------------------
// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
// ***** *****
// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
// --------------------------------------------------------------------------------



// --------------------------------------------------------------------------------
// Function : privCheckFormat()
// Description :
// This method check that the archive exists and is a valid zip archive.
// Several level of check exists. (futur)
// Parameters :
// $p_level : Level of check. Default 0.
// 0 : Check the first bytes (magic codes) (default value))
// 1 : 0 + Check the central directory (futur)
// 2 : 1 + Check each file header (futur)
// Return Values :
// true on success,
// false on error, the error code is set.
// --------------------------------------------------------------------------------
function privCheckFormat($p_level=0)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFormat", "");
$v_result = true;

// ----- Reset the error handler
$this->privErrorReset();

// ----- Look if the file exits
if (!is_file($this->zipname)) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
return(false);
}

// ----- Check that the file is readeable
if (!is_readable($this->zipname)) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
return(false);
}

// ----- Check the magic code
// TBC

// ----- Check the central header
// TBC

// ----- Check each file header
// TBC

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privParseOptions()
// Description :
// This internal methods reads the variable list of arguments ($p_options_list,
// $p_size) and generate an array with the options and values ($v_result_list).
// $v_requested_options contains the options that can be present and those that
// must be present.
// $v_requested_options is an array, with the option value as key, and 'optional',
// or 'mandatory' as value.
// Parameters :
// See above.
// Return Values :
// 1 on success.
// 0 on failure.
// --------------------------------------------------------------------------------
function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privParseOptions", "");
$v_result=1;

// ----- Read the options
$i=0;
while ($i<$p_size) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Looking for table index $i, option = '".PclZipUtilOptionText($p_options_list[$i])."(".$p_options_list[$i].")'");

// ----- Check if the option is requested
if (!isset($v_requested_options[$p_options_list[$i]])) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Look for next option
switch ($p_options_list[$i]) {
// ----- Look for options that request a path value
case PCLZIP_OPT_PATH :
case PCLZIP_OPT_REMOVE_PATH :
case PCLZIP_OPT_ADD_PATH :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Get the value
$v_result_list[$p_options_list[$i]] = strtr($p_options_list[$i+1], '\\', '/');
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
break;

// ----- Look for options that request no value
case PCLZIP_OPT_REMOVE_ALL_PATH :
$v_result_list[$p_options_list[$i]] = true;
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
break;

// ----- Look for options that request an octal value
case PCLZIP_OPT_SET_CHMOD :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Get the value
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
break;

// ----- Look for options that request a call-back
case PCLZIP_CB_PRE_EXTRACT :
case PCLZIP_CB_POST_EXTRACT :
case PCLZIP_CB_PRE_ADD :
case PCLZIP_CB_POST_ADD :
/* for futur use
case PCLZIP_CB_PRE_DELETE :
case PCLZIP_CB_POST_DELETE :
case PCLZIP_CB_PRE_LIST :
case PCLZIP_CB_POST_LIST :
*/
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Get the value
$v_function_name = $p_options_list[$i+1];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "call-back ".PclZipUtilOptionText($p_options_list[$i])." = '".$v_function_name."'");

// ----- Check that the value is a valid existing function
if (!function_exists($v_function_name)) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Set the attribute
$v_result_list[$p_options_list[$i]] = $v_function_name;
$i++;
break;

default :
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Unknown optional parameter '".$p_options_list[$i]."'");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Next options
$i++;
}

// ----- Look for mandatory options
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
// ----- Look for mandatory option
if ($v_requested_options[$key] == 'mandatory') {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
// ----- Look if present
if (!isset($v_result_list[$key])) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privCreate()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privCreate($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCreate", "list, result_list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
$v_result=1;
$v_list_detail = array();

// ----- Open the file in write mode
if (($v_result = $this->privOpenFd('wb')) != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Add the list of files
$v_result = $this->privAddList($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);

// ----- Close
$this->privCloseFd();

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privAdd()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privAdd($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAdd", "list, result_list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
$v_result=1;
$v_list_detail = array();

// ----- Look if the archive exists
if (!is_file($this->zipname))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, create it.");

// ----- Do a create
$v_result = $this->privCreate($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privCloseFd();
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Go to beginning of File
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");

// ----- Creates a temporay file
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';

// ----- Open the temporary file in write mode
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
{
$this->privCloseFd();

PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Copy the files from the archive to the temporary file
// TBC : Here I should better append the file and go back to erase the central dir
$v_size = $v_central_dir['offset'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Swap the file descriptor
// Here is a trick : I swap the temporary fd with the zip fd, in order to use
// the following methods on the temporary fil and not the real archive
$v_swap = $this->zip_fd;
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;

// ----- Add the files
$v_header_list = array();
if (($v_result = $this->privAddFileList($p_list, $v_header_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
{
fclose($v_zip_temp_fd);
$this->privCloseFd();
@unlink($v_zip_temp_name);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Store the offset of the central dir
$v_offset = @ftell($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");

// ----- Copy the block of file headers from the old archive
$v_size = $v_central_dir['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($v_zip_temp_fd, $v_read_size);
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Create the Central Dir files header
for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
{
// ----- Create the file header
if ($v_header_list[$i]['status'] == 'ok') {
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
fclose($v_zip_temp_fd);
$this->privCloseFd();
@unlink($v_zip_temp_name);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
$v_count++;
}

// ----- Transform the header to a 'usable' info
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
}

// ----- Zip file comment
$v_comment = '';

// ----- Calculate the size of the central header
$v_size = @ftell($this->zip_fd)-$v_offset;

// ----- Create the central dir footer
if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
{
// ----- Reset the file list
unset($v_header_list);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Swap back the file descriptor
$v_swap = $this->zip_fd;
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;

// ----- Close
$this->privCloseFd();

// ----- Close the temporary file
@fclose($v_zip_temp_fd);

// ----- Delete the zip file
// TBC : I should test the result ...
@unlink($this->zipname);

// ----- Rename the temporary file
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
PclZipUtilRename($v_zip_temp_name, $this->zipname);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privOpenFd()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function privOpenFd($p_mode)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOpenFd", 'mode='.$p_mode);
$v_result=1;

// ----- Look if already open
if ($this->zip_fd != 0)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Open file in '.$p_mode.' mode');
if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privCloseFd()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function privCloseFd()
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCloseFd", "");
$v_result=1;

if ($this->zip_fd != 0)
@fclose($this->zip_fd);
$this->zip_fd = 0;

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privAddList()
// Description :
// $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
// different from the real path of the file. This is usefull if you want to have PclTar
// running in any directory, and memorize relative path from an other directory.
// Parameters :
// $p_list : An array containing the file or directory names to add in the tar
// $p_result_list : list of added files with their properties (specially the status field)
// $p_add_dir : Path to add in the filename path archived
// $p_remove_dir : Path to remove in the filename path archived
// Return Values :
// --------------------------------------------------------------------------------
function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddList", "list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
$v_result=1;

// ----- Add the files
$v_header_list = array();
if (($v_result = $this->privAddFileList($p_list, $v_header_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Store the offset of the central dir
$v_offset = @ftell($this->zip_fd);

// ----- Create the Central Dir files header
for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
{
// ----- Create the file header
if ($v_header_list[$i]['status'] == 'ok') {
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
$v_count++;
}

// ----- Transform the header to a 'usable' info
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
}

// ----- Zip file comment
$v_comment = '';

// ----- Calculate the size of the central header
$v_size = @ftell($this->zip_fd)-$v_offset;

// ----- Create the central dir footer
if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
{
// ----- Reset the file list
unset($v_header_list);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privAddFileList()
// Description :
// $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
// different from the real path of the file. This is usefull if you want to
// run the lib in any directory, and memorize relative path from an other directory.
// Parameters :
// $p_list : An array containing the file or directory names to add in the tar
// $p_result_list : list of added files with their properties (specially the status field)
// $p_add_dir : Path to add in the filename path archived
// $p_remove_dir : Path to remove in the filename path archived
// Return Values :
// --------------------------------------------------------------------------------
function privAddFileList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileList", "list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
$v_result=1;
$v_header = array();

// ----- Recuperate the current number of elt in list
$v_nb = sizeof($p_result_list);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Before add, list have $v_nb elements");

// ----- Loop on the files
for ($j=0; ($j<count($p_list)) && ($v_result==1); $j++)
{
// ----- Recuperate the filename
$p_filename = $p_list[$j];

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for file [$p_filename]");

// ----- Skip empty file names
if ($p_filename == "")
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Skip empty filename");
continue;
}

// ----- Check the filename
if (!file_exists($p_filename))
{
// ----- Error log
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '$p_filename' does not exists");
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '$p_filename' does not exists");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

/* This test is done later
// ----- Check the path length
if (strlen($p_filename) > 0xFF)
{
// ----- Error log
PclZip::privErrorLog(-5, "File name is too long (max. 255) : '$p_filename'");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
*/

// ----- Look if it is a file or a dir with no all pathnre move
if ((is_file($p_filename)) || ((is_dir($p_filename)) && !$p_remove_all_dir)) {
// ----- Add the file
if (($v_result = $this->privAddFile($p_filename, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
{
// ----- Return status
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Store the file infos
$p_result_list[$v_nb++] = $v_header;
}

// ----- Look for directory
if (is_dir($p_filename))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "$p_filename is a directory");

// ----- Look for path
if ($p_filename != ".")
$v_path = $p_filename."/";
else
$v_path = "";

// ----- Read the directory for files and sub-directories
$p_hdir = opendir($p_filename);
$p_hitem = readdir($p_hdir); // '.' directory
$p_hitem = readdir($p_hdir); // '..' directory
while ($p_hitem = readdir($p_hdir))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for $p_hitem in the directory");

// ----- Look for a file
if (is_file($v_path.$p_hitem))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Add the file '".$v_path.$p_hitem."'");

// ----- Add the file
if (($v_result = $this->privAddFile($v_path.$p_hitem, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
{
// ----- Return status
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Store the file infos
$p_result_list[$v_nb++] = $v_header;
}

// ----- Recursive call to privAddFileList()
else
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Add the directory '".$v_path.$p_hitem."'");

// ----- Need an array as parameter
$p_temp_list[0] = $v_path.$p_hitem;
$v_result = $this->privAddFileList($p_temp_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);

// ----- Update the number of elements of the list
$v_nb = sizeof($p_result_list);
}
}

// ----- Free memory for the recursive loop
unset($p_temp_list);
unset($p_hdir);
unset($p_hitem);
}
}

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "After add, list have $v_nb elements");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privAddFile()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privAddFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFile", "filename='$p_filename', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
$v_result=1;

if ($p_filename == "")
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Calculate the stored filename
$v_stored_filename = $p_filename;

// ----- Look for all path to remove
if ($p_remove_all_dir) {
$v_stored_filename = basename($p_filename);
}
// ----- Look for partial path remove
else if ($p_remove_dir != "")
{
if (substr($p_remove_dir, -1) != '/')
$p_remove_dir .= "/";

if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./"))
{
if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./"))
$p_remove_dir = "./".$p_remove_dir;
if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./"))
$p_remove_dir = substr($p_remove_dir, 2);
}

if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
{
$v_stored_filename = substr($p_filename, strlen($p_remove_dir));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Remove path '$p_remove_dir' in file '$p_filename' = '$v_stored_filename'");
}
}
// ----- Look for path to add
if ($p_add_dir != "")
{
if (substr($p_add_dir, -1) == "/")
$v_stored_filename = $p_add_dir.$v_stored_filename;
else
$v_stored_filename = $p_add_dir."/".$v_stored_filename;
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
}

// ----- Filename (reduce the path of stored name)
$v_stored_filename = PclZipUtilPathReduction($v_stored_filename);

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Filename (reduced) '$v_stored_filename', strlen ".strlen($v_stored_filename));

/* filename length moved after call-back in release 1.3
// ----- Check the path length
if (strlen($v_stored_filename) > 0xFF)
{
// ----- Error log
PclZip::privErrorLog(-5, "Stored file name is too long (max. 255) : '$v_stored_filename'");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
*/

// ----- Set the file properties
clearstatcache();
$p_header['version'] = 20;
$p_header['version_extracted'] = 10;
$p_header['flag'] = 0;
$p_header['compression'] = 0;
$p_header['mtime'] = filemtime($p_filename);
$p_header['crc'] = 0;
$p_header['compressed_size'] = 0;
$p_header['size'] = filesize($p_filename);
$p_header['filename_len'] = strlen($p_filename);
$p_header['extra_len'] = 0;
$p_header['comment_len'] = 0;
$p_header['disk'] = 0;
$p_header['internal'] = 0;
$p_header['external'] = (is_file($p_filename)?0xFE49FFE0:0x41FF0010);
$p_header['offset'] = 0;
$p_header['filename'] = $p_filename;
$p_header['stored_filename'] = $v_stored_filename;
$p_header['extra'] = '';
$p_header['comment'] = '';
$p_header['status'] = 'ok';
$p_header['index'] = -1;

// ----- Look for pre-add callback
if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_ADD]."()') is defined for the extraction");

// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_header, $v_local_header);

// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
if ($v_result == 0) {
// ----- Change the file status
$p_header['status'] = "skipped";
$v_result = 1;
}

// ----- Update the informations
// Only some fields can be modified
if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
$p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New stored filename is '".$p_header['stored_filename']."'");
}
}

// ----- Check the path length
if (strlen($p_header['stored_filename']) > 0xFF) {
$p_header['status'] = 'filename_too_long';
}

// ----- Look if no error, or file not skipped
if ($p_header['status'] == 'ok') {

// ----- Look for a file
if (is_file($p_filename))
{
// ----- Open the source file
if (($v_file = @fopen($p_filename, "rb")) == 0)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Creates a compressed temporary file
if (($v_file_compressed = @gzopen($p_filename.'.gz', "wb")) == 0)
{
// ----- Close the file
fclose($v_file);

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, "Unable to open file '$p_filename.gz' in gz binary write mode");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = filesize($p_filename);
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
$v_buffer = fread($v_file, $v_read_size);
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@gzputs($v_file_compressed, $v_binary_data, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Close the file
@fclose($v_file);
@gzclose($v_file_compressed);

// ----- Check the minimum file size
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "gzip file size ".filesize($p_filename.'.gz'));
if (filesize($p_filename.'.gz') < 18)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Invalid file "'.$p_filename.'.gz'.'" size (less than header size)');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Extract the compressed attributes
if (($v_file_compressed = @fopen($p_filename.'.gz', "rb")) == 0)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename.gz' in gz binary read mode");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Read the gzip file header
$v_binary_data = @fread($v_file_compressed, 10);
$v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);

// ----- Check some parameters
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[id1]='.bin2hex($v_data_header['id1']));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[id2]='.bin2hex($v_data_header['id2']));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[cm]='.bin2hex($v_data_header['cm']));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[flag]='.bin2hex($v_data_header['flag']));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[mtime]='.$v_data_header['mtime']);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[xfl]='.bin2hex($v_data_header['xfl']));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[os]='.bin2hex($v_data_header['os']));
$v_data_header['os'] = bin2hex($v_data_header['os']);

// ----- Read the gzip file footer
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File position after header ".ftell($v_file_compressed));
@fseek($v_file_compressed, filesize($p_filename.'.gz')-8);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File position at beginning of footer ".ftell($v_file_compressed));
$v_binary_data = @fread($v_file_compressed, 8);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File position after footer ".ftell($v_file_compressed));
$v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);

// ----- Set the attributes
$p_header['compression'] = ord($v_data_header['cm']);
//$p_header['mtime'] = $v_data_header['mtime'];
$p_header['crc'] = $v_data_footer['crc'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Compressed size ".(filesize($p_filename.'.gz')-18));
$p_header['compressed_size'] = filesize($p_filename.'.gz')-18;

// ----- Close the file
@fclose($v_file_compressed);

// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
{
// ----- Return status
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Add the compressed data
if (($v_file_compressed = @fopen($p_filename.'.gz', "rb")) == 0)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename.gz' in gz binary read mode");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
fseek($v_file_compressed, 10);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File position before reading compressed data ".ftell($v_file_compressed));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, ' '.$p_header['compressed_size'].' bytes to read');
$v_size = $p_header['compressed_size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
$v_buffer = fread($v_file_compressed, $v_read_size);
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($this->zip_fd, $v_binary_data, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Close the file
@fclose($v_file_compressed);

// ----- Unlink the temporary file
@unlink($p_filename.'.gz');
}

// ----- Look for a directory
else
{
// ----- Set the file properties
$p_header['filename'] .= '/';
$p_header['filename_len']++;
$p_header['size'] = 0;
$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked

// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
{
// ----- Return status
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
}
}

// ----- Look for pre-add callback
if (isset($p_options[PCLZIP_CB_POST_ADD])) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_ADD]."()') is defined for the extraction");

// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_header, $v_local_header);

// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
if ($v_result == 0) {
// ----- Ignored
$v_result = 1;
}

// ----- Update the informations
// Nothing can be modified
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privWriteFileHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privWriteFileHeader(&$p_header)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
$v_result=1;

// TBC
//for(reset($p_header); $key = key($p_header); next($p_header)) {
// //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
//}

// ----- Store the offset position of the file
$p_header['offset'] = ftell($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'File offset of the header :'.$p_header['offset']);

// ----- Transform UNIX mtime to DOS format mdate/mtime
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
$v_date = getdate($p_header['mtime']);
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];

// ----- Packed data
$v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, $p_header['version'], $p_header['flag'],
$p_header['compression'], $v_mtime, $v_mdate,
$p_header['crc'], $p_header['compressed_size'], $p_header['size'],
strlen($p_header['stored_filename']), $p_header['extra_len']);

// ----- Write the first 148 bytes of the header in the archive
fputs($this->zip_fd, $v_binary_data, 30);

// ----- Write the variable fields
if (strlen($p_header['stored_filename']) != 0)
{
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
}
if ($p_header['extra_len'] != 0)
{
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privWriteCentralFileHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privWriteCentralFileHeader(&$p_header)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
$v_result=1;

// TBC
//for(reset($p_header); $key = key($p_header); next($p_header)) {
// //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
//}

// ----- Transform UNIX mtime to DOS format mdate/mtime
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
$v_date = getdate($p_header['mtime']);
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];

// ----- Packed data
$v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, $p_header['version'], $p_header['version_extracted'],
$p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'],
$p_header['compressed_size'], $p_header['size'],
strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'],
$p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']);

// ----- Write the 42 bytes of the header in the zip file
fputs($this->zip_fd, $v_binary_data, 46);

// ----- Write the variable fields
if (strlen($p_header['stored_filename']) != 0)
{
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
}
if ($p_header['extra_len'] != 0)
{
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
}
if ($p_header['comment_len'] != 0)
{
fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privWriteCentralHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralHeader", 'nb_entries='.$p_nb_entries.', size='.$p_size.', offset='.$p_offset.', comment="'.$p_comment.'"');
$v_result=1;

// ----- Packed data
$v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment));

// ----- Write the 22 bytes of the header in the zip file
fputs($this->zip_fd, $v_binary_data, 22);

// ----- Write the variable fields
if (strlen($p_comment) != 0)
{
fputs($this->zip_fd, $p_comment, strlen($p_comment));
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privList()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privList(&$p_list)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privList", "list");
$v_result=1;

// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Go to beginning of Central Dir
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset : ".$v_central_dir['offset']."'");
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_central_dir['offset']))
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");

// ----- Read each entry
for ($i=0; $i<$v_central_dir['entries']; $i++)
{
// ----- Read the file header
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
$v_header['index'] = $i;

// ----- Get the only interesting attributes
$this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
unset($v_header);
}

// ----- Close the zip file
$this->privCloseFd();

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privConvertHeader2FileInfo()
// Description :
// This function takes the file informations from the central directory
// entries and extract the interesting parameters that will be given back.
// The resulting file infos are set in the array $p_info
// $p_info['filename'] : Filename with full path. Given by user (add),
// extracted in the filesystem (extract).
// $p_info['stored_filename'] : Stored filename in the archive.
// $p_info['size'] = Size of the file.
// $p_info['compressed_size'] = Compressed size of the file.
// $p_info['mtime'] = Last modification date of the file.
// $p_info['comment'] = Comment associated with the file.
// $p_info['folder'] = true/false : indicates if the entry is a folder or not.
// $p_info['status'] = status of the action on the file.
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privConvertHeader2FileInfo($p_header, &$p_info)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privConvertHeader2FileInfo", "Filename='".$p_header['filename']."'");
$v_result=1;

// ----- Get the interesting attributes
$p_info['filename'] = $p_header['filename'];
$p_info['stored_filename'] = $p_header['stored_filename'];
$p_info['size'] = $p_header['size'];
$p_info['compressed_size'] = $p_header['compressed_size'];
$p_info['mtime'] = $p_header['mtime'];
$p_info['comment'] = $p_header['comment'];
$p_info['folder'] = ($p_header['external']==0x41FF0010);
$p_info['index'] = $p_header['index'];
$p_info['status'] = $p_header['status'];

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privExtract()
// Description :
// Parameters :
// $p_file_list : An array where will be placed the properties of each
// extracted file
// $p_path : Path to add while writing the extracted files
// $p_remove_path : Path to remove (from the file memorized path) while writing the
// extracted files. If the path does not match the file path,
// the file is extracted with its memorized path.
// $p_remove_path does not apply to 'list' mode.
// $p_path and $p_remove_path are commulative.
// Return Values :
// 1 on success,0 or less on error (see error code list)
// --------------------------------------------------------------------------------
function privExtract(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtract", "list, path=$p_path, remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
$v_result=1;

// ----- Check the path
if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../")))
$p_path = "./".$p_path;

// ----- Reduce the path last (and duplicated) '/'
if (($p_path != "./") && ($p_path != "/"))
{
// ----- Look for the path end '/'
while (substr($p_path, -1) == "/")
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
$p_path = substr($p_path, 0, strlen($p_path)-1);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
}
}

// ----- Look for path to remove format (should end by /)
if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
{
$p_remove_path .= '/';
}
$p_remove_path_size = strlen($p_remove_path);

// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result = $this->privOpenFd('rb')) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Start at beginning of Central Dir
$v_pos_entry = $v_central_dir['offset'];

// ----- Read each entry
for ($i=0; $i<$v_central_dir['entries']; $i++)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file entry : $i'");

// ----- Read next Central dir entry
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_pos_entry))
{
// ----- Close the zip file
$this->privCloseFd();

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");

// ----- Read the file header
$v_header = array();
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Store the index
$v_header['index'] = $i;

// ----- Store the file position
$v_pos_entry = ftell($this->zip_fd);

// ----- Go to the file position
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_header['offset']))
{
// ----- Close the zip file
$this->privCloseFd();

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");

// ----- Extracting the file
if (($v_result = $this->privExtractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_options)) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Get the only interesting attributes
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$i])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
}

// ----- Close the zip file
$this->privCloseFd();

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privExtractByIndex()
// Description :
// Parameters :
// $p_file_list : An array where will be placed the properties of each
// extracted file
// $p_index : A single index (integer) or a string of indexes of files to
// extract. The form of the string is "0,4-6,8-12" with only numbers
// and '-' for range or ',' to separate ranges. No spaces or ';'
// are allowed.
// $p_path : Path to add while writing the extracted files
// $p_remove_path : Path to remove (from the file memorized path) while writing the
// extracted files. If the path does not match the file path,
// the file is extracted with its memorized path.
// $p_remove_path does not apply to 'list' mode.
// $p_path and $p_remove_path are commulative.
// Return Values :
// 1 on success,0 or less on error (see error code list)
// --------------------------------------------------------------------------------
function privExtractByIndex(&$p_file_list, $p_index, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtractByIndex", "list, index='$p_index', path=$p_path, remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
$v_result=1;

// ----- Check the path
if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../")))
$p_path = "./".$p_path;

// ----- Reduce the path last (and duplicated) '/'
if (($p_path != "./") && ($p_path != "/"))
{
// ----- Look for the path end '/'
while (substr($p_path, -1) == "/")
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
$p_path = substr($p_path, 0, strlen($p_path)-1);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
}
}

// ----- Look for path to remove format (should end by /)
if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
{
$p_remove_path .= '/';
}
$p_remove_path_size = strlen($p_remove_path);

// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result = $this->privOpenFd('rb')) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Manipulate the index list
$p_index = strtr($p_index, ' ', '');
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Reduced index : '$p_index'");
$v_index_list = explode(",", $p_index);
// TBC : Here I should sort the index. However a simple sort is not enought.
// look for the use of usort()
//sort($v_index_list);

// ----- Start at beginning of Central Dir
$v_pos_entry = $v_central_dir['offset'];

// ----- Read each entry
for ($i=0, $j_start=0, $v_nb_extracted=0; ($i<$v_central_dir['entries']) && ($j_start<sizeof($v_index_list)); $i++)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : $i'");

// ----- Read next Central dir entry
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_pos_entry))
{
// ----- Close the zip file
$this->privCloseFd();

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");

// ----- Read the file header
$v_header = array();
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Store the index
$v_header['index'] = $i;

// ----- Store the file position
$v_pos_entry = ftell($this->zip_fd);

// ----- Look if the index is in the list
$v_extract = false;
for ($j=$j_start; ($j<sizeof($v_index_list)) && (!$v_extract); $j++)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in '".$v_index_list[$j]."'");

// ----- Extract range
$v_item_list = explode("-", $v_index_list[$j]);
$v_size_item_list = sizeof($v_item_list);
if ($v_size_item_list == 1)
{
if ($i==$v_item_list[0])
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as a single index");
$v_extract = true;
}
if ($i>=$v_item_list[0])
{
$j_start = $j+1;
}
}
else if ($v_size_item_list == 2)
{
if (($i>=$v_item_list[0]) && ($i<=$v_item_list[1]))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
$v_extract = true;
}
if ($i>=$v_item_list[1])
{
$j_start = $j+1;
}
}
if ($v_item_list[0]>$i)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Range is greater than index, stop loop");
break;
}
}

// ----- Look for real extraction
if ($v_extract)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file '".$v_header['filename']."', index '$i'");

// ----- Go to the file position
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_header['offset']))
{
// ----- Close the zip file
$this->privCloseFd();

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");

// ----- Extracting the file
if (($v_result = $this->privExtractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_options)) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Get the only interesting attributes
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
}
}

// ----- Close the zip file
$this->privCloseFd();

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privExtractFile()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFile', "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
$v_result=1;

// ----- Read the file header
if (($v_result = $this->privReadFileHeader($v_header)) != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");

// ----- Check that the file header is coherent with $p_entry info
// TBC

// ----- Look for all path to remove
if ($p_remove_all_path == true) {
// ----- Get the basename of the path
$p_entry['filename'] = basename($p_entry['filename']);
}

// ----- Look for path to remove
else if ($p_remove_path != "")
{
//if (strcmp($p_remove_path, $p_entry['filename'])==0)
if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The folder is the same as the removed path '".$p_entry['filename']."'");

// ----- Change the file status
$p_entry['status'] = "filtered";

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

$p_remove_path_size = strlen($p_remove_path);
if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '".$p_entry['filename']."'");

// ----- Remove the path
$p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Resulting file is '".$p_entry['filename']."'");
}
}

// ----- Add the path
if ($p_path != '')
{
$p_entry['filename'] = $p_path."/".$p_entry['filename'];
}

// ----- Look for pre-extract callback
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");

// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);

// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
if ($v_result == 0) {
// ----- Change the file status
$p_entry['status'] = "skipped";
}

// ----- Update the informations
// Only some fields can be modified
$p_entry['filename'] = $v_local_header['filename'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
}

// ----- Trace
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");

// ----- Look if extraction should be done
if ($p_entry['status'] == 'ok') {

// ----- Look for specific actions while the file exist
if (file_exists($p_entry['filename']))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_entry['filename']."' already exists");

// ----- Look if file is a directory
if (is_dir($p_entry['filename']))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is a directory");

// ----- Change the file status
$p_entry['status'] = "already_a_directory";

// ----- Return
////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
//return $v_result;
}
// ----- Look if file is write protected
else if (!is_writeable($p_entry['filename']))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is write protected");

// ----- Change the file status
$p_entry['status'] = "write_protected";

// ----- Return
////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
//return $v_result;
}

// ----- Look if the extracted file is older
else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is newer (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");

// ----- Change the file status
$p_entry['status'] = "newer_exist";

// ----- Return
////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
//return $v_result;
}
}

// ----- Check the directory availability and create it if necessary
else {
if (substr($p_entry['filename'], -1) == '/')
$v_dir_to_check = $p_entry['filename'];
else if (!strstr($p_entry['filename'], "/"))
$v_dir_to_check = "";
else
$v_dir_to_check = dirname($p_entry['filename']);

if (($v_result = $this->privDirCheck($v_dir_to_check, ($p_entry['external']==0x41FF0010))) != 1) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '".$p_entry['filename']."'");

// ----- Change the file status
$p_entry['status'] = "path_creation_fail";

// ----- Return
////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
//return $v_result;
$v_result = 1;
}
}
}

// ----- Look if extraction should be done
if ($p_entry['status'] == 'ok') {

// ----- Do the extraction (if not a folder)
if (!($p_entry['external']==0x41FF0010))
{

// ----- Look for not compressed file
if ($p_entry['compressed_size'] == $p_entry['size'])
{
// ----- Trace
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");

// ----- Opening destination file
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");

// ----- Change the file status
$p_entry['status'] = "write_error";

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");

// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['compressed_size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
$v_buffer = fread($this->zip_fd, $v_read_size);
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_binary_data, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Closing the destination file
fclose($v_dest_file);

// ----- Change the file mtime
touch($p_entry['filename'], $p_entry['mtime']);
}
else
{
// ----- Trace
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");

// ----- Open the destination file in write mode
if (($v_dest_file = @fopen($p_entry['filename'].'.gz', 'wb')) == 0)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");

// ----- Change the file status
$p_entry['status'] = "write_error";

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Start extraction of '".$p_entry['filename']."'");

// ----- Write gz file format header
$v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
fwrite($v_dest_file, $v_binary_data, 10);

// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['compressed_size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
$v_buffer = fread($this->zip_fd, $v_read_size);
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_binary_data, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Write gz file format footer
$v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']);
fwrite($v_dest_file, $v_binary_data, 8);

// ----- Close the temporary file
fclose($v_dest_file);

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position after extract [".ftell($this->zip_fd)."]");

// ----- Uncompress
if (($v_src_file = gzopen($p_entry['filename'].'.gz', 'rb')) == 0)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in read binary mode");

// ----- Change the file status
$p_entry['status'] = "read_error";

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");

// ----- Change the file status
$p_entry['status'] = "write_error";
gzclose($v_src_file);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'File size is '.filesize($p_entry['filename'].'.gz'));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '$p_entry[size]' bytes");

// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
$v_buffer = gzread($v_src_file, $v_read_size);
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_binary_data, $v_read_size);
$v_size -= $v_read_size;
}
fclose($v_dest_file);
gzclose($v_src_file);

// ----- Change the file mtime
touch($p_entry['filename'], $p_entry['mtime']);

// ----- Delete the temporary file
@unlink($p_entry['filename'].'.gz');
}

// ----- Look for chmod option
if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "chmod option activated '".$p_options[PCLZIP_OPT_SET_CHMOD]."'");

// ----- Change the mode of the file
chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
}

// ----- Trace
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
}
}

// ----- Look for post-extract callback
if (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");

// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);

// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privReadFileHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privReadFileHeader(&$p_header)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadFileHeader", "");
$v_result=1;

// ----- Read the 4 bytes signature
$v_binary_data = @fread($this->zip_fd, 4);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
$v_data = unpack('Vid', $v_binary_data);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");

// ----- Check signature
if ($v_data['id'] != 0x04034b50)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid File header");

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Read the first 42 bytes of the header
$v_binary_data = fread($this->zip_fd, 26);

// ----- Look for invalid block size
if (strlen($v_binary_data) != 26)
{
$p_header['filename'] = "";
$p_header['status'] = "invalid_header";
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Extract the values
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'");
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'");
$v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);

// ----- Get filename
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$v_data['filename_len']);
$p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\'');

// ----- Get extra_fields
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra field length : ".$v_data['extra_len']);
if ($v_data['extra_len'] != 0) {
$p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
}
else {
$p_header['extra'] = '';
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra field : \''.bin2hex($p_header['extra']).'\'');

// ----- Extract properties
$p_header['compression'] = $v_data['compression'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compression method : \''.bin2hex($p_header['compression']).'\'');
$p_header['size'] = $v_data['size'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\'');
$p_header['compressed_size'] = $v_data['compressed_size'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
$p_header['crc'] = $v_data['crc'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.$p_header['crc'].'\'');
$p_header['flag'] = $v_data['flag'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\'');

// ----- Recuperate date in UNIX format
$p_header['mdate'] = $v_data['mdate'];
$p_header['mtime'] = $v_data['mtime'];
if ($p_header['mdate'] && $p_header['mtime'])
{
// ----- Extract time
$v_hour = ($p_header['mtime'] & 0xF800) >> 11;
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
$v_seconde = ($p_header['mtime'] & 0x001F)*2;

// ----- Extract date
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
$v_month = ($p_header['mdate'] & 0x01E0) >> 5;
$v_day = $p_header['mdate'] & 0x001F;

// ----- Get UNIX date format
$p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
}
else
{
$p_header['mtime'] = time();
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
}

// ----- Other informations
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compression type : ".$v_data['compression']);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Version : ".$v_data['version']);

// TBC
//for(reset($v_data); $key = key($v_data); next($v_data)) {
// //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Attribut[$key] = ".$v_data[$key]);
//}

// ----- Set the stored filename
$p_header['stored_filename'] = $p_header['filename'];

// ----- Set the status field
$p_header['status'] = "ok";

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privReadCentralFileHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privReadCentralFileHeader(&$p_header)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadCentralFileHeader", "");
$v_result=1;

// ----- Read the 4 bytes signature
$v_binary_data = @fread($this->zip_fd, 4);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
$v_data = unpack('Vid', $v_binary_data);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");

// ----- Check signature
if ($v_data['id'] != 0x02014b50)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid Central Dir File signature");

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Read the first 42 bytes of the header
$v_binary_data = fread($this->zip_fd, 42);

// ----- Look for invalid block size
if (strlen($v_binary_data) != 42)
{
$p_header['filename'] = "";
$p_header['status'] = "invalid_header";
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Extract the values
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'");
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'");
$p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);

// ----- Get filename
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$p_header['filename_len']);
if ($p_header['filename_len'] != 0)
$p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
else
$p_header['filename'] = '';
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\'');

// ----- Get extra
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra length : ".$p_header['extra_len']);
if ($p_header['extra_len'] != 0)
$p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
else
$p_header['extra'] = '';
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra : \''.$p_header['extra'].'\'');

// ----- Get comment
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$p_header['comment_len']);
if ($p_header['comment_len'] != 0)
$p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
else
$p_header['comment'] = '';
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_header['comment'].'\'');

// ----- Extract properties
//$p_header['size'] = $v_data['size'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\'');
//$p_header['compressed_size'] = $v_data['compressed_size'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
//$p_header['crc'] = $v_data['crc'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.$p_header['crc'].'\'');
//$p_header['flag'] = $v_data['flag'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\'');
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset : \''.$p_header['offset'].'\'');

// ----- Recuperate date in UNIX format
if ($p_header['mdate'] && $p_header['mtime'])
{
// ----- Extract time
$v_hour = ($p_header['mtime'] & 0xF800) >> 11;
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
$v_seconde = ($p_header['mtime'] & 0x001F)*2;

// ----- Extract date
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
$v_month = ($p_header['mdate'] & 0x01E0) >> 5;
$v_day = $p_header['mdate'] & 0x001F;

// ----- Get UNIX date format
$p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);

//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
}
else
{
$p_header['mtime'] = time();
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
}

// ----- Set the stored filename
$p_header['stored_filename'] = $p_header['filename'];

// ----- Set default status to ok
$p_header['status'] = 'ok';

// ----- Look if it is a directory
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "external (Hex) : '".sprintf("Ox%04X", $p_header['external'])."' (".($p_header['external']==0x41FF0010?'is a folder':'is a file').')');
if (substr($p_header['filename'], -1) == '/')
{
$p_header['external'] = 0x41FF0010;
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Force folder external : \''.$p_header['external'].'\'');
}


// TBC
//for(reset($p_header); $key = key($p_header); next($p_header)) {
// //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
//}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privReadEndCentralDir()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privReadEndCentralDir(&$p_central_dir)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadEndCentralDir", "");
$v_result=1;

// ----- Go to the end of the zip file
$v_size = filesize($this->zipname);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size of the file :$v_size");
@fseek($this->zip_fd, $v_size);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position at end of zip file : \''.ftell($this->zip_fd).'\'');
if (@ftell($this->zip_fd) != $v_size)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- First try : look if this is an archive with no commentaries (most of the time)
// in this case the end of central dir is at 22 bytes of the file end
$v_found = 0;
if ($v_size > 26) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Look for central dir with no comment');
@fseek($this->zip_fd, $v_size-22);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');
if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');

// ----- Read for bytes
$v_binary_data = @fread($this->zip_fd, 4);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
$v_data = unpack('Vid', $v_binary_data);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");

// ----- Check signature
if ($v_data['id'] == 0x06054b50) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found central dir at the default position.");
$v_found = 1;
}

$v_pos = ftell($this->zip_fd);
}

// ----- Go back to the maximum possible size of the Central Dir End Record
if (!$v_found) {
$v_maximum_size = 65557; // 0xFFFF + 22;
if ($v_maximum_size > $v_size)
$v_maximum_size = $v_size;
@fseek($this->zip_fd, $v_size-$v_maximum_size);
if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');

// ----- Read byte per byte in order to find the signature
$v_pos = ftell($this->zip_fd);
$v_bytes = 0x00000000;
while ($v_pos < $v_size)
{
// ----- Read a byte
$v_byte = @fread($this->zip_fd, 1);

// ----- Add the byte
$v_bytes = ($v_bytes << 8) | Ord($v_byte);

// ----- Compare the bytes
if ($v_bytes == 0x504b0506)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Found End Central Dir signature : \''.ftell($this->zip_fd).'\'');
$v_pos++;
break;
}

$v_pos++;
}

// ----- Look if not found end of central dir
if ($v_pos == $v_size)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to find End of Central Dir Record signature");

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}

// ----- Read the first 18 bytes of the header
$v_binary_data = fread($this->zip_fd, 18);

// ----- Look for invalid block size
if (strlen($v_binary_data) != 18)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Extract the values
////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record : '".$v_binary_data."'");
////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record (Hex) : '".bin2hex($v_binary_data)."'");
$v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);

// ----- Check the global size
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$v_data['comment_size']);
if (($v_pos + $v_data['comment_size'] + 18) != $v_size)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Fail to find the right siganture");

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Fail to find the right signature");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Get comment
if ($v_data['comment_size'] != 0)
$p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
else
$p_central_dir['comment'] = '';
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_central_dir['comment'].'\'');

$p_central_dir['entries'] = $v_data['entries'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries : \''.$p_central_dir['entries'].'\'');
$p_central_dir['disk_entries'] = $v_data['disk_entries'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries for this disk : \''.$p_central_dir['disk_entries'].'\'');
$p_central_dir['offset'] = $v_data['offset'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset of Central Dir : \''.$p_central_dir['offset'].'\'');
$p_central_dir['size'] = $v_data['size'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size of Central Dir : \''.$p_central_dir['size'].'\'');
$p_central_dir['disk'] = $v_data['disk'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Disk number : \''.$p_central_dir['disk'].'\'');
$p_central_dir['disk_start'] = $v_data['disk_start'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Start disk number : \''.$p_central_dir['disk_start'].'\'');

// TBC
//for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
// //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "central_dir[$key] = ".$p_central_dir[$key]);
//}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privDeleteByIndex()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privDeleteByIndex($p_index, &$p_result_list)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDeleteByIndex", "index='$p_index'");
$v_result=1;
$v_list_detail = array();

// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privCloseFd();
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Go to beginning of File
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");

// ----- Scan all the files
// ----- Manipulate the index list
$p_index = strtr($p_index, ' ', '');
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Reduced index : '$p_index'");
$v_index_list = explode(",", $p_index);
// TBC : Here I should sort the index. However a simple sort is not enought.
// look for the use of usort()
//sort($v_index_list);

// ----- Start at beginning of Central Dir
$v_pos_entry = $v_central_dir['offset'];
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_pos_entry))
{
// ----- Close the zip file
$this->privCloseFd();

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");

// ----- Read each entry
$v_header_list = array();
for ($i=0, $j_start=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : $i'");

// ----- Read the file header
$v_header_list[$v_nb_extracted] = array();
if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Store the index
$v_header_list[$v_nb_extracted]['index'] = $i;

// ----- Look if the index is in the list
for ($j=$j_start, $v_found = false; ($j<sizeof($v_index_list)) && (!$v_found); $j++)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in '".$v_index_list[$j]."'");

// ----- Extract range
$v_item_list = explode("-", $v_index_list[$j]);
$v_size_item_list = sizeof($v_item_list);
if ($v_size_item_list == 1)
{
if ($i==$v_item_list[0])
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as a single index");
$v_found = true;
}
if ($i>=$v_item_list[0])
{
$j_start = $j+1;
}
}
else if ($v_size_item_list == 2)
{
if (($i>=$v_item_list[0]) && ($i<=$v_item_list[1]))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
$v_found = true;
}
if ($i>=$v_item_list[1])
{
$j_start = $j+1;
}
}
if ($v_item_list[0]>$i)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Range is greater than index, stop loop");
break;
}
}

// ----- Look for deletion
if ($v_found)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header['filename']."', index '$i' need to be deleted");
unset($v_header_list[$v_nb_extracted]);
}
else
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header['filename']."', index '$i' will not be deleted");
$v_nb_extracted++;
}
}

// ----- Creates a temporay file
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';

// ----- Creates a temporary zip archive
$v_temp_zip = new PclZip($v_zip_temp_name);

// ----- Open the temporary zip file in write mode
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary write mode");
if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1)
{
$this->privCloseFd();

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Look which file need to be kept
for ($i=0; $i<sizeof($v_header_list); $i++)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Keep entry : $i'");

// ----- Calculate the position of the header
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Offset='". $v_header_list[$i]['offset']."'");
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_header_list[$i]['offset']))
{
// ----- Close the zip file
$this->privCloseFd();
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);

// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");

// ----- Read the file header
if (($v_result = $this->privReadFileHeader($v_header_list[$i])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Write the file header
if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset for this file is '".$v_header_list[$i]['offset']."'");

// ----- Read/write the data block
if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
}

// ----- Store the offset of the central dir
$v_offset = @ftell($v_temp_zip->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");

// ----- Re-Create the Central Dir files header
for ($i=0; $i<sizeof($v_header_list); $i++)
{
// ----- Create the file header
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Offset of file : ".$v_header_list[$i]['offset']);
if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1)
{
$v_temp_zip->privCloseFd();
$this->privCloseFd();
@unlink($v_zip_temp_name);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Transform the header to a 'usable' info
$v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
}

// ----- Zip file comment
$v_comment = '';

// ----- Calculate the size of the central header
$v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;

// ----- Create the central dir footer
if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1)
{
// ----- Reset the file list
unset($v_header_list);
$v_temp_zip->privCloseFd();
$this->privCloseFd();
@unlink($v_zip_temp_name);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Close
$v_temp_zip->privCloseFd();
$this->privCloseFd();

// ----- Delete the zip file
// TBC : I should test the result ...
@unlink($this->zipname);

// ----- Rename the temporary file
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
PclZipUtilRename($v_zip_temp_name, $this->zipname);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------


// --------------------------------------------------------------------------------
// Function : privDirCheck()
// Description :
// Check if a directory exists, if not it creates it and all the parents directory
// which may be useful.
// Parameters :
// $p_dir : Directory path to check.
// Return Values :
// 1 : OK
// -1 : Unable to create directory
// --------------------------------------------------------------------------------
function privDirCheck($p_dir, $p_is_dir=false)
{
$v_result = 1;

//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDirCheck", "entry='$p_dir', is_dir='".($p_is_dir?"true":"false")."'");

// ----- Remove the final '/'
if (($p_is_dir) && (substr($p_dir, -1)=='/'))
{
$p_dir = substr($p_dir, 0, strlen($p_dir)-1);
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for entry '$p_dir'");

// ----- Check the directory availability
if ((is_dir($p_dir)) || ($p_dir == ""))
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
return 1;
}

// ----- Extract parent directory
$p_parent_dir = dirname($p_dir);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");

// ----- Just a check
if ($p_parent_dir != $p_dir)
{
// ----- Look for parent directory
if ($p_parent_dir != "")
{
if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
{
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
}
}

// ----- Create the directory
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
if (!@mkdir($p_dir, 0777))
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privMerge()
// Description :
// If $p_archive_to_add does not exist, the function exit with a success result.
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privMerge(&$p_archive_to_add)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privMerge", "archive='".$p_archive_to_add->zipname."'");
$v_result=1;

// ----- Look if the archive_to_add exists
if (!is_file($p_archive_to_add->zipname))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to add does not exist. End of merge.");

// ----- Nothing to merge, so merge is a success
$v_result = 1;

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Look if the archive exists
if (!is_file($this->zipname))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, duplicate the archive_to_add.");

// ----- Do a duplicate
$v_result = $this->privDuplicate($p_archive_to_add->zipname);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privCloseFd();
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Go to beginning of File
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");

// ----- Open the archive_to_add file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open archive_to_add in binary read mode");
if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
{
$this->privCloseFd();

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Read the central directory informations
$v_central_dir_to_add = array();
if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
{
$this->privCloseFd();
$p_archive_to_add->privCloseFd();

//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Go to beginning of File
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
@rewind($p_archive_to_add->zip_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");

// ----- Creates a temporay file
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';

// ----- Open the temporary file in write mode
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
{
$this->privCloseFd();
$p_archive_to_add->privCloseFd();

PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Copy the files from the archive to the temporary file
// TBC : Here I should better append the file and go back to erase the central dir
$v_size = $v_central_dir['offset'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Copy the files from the archive_to_add into the temporary file
$v_size = $v_central_dir_to_add['offset'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Store the offset of the central dir
$v_offset = @ftell($v_zip_temp_fd);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");

// ----- Copy the block of file headers from the old archive
$v_size = $v_central_dir['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Copy the block of file headers from the archive_to_add
$v_size = $v_central_dir_to_add['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Zip file comment
// TBC : I should merge the two comments
$v_comment = '';

// ----- Calculate the size of the (new) central header
$v_size = @ftell($v_zip_temp_fd)-$v_offset;

// ----- Swap the file descriptor
// Here is a trick : I swap the temporary fd with the zip fd, in order to use
// the following methods on the temporary fil and not the real archive fd
$v_swap = $this->zip_fd;
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;

// ----- Create the central dir footer
if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
{
$this->privCloseFd();
$p_archive_to_add->privCloseFd();
@fclose($v_zip_temp_fd);
$this->zip_fd = null;

// ----- Reset the file list
unset($v_header_list);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Swap back the file descriptor
$v_swap = $this->zip_fd;
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;

// ----- Close
$this->privCloseFd();
$p_archive_to_add->privCloseFd();

// ----- Close the temporary file
@fclose($v_zip_temp_fd);

// ----- Delete the zip file
// TBC : I should test the result ...
@unlink($this->zipname);

// ----- Rename the temporary file
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
PclZipUtilRename($v_zip_temp_name, $this->zipname);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privDuplicate()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privDuplicate($p_archive_filename)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDuplicate", "archive_filename='$p_archive_filename'");
$v_result=1;

// ----- Look if the $p_archive_filename exists
if (!is_file($p_archive_filename))
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to duplicate does not exist. End of duplicate.");

// ----- Nothing to duplicate, so duplicate is a success.
$v_result = 1;

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Open the zip file
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result=$this->privOpenFd('wb')) != 1)
{
// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}

// ----- Open the temporary file in write mode
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
{
$this->privCloseFd();

PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}

// ----- Copy the files from the archive to the temporary file
// TBC : Here I should better append the file and go back to erase the central dir
$v_size = filesize($p_archive_filename);
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read $v_read_size bytes");
$v_buffer = fread($v_zip_temp_fd, $v_read_size);
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}

// ----- Close
$this->privCloseFd();

// ----- Close the temporary file
@fclose($v_zip_temp_fd);

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privErrorLog()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function privErrorLog($p_error_code=0, $p_error_string='')
{
if (PCLZIP_ERROR_EXTERNAL == 1) {
PclError($p_error_code, $p_error_string);
}
else {
$this->error_code = $p_error_code;
$this->error_string = $p_error_string;
}
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : privErrorReset()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function privErrorReset()
{
if (PCLZIP_ERROR_EXTERNAL == 1) {
PclErrorReset();
}
else {
$this->error_code = 1;
$this->error_string = '';
}
}
// --------------------------------------------------------------------------------

}
// End of class
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : PclZipUtilPathReduction()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function PclZipUtilPathReduction($p_dir)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathReduction", "dir='$p_dir'");
$v_result = "";

// ----- Look for not empty path
if ($p_dir != "")
{
// ----- Explode path by directory names
$v_list = explode("/", $p_dir);

// ----- Study directories from last to first
for ($i=sizeof($v_list)-1; $i>=0; $i--)
{
// ----- Look for current path
if ($v_list[$i] == ".")
{
// ----- Ignore this directory
// Should be the first $i=0, but no check is done
}
else if ($v_list[$i] == "..")
{
// ----- Ignore it and ignore the $i-1
$i--;
}
else if (($v_list[$i] == "") && ($i!=(sizeof($v_list)-1)) && ($i!=0))
{
// ----- Ignore only the double '//' in path,
// but not the first and last '/'
}
else
{
$v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
}
}
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : PclZipUtilPathInclusion()
// Description :
// This function indicates if the path $p_path is under the $p_dir tree. Or,
// said in an other way, if the file or sub-dir $p_path is inside the dir
// $p_dir.
// The function indicates also if the path is exactly the same as the dir.
// This function supports path with duplicated '/' like '//', but does not
// support '.' or '..' statements.
// Parameters :
// Return Values :
// 0 if $p_path is not inside directory $p_dir
// 1 if $p_path is inside directory $p_dir
// 2 if $p_path is exactly the same as $p_dir
// --------------------------------------------------------------------------------
function PclZipUtilPathInclusion($p_dir, $p_path)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathInclusion", "dir='$p_dir', path='$p_path'");
$v_result = 1;

// ----- Explode dir and path by directory separator
$v_list_dir = explode("/", $p_dir);
$v_list_dir_size = sizeof($v_list_dir);
$v_list_path = explode("/", $p_path);
$v_list_path_size = sizeof($v_list_path);

// ----- Study directories paths
$i = 0;
$j = 0;
while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Working on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'");

// ----- Look for empty dir (path reduction)
if ($v_list_dir[$i] == '') {
$i++;
continue;
}
if ($v_list_path[$j] == '') {
$j++;
continue;
}

// ----- Compare the items
if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Items ($i,$j) are different");
$v_result = 0;
}

// ----- Next items
$i++;
$j++;
}

// ----- Look if everything seems to be the same
if ($v_result) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Look for tie break");
// ----- Skip all the empty items
while (($v_list_path[$j] == '') && ($j < $v_list_path_size)) $j++;
while (($v_list_dir[$i] == '') && ($i < $v_list_dir_size)) $i++;
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Looking on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'");

if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
// ----- There are exactly the same
$v_result = 2;
}
else if ($i < $v_list_dir_size) {
// ----- The path is shorter than the dir
$v_result = 0;
}
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : PclZipUtilCopyBlock()
// Description :
// Parameters :
// $p_mode : read/write compression mode
// 0 : src & dest normal
// 1 : src gzip, dest normal
// 2 : src normal, dest gzip
// 3 : src & dest gzip
// Return Values :
// --------------------------------------------------------------------------------
function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilCopyBlock", "size=$p_size, mode=$p_mode");
$v_result = 1;

if ($p_mode==0)
{
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset before read :".(@ftell($p_src)));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset before write :".(@ftell($p_dest)));
while ($p_size != 0)
{
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($p_src, $v_read_size);
@fwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset after read :".(@ftell($p_src)));
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset after write :".(@ftell($p_dest)));
}
else if ($p_mode==1)
{
while ($p_size != 0)
{
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @gzread($p_src, $v_read_size);
@fwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
}
else if ($p_mode==2)
{
while ($p_size != 0)
{
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($p_src, $v_read_size);
@gzwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
}
else if ($p_mode==3)
{
while ($p_size != 0)
{
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @gzread($p_src, $v_read_size);
@gzwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : PclZipUtilRename()
// Description :
// This function tries to do a simple rename() function. If it fails, it
// tries to copy the $p_src file in a new $p_dest file and then unlink the
// first one.
// Parameters :
// $p_src : Old filename
// $p_dest : New filename
// Return Values :
// 1 on success, 0 on failure.
// --------------------------------------------------------------------------------
function PclZipUtilRename($p_src, $p_dest)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilRename", "source=$p_src, destination=$p_dest");
$v_result = 1;

// ----- Try to rename the files
if (!@rename($p_src, $p_dest)) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to rename file, try copy+unlink");

// ----- Try to copy & unlink the src
if (!@copy($p_src, $p_dest)) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to copy file");
$v_result = 0;
}
else if (!@unlink($p_src)) {
//--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to unlink old filename");
$v_result = 0;
}
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// Function : PclZipUtilOptionText()
// Description :
// Translate option value in text. Mainly for debug purpose.
// Parameters :
// $p_option : the option value.
// Return Values :
// The option text value.
// --------------------------------------------------------------------------------
function PclZipUtilOptionText($p_option)
{
//--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilOptionText", "option='".$p_option."'");

switch ($p_option) {
case PCLZIP_OPT_PATH :
$v_result = 'PCLZIP_OPT_PATH';
break;
case PCLZIP_OPT_ADD_PATH :
$v_result = 'PCLZIP_OPT_ADD_PATH';
break;
case PCLZIP_OPT_REMOVE_PATH :
$v_result = 'PCLZIP_OPT_REMOVE_PATH';
break;
case PCLZIP_OPT_REMOVE_ALL_PATH :
$v_result = 'PCLZIP_OPT_REMOVE_ALL_PATH';
break;
case PCLZIP_OPT_SET_CHMOD :
$v_result = 'PCLZIP_OPT_SET_CHMOD';
break;


case PCLZIP_CB_PRE_EXTRACT :
$v_result = 'PCLZIP_CB_PRE_EXTRACT';
break;
case PCLZIP_CB_POST_EXTRACT :
$v_result = 'PCLZIP_CB_POST_EXTRACT';
break;
case PCLZIP_CB_PRE_ADD :
$v_result = 'PCLZIP_CB_PRE_ADD';
break;
case PCLZIP_CB_POST_ADD :
$v_result = 'PCLZIP_CB_POST_ADD';
break;

default :
$v_result = 'Unknown';
}

// ----- Return
//--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------

?>
then  put this code in the controller. Here extraction of zip file takeplace:-
here the zip file is extracted and put the extracted contents to the path specified...
if(!empty($_FILES['txtZip']['name'])){
$absDirName =Configure::read('ThemeDir');
mkdir($absDirName.$txtProject);
chmod($absDirName.$txtProject,0777);
$mediaPath1 = $absDirName. $txtProject.'/';
$mediaPath=$absDirName;
$this->Uploader->setDir($mediaPath);
$this->Uploader->setExtensions(array('zip'));
$this->Uploader->setMaxSize(8);
$this->Uploader->setSequence('project');
$filename1 = $_FILES['txtZip'];

if($this->Uploader->uploadFile($filename1)){ //upload thunbnail file//

echo $zipd = $this->Uploader->getUploadName();

echo $org = strtolower(trim($_FILES['txtZip']['name']));
echo $orgName = str_replace('.zip','',$org);
//extracting//
$archive = $this-> PclZip-> PclZip($mediaPath.'/'.$zipd);
//chmod($absDirName.$txtProject,0777);
if ( $this-> PclZip->extract(PCLZIP_OPT_PATH,$mediaPath.'/') == 0){
echo "failed";
exit;

}else {
echo "ok";

unlink($mediaPath.'/'.$zipd);


}