BackWPup – WordPress Backup Plugin - Version 0.8.1

Version Description

  • use global var instat of constant for log file
  • PCL Zip Trace included with setting for log Level
Download this release

Release Info

Developer danielhuesken
Plugin Icon 128x128 BackWPup – WordPress Backup Plugin
Version 0.8.1
Comparing to
See all releases

Code changes from version 0.8.0 to 0.8.1

app/backwpup_dojob.php CHANGED
@@ -6,6 +6,7 @@ if ( !defined('ABSPATH') )
6
 
7
  //function for PHP error handling
8
  function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
 
9
 
10
  switch ($errno) {
11
  case E_NOTICE:
@@ -15,19 +16,19 @@ function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
15
  break;
16
  case E_WARNING:
17
  case E_USER_WARNING:
18
- case E_CORE_WARNING;
19
  case E_COMPILE_WARNING:
20
  $errorstype = __("[WARNING]");
21
- $logheader=backwpup_read_logheader(BACKWPUP_LOGFILE); //read waring count from log header
22
  $warnings=$logheader['warnings']+1;
23
  $style=' style="background-color:yellow;"';
24
  break;
25
  case E_ERROR:
26
  case E_USER_ERROR:
27
- case E_CORE_ERROR;
28
- case E_COMPILE_ERROR;
29
  $errorstype = __("[ERROR]");
30
- $logheader=backwpup_read_logheader(BACKWPUP_LOGFILE); //read error count from log header
31
  $errors=$logheader['errors']+1;
32
  $style=' style="background-color:red;"';
33
  break;
@@ -57,7 +58,7 @@ function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
57
  $title="[Line: ".$errline."|File: ".basename($errfile)."|Mem: ".backwpup_formatBytes(@memory_get_usage())."|Mem Max: ".backwpup_formatBytes(@memory_get_peak_usage())."|Mem Limit: ".ini_get('memory_limit')."]";
58
 
59
  //wirte log file
60
- $fd=@fopen(BACKWPUP_LOGFILE,"a+");
61
  @fputs($fd,"<span style=\"background-color:c3c3c3;\" title=\"".$title."\">".date_i18n('Y-m-d H:i.s').":</span> <span".$style.">".$errorstype." ".$errstr."</span><br />\n");
62
  @fclose($fd);
63
 
@@ -66,7 +67,7 @@ function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
66
 
67
  //write new log header
68
  if (isset($errors) or isset($warnings)) {
69
- $fd=@fopen(BACKWPUP_LOGFILE,"r+");
70
  while (!feof($fd)) {
71
  $line=@fgets($fd);
72
  if (stripos($line,"<meta name=\"backwpup_errors\"") !== false and isset($errors)) {
@@ -94,8 +95,75 @@ function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
94
  return true;
95
  }
96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  /**
101
  * BackWPup PHP class for WordPress
@@ -115,8 +183,14 @@ class backwpup_dojob {
115
  private $job=array();
116
 
117
  public function __construct($jobid) {
 
 
 
118
  $this->jobid=$jobid; //set job id
119
  $this->cfg=get_option('backwpup'); //load config
 
 
 
120
  $jobs=get_option('backwpup_jobs'); //load jobdata
121
  $jobs[$this->jobid]['starttime']=time(); //set start time for job
122
  $jobs[$this->jobid]['stoptime']=''; //Set stop time for job
@@ -140,11 +214,11 @@ class backwpup_dojob {
140
  $this->backupfile='backwpup_'.$this->jobid.'_'.date_i18n('Y-m-d_H-i-s').'.zip';
141
  //set Log file name
142
  $this->logfile='backwpup_log_'.date_i18n('Y-m-d_H-i-s').'.html';
143
- define('BACKWPUP_LOGFILE',$this->logdir.'/'.$this->logfile);
144
  //Create log file
145
  if (!$this->_check_folders($this->logdir))
146
  return false;
147
- $fd=@fopen(BACKWPUP_LOGFILE,"a+");
148
  @fputs($fd,"<html>\n<head>\n");
149
  @fputs($fd,"<meta name=\"backwpup_version\" content=\"".BACKWPUP_VERSION."\" />\n");
150
  @fputs($fd,"<meta name=\"backwpup_logtime\" content=\"".time()."\" />\n");
@@ -575,6 +649,9 @@ class backwpup_dojob {
575
  public function zip_files() {
576
 
577
  define( 'PCLZIP_TEMPORARY_DIR', $this->tempdir );
 
 
 
578
 
579
  if (!is_array($this->filelist[0])) {
580
  trigger_error(__('No files to Backup','backwpup'),E_USER_ERROR);
@@ -586,7 +663,6 @@ class backwpup_dojob {
586
  if (is_array($this->filelist[0])) {
587
  $this->need_free_memory(10485760); //10MB free memory for zip
588
  trigger_error(__('Create Backup Zip file...','backwpup'),E_USER_NOTICE);
589
- if (!class_exists('PclZip')) require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
590
  $zipbackupfile = new PclZip($this->backupdir.'/'.$this->backupfile);
591
  if (0==$zipbackupfile -> create($this->filelist,PCLZIP_OPT_ADD_TEMP_FILE_ON)) {
592
  trigger_error(__('Zip file create:','backwpup').' '.$zipbackupfile->errorInfo(true),E_USER_ERROR);
@@ -873,6 +949,8 @@ class backwpup_dojob {
873
  }
874
 
875
  public function __destruct() {
 
 
876
  if (is_file($this->backupdir.'/'.$this->backupfile)) {
877
  trigger_error(sprintf(__('Backup ZIP File size is %1s','backwpup'),backwpup_formatBytes(filesize($this->backupdir.'/'.$this->backupfile))),E_USER_NOTICE);
878
  }
@@ -915,7 +993,7 @@ class backwpup_dojob {
915
  trigger_error(sprintf(__('Job done in %1s sec.','backwpup'),$jobs[$this->jobid]['lastruntime']),E_USER_NOTICE);
916
 
917
  //write runtime header
918
- $fd=@fopen(BACKWPUP_LOGFILE,"r+");
919
  while (!feof($fd)) {
920
  $line=@fgets($fd);
921
  if (stripos($line,"<meta name=\"backwpup_jobruntime\"") !== false) {
@@ -927,11 +1005,11 @@ class backwpup_dojob {
927
  }
928
  @fclose($fd);
929
  //logfile end
930
- $fd=fopen(BACKWPUP_LOGFILE,"a+");
931
  fputs($fd,"</body>\n</html>\n");
932
  fclose($fd);
933
  restore_error_handler();
934
- $logdata=backwpup_read_logheader(BACKWPUP_LOGFILE);
935
  //Send mail with log
936
  $sendmail=false;
937
  if ($logdata['errors']>0 and $this->job['mailerroronly'] and !empty($this->job['mailaddresslog']))
6
 
7
  //function for PHP error handling
8
  function backwpup_joberrorhandler($errno, $errstr, $errfile, $errline) {
9
+ global $backwpup_logfile;
10
 
11
  switch ($errno) {
12
  case E_NOTICE:
16
  break;
17
  case E_WARNING:
18
  case E_USER_WARNING:
19
+ case E_CORE_WARNING:
20
  case E_COMPILE_WARNING:
21
  $errorstype = __("[WARNING]");
22
+ $logheader=backwpup_read_logheader($backwpup_logfile); //read waring count from log header
23
  $warnings=$logheader['warnings']+1;
24
  $style=' style="background-color:yellow;"';
25
  break;
26
  case E_ERROR:
27
  case E_USER_ERROR:
28
+ case E_CORE_ERROR:
29
+ case E_COMPILE_ERROR:
30
  $errorstype = __("[ERROR]");
31
+ $logheader=backwpup_read_logheader($backwpup_logfile); //read error count from log header
32
  $errors=$logheader['errors']+1;
33
  $style=' style="background-color:red;"';
34
  break;
58
  $title="[Line: ".$errline."|File: ".basename($errfile)."|Mem: ".backwpup_formatBytes(@memory_get_usage())."|Mem Max: ".backwpup_formatBytes(@memory_get_peak_usage())."|Mem Limit: ".ini_get('memory_limit')."]";
59
 
60
  //wirte log file
61
+ $fd=@fopen($backwpup_logfile,"a+");
62
  @fputs($fd,"<span style=\"background-color:c3c3c3;\" title=\"".$title."\">".date_i18n('Y-m-d H:i.s').":</span> <span".$style.">".$errorstype." ".$errstr."</span><br />\n");
63
  @fclose($fd);
64
 
67
 
68
  //write new log header
69
  if (isset($errors) or isset($warnings)) {
70
+ $fd=@fopen($backwpup_logfile,"r+");
71
  while (!feof($fd)) {
72
  $line=@fgets($fd);
73
  if (stripos($line,"<meta name=\"backwpup_errors\"") !== false and isset($errors)) {
95
  return true;
96
  }
97
 
98
+ //PCL Zip trace functions
99
+ function PclTraceFctStart($p_file, $p_line, $p_name, $p_param="", $p_message="") {
100
+ return;
101
+ }
102
+ function TrFctStart($p_file, $p_line, $p_name, $p_param="", $p_message="") {
103
+ return;
104
+ }
105
+ function PclTraceFctEnd($p_file, $p_line, $p_level=1, $p_message="") {
106
+ return;
107
+ }
108
+ function TrFctEnd($p_file, $p_line, $p_level=1, $p_message="") {
109
+ return;
110
+ }
111
+ function PclTraceFctMessage($p_file, $p_line, $p_level, $p_message="") {
112
+ TrFctMessage($p_file, $p_line, $p_level, $p_message);
113
+ }
114
+ function TrFctMessage($p_file, $p_line, $p_level, $p_message="") {
115
+ global $backwpup_logfile;
116
+ global $backwpup_pcl_log_level;
117
+
118
+ if (($backwpup_pcl_log_level < $p_level))
119
+ return;
120
 
121
+ switch ($p_level) {
122
+ case 1:
123
+ $errorstype = __("[PCLZIP ERROR]");
124
+ $logheader=backwpup_read_logheader($backwpup_logfile); //read error count from log header
125
+ $errors=$logheader['errors']+1;
126
+ $style=' style="background-color:red;"';
127
+ break;
128
+ default:
129
+ $errorstype = "[PCLZIP ".$p_level."]";
130
+ $style='';
131
+ break;
132
+ }
133
 
134
+ $title="[Line: ".$p_line."|File: ".basename($p_file)."|Mem: ".backwpup_formatBytes(@memory_get_usage())."|Mem Max: ".backwpup_formatBytes(@memory_get_peak_usage())."|Mem Limit: ".ini_get('memory_limit')."]";
135
+
136
+ //wirte log file
137
+ $fd=@fopen($backwpup_logfile,"a+");
138
+ @fputs($fd,"<span style=\"background-color:c3c3c3;\" title=\"".$title."\">".date_i18n('Y-m-d H:i.s').":</span> <span".$style.">".$errorstype." ".$p_message."</span><br />\n");
139
+ @fclose($fd);
140
+
141
+ if (!defined('DOING_CRON'))
142
+ echo "<span style=\"background-color:c3c3c3;\" title=\"".$title."\">".date_i18n('Y-m-d H:i.s').":</span> <span".$style.">".$errorstype." ".$p_message."</span><script type=\"text/javascript\">window.scrollBy(0, 15);</script><br />\n";
143
+
144
+ //write new log header
145
+ if (isset($errors) or isset($warnings)) {
146
+ $fd=@fopen($backwpup_logfile,"r+");
147
+ while (!feof($fd)) {
148
+ $line=@fgets($fd);
149
+ if (stripos($line,"<meta name=\"backwpup_errors\"") !== false and isset($errors)) {
150
+ @fseek($fd,$filepos);
151
+ @fputs($fd,"<meta name=\"backwpup_errors\" content=\"".$errors."\" />".backwpup_fillspases(4-strlen($errors))."\n");
152
+ break;
153
+ }
154
+ if (stripos($line,"<meta name=\"backwpup_warnings\"") !== false and isset($warnings)) {
155
+ @fseek($fd,$filepos);
156
+ @fputs($fd,"<meta name=\"backwpup_warnings\" content=\"".$warnings."\" />".backwpup_fillspases(4-strlen($warnings))."\n");
157
+ break;
158
+ }
159
+ $filepos=ftell($fd);
160
+ }
161
+ @fclose($fd);
162
+ }
163
+
164
+ @flush();
165
+ }
166
+
167
 
168
  /**
169
  * BackWPup PHP class for WordPress
183
  private $job=array();
184
 
185
  public function __construct($jobid) {
186
+ global $backwpup_logfile;
187
+ global $backwpup_pcl_log_level;
188
+
189
  $this->jobid=$jobid; //set job id
190
  $this->cfg=get_option('backwpup'); //load config
191
+ $backwpup_pcl_log_level=$this->cfg['pcl_log_level'];
192
+ if ($backwpup_pcl_log_level<1 or $backwpup_pcl_log_level>5) //set to 1 for false values
193
+ $backwpup_pcl_log_level=1;
194
  $jobs=get_option('backwpup_jobs'); //load jobdata
195
  $jobs[$this->jobid]['starttime']=time(); //set start time for job
196
  $jobs[$this->jobid]['stoptime']=''; //Set stop time for job
214
  $this->backupfile='backwpup_'.$this->jobid.'_'.date_i18n('Y-m-d_H-i-s').'.zip';
215
  //set Log file name
216
  $this->logfile='backwpup_log_'.date_i18n('Y-m-d_H-i-s').'.html';
217
+ $backwpup_logfile=$this->logdir.'/'.$this->logfile;
218
  //Create log file
219
  if (!$this->_check_folders($this->logdir))
220
  return false;
221
+ $fd=@fopen($backwpup_logfile,"a+");
222
  @fputs($fd,"<html>\n<head>\n");
223
  @fputs($fd,"<meta name=\"backwpup_version\" content=\"".BACKWPUP_VERSION."\" />\n");
224
  @fputs($fd,"<meta name=\"backwpup_logtime\" content=\"".time()."\" />\n");
649
  public function zip_files() {
650
 
651
  define( 'PCLZIP_TEMPORARY_DIR', $this->tempdir );
652
+ if (!class_exists('PclZip')) require_once 'libs/pclzip-trace.lib.php';
653
+
654
+
655
 
656
  if (!is_array($this->filelist[0])) {
657
  trigger_error(__('No files to Backup','backwpup'),E_USER_ERROR);
663
  if (is_array($this->filelist[0])) {
664
  $this->need_free_memory(10485760); //10MB free memory for zip
665
  trigger_error(__('Create Backup Zip file...','backwpup'),E_USER_NOTICE);
 
666
  $zipbackupfile = new PclZip($this->backupdir.'/'.$this->backupfile);
667
  if (0==$zipbackupfile -> create($this->filelist,PCLZIP_OPT_ADD_TEMP_FILE_ON)) {
668
  trigger_error(__('Zip file create:','backwpup').' '.$zipbackupfile->errorInfo(true),E_USER_ERROR);
949
  }
950
 
951
  public function __destruct() {
952
+ global $backwpup_logfile;
953
+
954
  if (is_file($this->backupdir.'/'.$this->backupfile)) {
955
  trigger_error(sprintf(__('Backup ZIP File size is %1s','backwpup'),backwpup_formatBytes(filesize($this->backupdir.'/'.$this->backupfile))),E_USER_NOTICE);
956
  }
993
  trigger_error(sprintf(__('Job done in %1s sec.','backwpup'),$jobs[$this->jobid]['lastruntime']),E_USER_NOTICE);
994
 
995
  //write runtime header
996
+ $fd=@fopen($backwpup_logfile,"r+");
997
  while (!feof($fd)) {
998
  $line=@fgets($fd);
999
  if (stripos($line,"<meta name=\"backwpup_jobruntime\"") !== false) {
1005
  }
1006
  @fclose($fd);
1007
  //logfile end
1008
+ $fd=fopen($backwpup_logfile,"a+");
1009
  fputs($fd,"</body>\n</html>\n");
1010
  fclose($fd);
1011
  restore_error_handler();
1012
+ $logdata=backwpup_read_logheader($backwpup_logfile);
1013
  //Send mail with log
1014
  $sendmail=false;
1015
  if ($logdata['errors']>0 and $this->job['mailerroronly'] and !empty($this->job['mailaddresslog']))
app/functions.php CHANGED
@@ -111,6 +111,7 @@ if ( !defined('ABSPATH') )
111
  if (empty($cfg['mailsendmail'])) $cfg['mailsendmail']=substr(ini_get('sendmail_path'),0,strpos(ini_get('sendmail_path'),' -'));
112
  if (empty($cfg['memorylimit'])) $cfg['memorylimit']='128M';
113
  if (empty($cfg['maxlogs'])) $cfg['maxlogs']=0;
 
114
  if (empty($cfg['dirlogs'])) $cfg['dirlogs']=str_replace('\\','/',stripslashes(get_temp_dir().'backwpup/logs'));
115
  if (empty($cfg['dirtemp'])) $cfg['dirtemp']=str_replace('\\','/',stripslashes(get_temp_dir().'backwpup'));
116
  update_option('backwpup',$cfg);
@@ -162,6 +163,7 @@ if ( !defined('ABSPATH') )
162
 
163
  //DoJob
164
  function backwpup_dojob($args) {
 
165
  if (is_array($args)) { //cron gifes no complete array back!!!
166
  extract($args, EXTR_SKIP );
167
  } else {
@@ -255,7 +257,7 @@ if ( !defined('ABSPATH') )
255
  echo '<strong>'.__('Logs:','backwpup').'</strong><br />';
256
  //get log files
257
  $logfiles=array();
258
- if ( $dir = opendir( $cfg['dirlogs'] ) ) {
259
  while (($file = readdir( $dir ) ) !== false ) {
260
  if (is_file($cfg['dirlogs'].'/'.$file) and 'backwpup_log_' == substr($file,0,strlen('backwpup_log_')) and '.html' == substr($file,-5))
261
  $logfiles[]=$file;
111
  if (empty($cfg['mailsendmail'])) $cfg['mailsendmail']=substr(ini_get('sendmail_path'),0,strpos(ini_get('sendmail_path'),' -'));
112
  if (empty($cfg['memorylimit'])) $cfg['memorylimit']='128M';
113
  if (empty($cfg['maxlogs'])) $cfg['maxlogs']=0;
114
+ if (empty($cfg['pcl_log_level'])) $cfg['pcl_log_level']=1;
115
  if (empty($cfg['dirlogs'])) $cfg['dirlogs']=str_replace('\\','/',stripslashes(get_temp_dir().'backwpup/logs'));
116
  if (empty($cfg['dirtemp'])) $cfg['dirtemp']=str_replace('\\','/',stripslashes(get_temp_dir().'backwpup'));
117
  update_option('backwpup',$cfg);
163
 
164
  //DoJob
165
  function backwpup_dojob($args) {
166
+ global $backwpup_logfile;
167
  if (is_array($args)) { //cron gifes no complete array back!!!
168
  extract($args, EXTR_SKIP );
169
  } else {
257
  echo '<strong>'.__('Logs:','backwpup').'</strong><br />';
258
  //get log files
259
  $logfiles=array();
260
+ if ( $dir = @opendir( $cfg['dirlogs'] ) ) {
261
  while (($file = readdir( $dir ) ) !== false ) {
262
  if (is_file($cfg['dirlogs'].'/'.$file) and 'backwpup_log_' == substr($file,0,strlen('backwpup_log_')) and '.html' == substr($file,-5))
263
  $logfiles[]=$file;
app/libs/pclzip-trace.lib.php ADDED
@@ -0,0 +1,6376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // --------------------------------------------------------------------------------
3
+ // PhpConcept Library - Zip Module 2.8.2
4
+ // --------------------------------------------------------------------------------
5
+ // License GNU/LGPL - Vincent Blavet - August 2009
6
+ // http://www.phpconcept.net
7
+ // --------------------------------------------------------------------------------
8
+ //
9
+ // Presentation :
10
+ // PclZip is a PHP library that manage ZIP archives.
11
+ // So far tests show that archives generated by PclZip are readable by
12
+ // WinZip application and other tools.
13
+ //
14
+ // Description :
15
+ // See readme.txt and http://www.phpconcept.net
16
+ //
17
+ // Warning :
18
+ // This library and the associated files are non commercial, non professional
19
+ // work.
20
+ // It should not have unexpected results. However if any damage is caused by
21
+ // this software the author can not be responsible.
22
+ // The use of this software is at the risk of the user.
23
+ //
24
+ // --------------------------------------------------------------------------------
25
+ // $Id: pclzip-trace.lib.php,v 1.73 2009/09/30 21:00:06 vblavet Exp $
26
+ // --------------------------------------------------------------------------------
27
+
28
+ // ----- Constants
29
+ if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
30
+ define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
31
+ }
32
+
33
+ // ----- File list separator
34
+ // In version 1.x of PclZip, the separator for file list is a space
35
+ // (which is not a very smart choice, specifically for windows paths !).
36
+ // A better separator should be a comma (,). This constant gives you the
37
+ // abilty to change that.
38
+ // However notice that changing this value, may have impact on existing
39
+ // scripts, using space separated filenames.
40
+ // Recommanded values for compatibility with older versions :
41
+ //define( 'PCLZIP_SEPARATOR', ' ' );
42
+ // Recommanded values for smart separation of filenames.
43
+ if (!defined('PCLZIP_SEPARATOR')) {
44
+ define( 'PCLZIP_SEPARATOR', ',' );
45
+ }
46
+
47
+ // ----- Error configuration
48
+ // 0 : PclZip Class integrated error handling
49
+ // 1 : PclError external library error handling. By enabling this
50
+ // you must ensure that you have included PclError library.
51
+ // [2,...] : reserved for futur use
52
+ if (!defined('PCLZIP_ERROR_EXTERNAL')) {
53
+ define( 'PCLZIP_ERROR_EXTERNAL', 0 );
54
+ }
55
+
56
+ // ----- Optional static temporary directory
57
+ // By default temporary files are generated in the script current
58
+ // path.
59
+ // If defined :
60
+ // - MUST BE terminated by a '/'.
61
+ // - MUST be a valid, already created directory
62
+ // Samples :
63
+ // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
64
+ // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
65
+ if (!defined('PCLZIP_TEMPORARY_DIR')) {
66
+ define( 'PCLZIP_TEMPORARY_DIR', '' );
67
+ }
68
+
69
+ // ----- Optional threshold ratio for use of temporary files
70
+ // Pclzip sense the size of the file to add/extract and decide to
71
+ // use or not temporary file. The algorythm is looking for
72
+ // memory_limit of PHP and apply a ratio.
73
+ // threshold = memory_limit * ratio.
74
+ // Recommended values are under 0.5. Default 0.47.
75
+ // Samples :
76
+ // define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 );
77
+ if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) {
78
+ define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 );
79
+ }
80
+
81
+ // --------------------------------------------------------------------------------
82
+ // ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
83
+ // --------------------------------------------------------------------------------
84
+
85
+ // ----- Global variables
86
+ $g_pclzip_version = "2.8.2";
87
+
88
+ // ----- Error codes
89
+ // -1 : Unable to open file in binary write mode
90
+ // -2 : Unable to open file in binary read mode
91
+ // -3 : Invalid parameters
92
+ // -4 : File does not exist
93
+ // -5 : Filename is too long (max. 255)
94
+ // -6 : Not a valid zip file
95
+ // -7 : Invalid extracted file size
96
+ // -8 : Unable to create directory
97
+ // -9 : Invalid archive extension
98
+ // -10 : Invalid archive format
99
+ // -11 : Unable to delete file (unlink)
100
+ // -12 : Unable to rename file (rename)
101
+ // -13 : Invalid header checksum
102
+ // -14 : Invalid archive size
103
+ define( 'PCLZIP_ERR_USER_ABORTED', 2 );
104
+ define( 'PCLZIP_ERR_NO_ERROR', 0 );
105
+ define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
106
+ define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
107
+ define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
108
+ define( 'PCLZIP_ERR_MISSING_FILE', -4 );
109
+ define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
110
+ define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
111
+ define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
112
+ define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
113
+ define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
114
+ define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
115
+ define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
116
+ define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
117
+ define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
118
+ define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
119
+ define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
120
+ define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
121
+ define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
122
+ define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
123
+ define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
124
+ define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
125
+ define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
126
+
127
+ // ----- Options values
128
+ define( 'PCLZIP_OPT_PATH', 77001 );
129
+ define( 'PCLZIP_OPT_ADD_PATH', 77002 );
130
+ define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
131
+ define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
132
+ define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
133
+ define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
134
+ define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
135
+ define( 'PCLZIP_OPT_BY_NAME', 77008 );
136
+ define( 'PCLZIP_OPT_BY_INDEX', 77009 );
137
+ define( 'PCLZIP_OPT_BY_EREG', 77010 );
138
+ define( 'PCLZIP_OPT_BY_PREG', 77011 );
139
+ define( 'PCLZIP_OPT_COMMENT', 77012 );
140
+ define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
141
+ define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
142
+ define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
143
+ define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
144
+ define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
145
+ // Having big trouble with crypt. Need to multiply 2 long int
146
+ // which is not correctly supported by PHP ...
147
+ //define( 'PCLZIP_OPT_CRYPT', 77018 );
148
+ define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
149
+ define( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 );
150
+ define( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias
151
+ define( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 );
152
+ define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
153
+ define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
154
+ define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
155
+
156
+ // ----- File description attributes
157
+ define( 'PCLZIP_ATT_FILE_NAME', 79001 );
158
+ define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
159
+ define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
160
+ define( 'PCLZIP_ATT_FILE_MTIME', 79004 );
161
+ define( 'PCLZIP_ATT_FILE_CONTENT', 79005 );
162
+ define( 'PCLZIP_ATT_FILE_COMMENT', 79006 );
163
+
164
+ // ----- Call backs values
165
+ define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
166
+ define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
167
+ define( 'PCLZIP_CB_PRE_ADD', 78003 );
168
+ define( 'PCLZIP_CB_POST_ADD', 78004 );
169
+ /* For futur use
170
+ define( 'PCLZIP_CB_PRE_LIST', 78005 );
171
+ define( 'PCLZIP_CB_POST_LIST', 78006 );
172
+ define( 'PCLZIP_CB_PRE_DELETE', 78007 );
173
+ define( 'PCLZIP_CB_POST_DELETE', 78008 );
174
+ */
175
+
176
+ // --------------------------------------------------------------------------------
177
+ // Class : PclZip
178
+ // Description :
179
+ // PclZip is the class that represent a Zip archive.
180
+ // The public methods allow the manipulation of the archive.
181
+ // Attributes :
182
+ // Attributes must not be accessed directly.
183
+ // Methods :
184
+ // PclZip() : Object creator
185
+ // create() : Creates the Zip archive
186
+ // listContent() : List the content of the Zip archive
187
+ // extract() : Extract the content of the archive
188
+ // properties() : List the properties of the archive
189
+ // --------------------------------------------------------------------------------
190
+ class PclZip
191
+ {
192
+ // ----- Filename of the zip file
193
+ var $zipname = '';
194
+
195
+ // ----- File descriptor of the zip file
196
+ var $zip_fd = 0;
197
+
198
+ // ----- Internal error handling
199
+ var $error_code = 1;
200
+ var $error_string = '';
201
+
202
+ // ----- Current status of the magic_quotes_runtime
203
+ // This value store the php configuration for magic_quotes
204
+ // The class can then disable the magic_quotes and reset it after
205
+ var $magic_quotes_status;
206
+
207
+ // --------------------------------------------------------------------------------
208
+ // Function : PclZip()
209
+ // Description :
210
+ // Creates a PclZip object and set the name of the associated Zip archive
211
+ // filename.
212
+ // Note that no real action is taken, if the archive does not exist it is not
213
+ // created. Use create() for that.
214
+ // --------------------------------------------------------------------------------
215
+ function PclZip($p_zipname)
216
+ {
217
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::PclZip', "zipname=$p_zipname");
218
+
219
+ // ----- Tests the zlib
220
+ if (!function_exists('gzopen'))
221
+ {
222
+ PclTraceFctMessage(__FILE__, __LINE__, 1, "zlib extension seems to be missing");
223
+ die('Abort '.basename(__FILE__).' : Missing zlib extensions');
224
+ }
225
+
226
+ // ----- Set the attributes
227
+ $this->zipname = $p_zipname;
228
+ $this->zip_fd = 0;
229
+ $this->magic_quotes_status = -1;
230
+
231
+ // ----- Return
232
+ PclTraceFctEnd(__FILE__, __LINE__, 1);
233
+ return;
234
+ }
235
+ // --------------------------------------------------------------------------------
236
+
237
+ // --------------------------------------------------------------------------------
238
+ // Function :
239
+ // create($p_filelist, $p_add_dir="", $p_remove_dir="")
240
+ // create($p_filelist, $p_option, $p_option_value, ...)
241
+ // Description :
242
+ // This method supports two different synopsis. The first one is historical.
243
+ // This method creates a Zip Archive. The Zip file is created in the
244
+ // filesystem. The files and directories indicated in $p_filelist
245
+ // are added in the archive. See the parameters description for the
246
+ // supported format of $p_filelist.
247
+ // When a directory is in the list, the directory and its content is added
248
+ // in the archive.
249
+ // In this synopsis, the function takes an optional variable list of
250
+ // options. See bellow the supported options.
251
+ // Parameters :
252
+ // $p_filelist : An array containing file or directory names, or
253
+ // a string containing one filename or one directory name, or
254
+ // a string containing a list of filenames and/or directory
255
+ // names separated by spaces.
256
+ // $p_add_dir : A path to add before the real path of the archived file,
257
+ // in order to have it memorized in the archive.
258
+ // $p_remove_dir : A path to remove from the real path of the file to archive,
259
+ // in order to have a shorter path memorized in the archive.
260
+ // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
261
+ // is removed first, before $p_add_dir is added.
262
+ // Options :
263
+ // PCLZIP_OPT_ADD_PATH :
264
+ // PCLZIP_OPT_REMOVE_PATH :
265
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
266
+ // PCLZIP_OPT_COMMENT :
267
+ // PCLZIP_CB_PRE_ADD :
268
+ // PCLZIP_CB_POST_ADD :
269
+ // Return Values :
270
+ // 0 on failure,
271
+ // The list of the added files, with a status of the add action.
272
+ // (see PclZip::listContent() for list entry format)
273
+ // --------------------------------------------------------------------------------
274
+ function create($p_filelist)
275
+ {
276
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::create', "filelist='$p_filelist', ...");
277
+ $v_result=1;
278
+
279
+ // ----- Reset the error handler
280
+ $this->privErrorReset();
281
+
282
+ // ----- Set default values
283
+ $v_options = array();
284
+ $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
285
+
286
+ // ----- Look for variable options arguments
287
+ $v_size = func_num_args();
288
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
289
+
290
+ // ----- Look for arguments
291
+ if ($v_size > 1) {
292
+ // ----- Get the arguments
293
+ $v_arg_list = func_get_args();
294
+
295
+ // ----- Remove from the options list the first argument
296
+ array_shift($v_arg_list);
297
+ $v_size--;
298
+
299
+ // ----- Look for first arg
300
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
301
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
302
+
303
+ // ----- Parse the options
304
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
305
+ array (PCLZIP_OPT_REMOVE_PATH => 'optional',
306
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
307
+ PCLZIP_OPT_ADD_PATH => 'optional',
308
+ PCLZIP_CB_PRE_ADD => 'optional',
309
+ PCLZIP_CB_POST_ADD => 'optional',
310
+ PCLZIP_OPT_NO_COMPRESSION => 'optional',
311
+ PCLZIP_OPT_COMMENT => 'optional',
312
+ PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
313
+ PCLZIP_OPT_TEMP_FILE_ON => 'optional',
314
+ PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
315
+ //, PCLZIP_OPT_CRYPT => 'optional'
316
+ ));
317
+ if ($v_result != 1) {
318
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
319
+ return 0;
320
+ }
321
+ }
322
+
323
+ // ----- Look for 2 args
324
+ // Here we need to support the first historic synopsis of the
325
+ // method.
326
+ else {
327
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
328
+
329
+ // ----- Get the first argument
330
+ $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
331
+
332
+ // ----- Look for the optional second argument
333
+ if ($v_size == 2) {
334
+ $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
335
+ }
336
+ else if ($v_size > 2) {
337
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
338
+ "Invalid number / type of arguments");
339
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
340
+ return 0;
341
+ }
342
+ }
343
+ }
344
+
345
+ // ----- Look for default option values
346
+ $this->privOptionDefaultThreshold($v_options);
347
+
348
+ // ----- Init
349
+ $v_string_list = array();
350
+ $v_att_list = array();
351
+ $v_filedescr_list = array();
352
+ $p_result_list = array();
353
+
354
+ // ----- Look if the $p_filelist is really an array
355
+ if (is_array($p_filelist)) {
356
+
357
+ // ----- Look if the first element is also an array
358
+ // This will mean that this is a file description entry
359
+ if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
360
+ $v_att_list = $p_filelist;
361
+ }
362
+
363
+ // ----- The list is a list of string names
364
+ else {
365
+ $v_string_list = $p_filelist;
366
+ }
367
+ }
368
+
369
+ // ----- Look if the $p_filelist is a string
370
+ else if (is_string($p_filelist)) {
371
+ // ----- Create a list from the string
372
+ $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
373
+ }
374
+
375
+ // ----- Invalid variable type for $p_filelist
376
+ else {
377
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
378
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
379
+ return 0;
380
+ }
381
+
382
+ // ----- Reformat the string list
383
+ if (sizeof($v_string_list) != 0) {
384
+ foreach ($v_string_list as $v_string) {
385
+ if ($v_string != '') {
386
+ $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
387
+ }
388
+ else {
389
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Ignore an empty filename");
390
+ }
391
+ }
392
+ }
393
+
394
+ // ----- For each file in the list check the attributes
395
+ $v_supported_attributes
396
+ = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
397
+ ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
398
+ ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
399
+ ,PCLZIP_ATT_FILE_MTIME => 'optional'
400
+ ,PCLZIP_ATT_FILE_CONTENT => 'optional'
401
+ ,PCLZIP_ATT_FILE_COMMENT => 'optional'
402
+ );
403
+ foreach ($v_att_list as $v_entry) {
404
+ $v_result = $this->privFileDescrParseAtt($v_entry,
405
+ $v_filedescr_list[],
406
+ $v_options,
407
+ $v_supported_attributes);
408
+ if ($v_result != 1) {
409
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
410
+ return 0;
411
+ }
412
+ }
413
+
414
+ // ----- Expand the filelist (expand directories)
415
+ $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
416
+ if ($v_result != 1) {
417
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
418
+ return 0;
419
+ }
420
+
421
+ // ----- Call the create fct
422
+ $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
423
+ if ($v_result != 1) {
424
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
425
+ return 0;
426
+ }
427
+
428
+ // ----- Return
429
+ PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
430
+ return $p_result_list;
431
+ }
432
+ // --------------------------------------------------------------------------------
433
+
434
+ // --------------------------------------------------------------------------------
435
+ // Function :
436
+ // add($p_filelist, $p_add_dir="", $p_remove_dir="")
437
+ // add($p_filelist, $p_option, $p_option_value, ...)
438
+ // Description :
439
+ // This method supports two synopsis. The first one is historical.
440
+ // This methods add the list of files in an existing archive.
441
+ // If a file with the same name already exists, it is added at the end of the
442
+ // archive, the first one is still present.
443
+ // If the archive does not exist, it is created.
444
+ // Parameters :
445
+ // $p_filelist : An array containing file or directory names, or
446
+ // a string containing one filename or one directory name, or
447
+ // a string containing a list of filenames and/or directory
448
+ // names separated by spaces.
449
+ // $p_add_dir : A path to add before the real path of the archived file,
450
+ // in order to have it memorized in the archive.
451
+ // $p_remove_dir : A path to remove from the real path of the file to archive,
452
+ // in order to have a shorter path memorized in the archive.
453
+ // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
454
+ // is removed first, before $p_add_dir is added.
455
+ // Options :
456
+ // PCLZIP_OPT_ADD_PATH :
457
+ // PCLZIP_OPT_REMOVE_PATH :
458
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
459
+ // PCLZIP_OPT_COMMENT :
460
+ // PCLZIP_OPT_ADD_COMMENT :
461
+ // PCLZIP_OPT_PREPEND_COMMENT :
462
+ // PCLZIP_CB_PRE_ADD :
463
+ // PCLZIP_CB_POST_ADD :
464
+ // Return Values :
465
+ // 0 on failure,
466
+ // The list of the added files, with a status of the add action.
467
+ // (see PclZip::listContent() for list entry format)
468
+ // --------------------------------------------------------------------------------
469
+ function add($p_filelist)
470
+ {
471
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::add', "filelist='$p_filelist', ...");
472
+ $v_result=1;
473
+
474
+ // ----- Reset the error handler
475
+ $this->privErrorReset();
476
+
477
+ // ----- Set default values
478
+ $v_options = array();
479
+ $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
480
+
481
+ // ----- Look for variable options arguments
482
+ $v_size = func_num_args();
483
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
484
+
485
+ // ----- Look for arguments
486
+ if ($v_size > 1) {
487
+ // ----- Get the arguments
488
+ $v_arg_list = func_get_args();
489
+
490
+ // ----- Remove form the options list the first argument
491
+ array_shift($v_arg_list);
492
+ $v_size--;
493
+
494
+ // ----- Look for first arg
495
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
496
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
497
+
498
+ // ----- Parse the options
499
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
500
+ array (PCLZIP_OPT_REMOVE_PATH => 'optional',
501
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
502
+ PCLZIP_OPT_ADD_PATH => 'optional',
503
+ PCLZIP_CB_PRE_ADD => 'optional',
504
+ PCLZIP_CB_POST_ADD => 'optional',
505
+ PCLZIP_OPT_NO_COMPRESSION => 'optional',
506
+ PCLZIP_OPT_COMMENT => 'optional',
507
+ PCLZIP_OPT_ADD_COMMENT => 'optional',
508
+ PCLZIP_OPT_PREPEND_COMMENT => 'optional',
509
+ PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
510
+ PCLZIP_OPT_TEMP_FILE_ON => 'optional',
511
+ PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
512
+ //, PCLZIP_OPT_CRYPT => 'optional'
513
+ ));
514
+ if ($v_result != 1) {
515
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
516
+ return 0;
517
+ }
518
+ }
519
+
520
+ // ----- Look for 2 args
521
+ // Here we need to support the first historic synopsis of the
522
+ // method.
523
+ else {
524
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
525
+
526
+ // ----- Get the first argument
527
+ $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
528
+
529
+ // ----- Look for the optional second argument
530
+ if ($v_size == 2) {
531
+ $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
532
+ }
533
+ else if ($v_size > 2) {
534
+ // ----- Error log
535
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
536
+
537
+ // ----- Return
538
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
539
+ return 0;
540
+ }
541
+ }
542
+ }
543
+
544
+ // ----- Look for default option values
545
+ $this->privOptionDefaultThreshold($v_options);
546
+
547
+ // ----- Init
548
+ $v_string_list = array();
549
+ $v_att_list = array();
550
+ $v_filedescr_list = array();
551
+ $p_result_list = array();
552
+
553
+ // ----- Look if the $p_filelist is really an array
554
+ if (is_array($p_filelist)) {
555
+
556
+ // ----- Look if the first element is also an array
557
+ // This will mean that this is a file description entry
558
+ if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
559
+ $v_att_list = $p_filelist;
560
+ }
561
+
562
+ // ----- The list is a list of string names
563
+ else {
564
+ $v_string_list = $p_filelist;
565
+ }
566
+ }
567
+
568
+ // ----- Look if the $p_filelist is a string
569
+ else if (is_string($p_filelist)) {
570
+ // ----- Create a list from the string
571
+ $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
572
+ }
573
+
574
+ // ----- Invalid variable type for $p_filelist
575
+ else {
576
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
577
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
578
+ return 0;
579
+ }
580
+
581
+ // ----- Reformat the string list
582
+ if (sizeof($v_string_list) != 0) {
583
+ foreach ($v_string_list as $v_string) {
584
+ $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
585
+ }
586
+ }
587
+
588
+ // ----- For each file in the list check the attributes
589
+ $v_supported_attributes
590
+ = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
591
+ ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
592
+ ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
593
+ ,PCLZIP_ATT_FILE_MTIME => 'optional'
594
+ ,PCLZIP_ATT_FILE_CONTENT => 'optional'
595
+ ,PCLZIP_ATT_FILE_COMMENT => 'optional'
596
+ );
597
+ foreach ($v_att_list as $v_entry) {
598
+ $v_result = $this->privFileDescrParseAtt($v_entry,
599
+ $v_filedescr_list[],
600
+ $v_options,
601
+ $v_supported_attributes);
602
+ if ($v_result != 1) {
603
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
604
+ return 0;
605
+ }
606
+ }
607
+
608
+ // ----- Expand the filelist (expand directories)
609
+ $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
610
+ if ($v_result != 1) {
611
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
612
+ return 0;
613
+ }
614
+
615
+ // ----- Call the create fct
616
+ $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
617
+ if ($v_result != 1) {
618
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
619
+ return 0;
620
+ }
621
+
622
+ // ----- Return
623
+ PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
624
+ return $p_result_list;
625
+ }
626
+ // --------------------------------------------------------------------------------
627
+
628
+ // --------------------------------------------------------------------------------
629
+ // Function : listContent()
630
+ // Description :
631
+ // This public method, gives the list of the files and directories, with their
632
+ // properties.
633
+ // The properties of each entries in the list are (used also in other functions) :
634
+ // filename : Name of the file. For a create or add action it is the filename
635
+ // given by the user. For an extract function it is the filename
636
+ // of the extracted file.
637
+ // stored_filename : Name of the file / directory stored in the archive.
638
+ // size : Size of the stored file.
639
+ // compressed_size : Size of the file's data compressed in the archive
640
+ // (without the headers overhead)
641
+ // mtime : Last known modification date of the file (UNIX timestamp)
642
+ // comment : Comment associated with the file
643
+ // folder : true | false
644
+ // index : index of the file in the archive
645
+ // status : status of the action (depending of the action) :
646
+ // Values are :
647
+ // ok : OK !
648
+ // filtered : the file / dir is not extracted (filtered by user)
649
+ // already_a_directory : the file can not be extracted because a
650
+ // directory with the same name already exists
651
+ // write_protected : the file can not be extracted because a file
652
+ // with the same name already exists and is
653
+ // write protected
654
+ // newer_exist : the file was not extracted because a newer file exists
655
+ // path_creation_fail : the file is not extracted because the folder
656
+ // does not exist and can not be created
657
+ // write_error : the file was not extracted because there was a
658
+ // error while writing the file
659
+ // read_error : the file was not extracted because there was a error
660
+ // while reading the file
661
+ // invalid_header : the file was not extracted because of an archive
662
+ // format error (bad file header)
663
+ // Note that each time a method can continue operating when there
664
+ // is an action error on a file, the error is only logged in the file status.
665
+ // Return Values :
666
+ // 0 on an unrecoverable failure,
667
+ // The list of the files in the archive.
668
+ // --------------------------------------------------------------------------------
669
+ function listContent()
670
+ {
671
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::listContent', "");
672
+ $v_result=1;
673
+
674
+ // ----- Reset the error handler
675
+ $this->privErrorReset();
676
+
677
+ // ----- Check archive
678
+ if (!$this->privCheckFormat()) {
679
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
680
+ return(0);
681
+ }
682
+
683
+ // ----- Call the extracting fct
684
+ $p_list = array();
685
+ if (($v_result = $this->privList($p_list)) != 1)
686
+ {
687
+ unset($p_list);
688
+ PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
689
+ return(0);
690
+ }
691
+
692
+ // ----- Return
693
+ PclTraceFctEnd(__FILE__, __LINE__, $p_list);
694
+ return $p_list;
695
+ }
696
+ // --------------------------------------------------------------------------------
697
+
698
+ // --------------------------------------------------------------------------------
699
+ // Function :
700
+ // extract($p_path="./", $p_remove_path="")
701
+ // extract([$p_option, $p_option_value, ...])
702
+ // Description :
703
+ // This method supports two synopsis. The first one is historical.
704
+ // This method extract all the files / directories from the archive to the
705
+ // folder indicated in $p_path.
706
+ // If you want to ignore the 'root' part of path of the memorized files
707
+ // you can indicate this in the optional $p_remove_path parameter.
708
+ // By default, if a newer file with the same name already exists, the
709
+ // file is not extracted.
710
+ //
711
+ // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
712
+ // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
713
+ // at the end of the path value of PCLZIP_OPT_PATH.
714
+ // Parameters :
715
+ // $p_path : Path where the files and directories are to be extracted
716
+ // $p_remove_path : First part ('root' part) of the memorized path
717
+ // (if any similar) to remove while extracting.
718
+ // Options :
719
+ // PCLZIP_OPT_PATH :
720
+ // PCLZIP_OPT_ADD_PATH :
721
+ // PCLZIP_OPT_REMOVE_PATH :
722
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
723
+ // PCLZIP_CB_PRE_EXTRACT :
724
+ // PCLZIP_CB_POST_EXTRACT :
725
+ // Return Values :
726
+ // 0 or a negative value on failure,
727
+ // The list of the extracted files, with a status of the action.
728
+ // (see PclZip::listContent() for list entry format)
729
+ // --------------------------------------------------------------------------------
730
+ function extract()
731
+ {
732
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::extract", "");
733
+ $v_result=1;
734
+
735
+ // ----- Reset the error handler
736
+ $this->privErrorReset();
737
+
738
+ // ----- Check archive
739
+ if (!$this->privCheckFormat()) {
740
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
741
+ return(0);
742
+ }
743
+
744
+ // ----- Set default values
745
+ $v_options = array();
746
+ // $v_path = "./";
747
+ $v_path = '';
748
+ $v_remove_path = "";
749
+ $v_remove_all_path = false;
750
+
751
+ // ----- Look for variable options arguments
752
+ $v_size = func_num_args();
753
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
754
+
755
+ // ----- Default values for option
756
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
757
+
758
+ // ----- Look for arguments
759
+ if ($v_size > 0) {
760
+ // ----- Get the arguments
761
+ $v_arg_list = func_get_args();
762
+
763
+ // ----- Look for first arg
764
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
765
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
766
+
767
+ // ----- Parse the options
768
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
769
+ array (PCLZIP_OPT_PATH => 'optional',
770
+ PCLZIP_OPT_REMOVE_PATH => 'optional',
771
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
772
+ PCLZIP_OPT_ADD_PATH => 'optional',
773
+ PCLZIP_CB_PRE_EXTRACT => 'optional',
774
+ PCLZIP_CB_POST_EXTRACT => 'optional',
775
+ PCLZIP_OPT_SET_CHMOD => 'optional',
776
+ PCLZIP_OPT_BY_NAME => 'optional',
777
+ PCLZIP_OPT_BY_EREG => 'optional',
778
+ PCLZIP_OPT_BY_PREG => 'optional',
779
+ PCLZIP_OPT_BY_INDEX => 'optional',
780
+ PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
781
+ PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
782
+ PCLZIP_OPT_REPLACE_NEWER => 'optional'
783
+ ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
784
+ ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
785
+ PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
786
+ PCLZIP_OPT_TEMP_FILE_ON => 'optional',
787
+ PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
788
+ ));
789
+ if ($v_result != 1) {
790
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
791
+ return 0;
792
+ }
793
+
794
+ // ----- Set the arguments
795
+ if (isset($v_options[PCLZIP_OPT_PATH])) {
796
+ $v_path = $v_options[PCLZIP_OPT_PATH];
797
+ }
798
+ if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
799
+ $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
800
+ }
801
+ if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
802
+ $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
803
+ }
804
+ if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
805
+ // ----- Check for '/' in last path char
806
+ if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
807
+ $v_path .= '/';
808
+ }
809
+ $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
810
+ }
811
+ }
812
+
813
+ // ----- Look for 2 args
814
+ // Here we need to support the first historic synopsis of the
815
+ // method.
816
+ else {
817
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
818
+
819
+ // ----- Get the first argument
820
+ $v_path = $v_arg_list[0];
821
+
822
+ // ----- Look for the optional second argument
823
+ if ($v_size == 2) {
824
+ $v_remove_path = $v_arg_list[1];
825
+ }
826
+ else if ($v_size > 2) {
827
+ // ----- Error log
828
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
829
+
830
+ // ----- Return
831
+ PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
832
+ return 0;
833
+ }
834
+ }
835
+ }
836
+
837
+ // ----- Look for default option values
838
+ $this->privOptionDefaultThreshold($v_options);
839
+
840
+ // ----- Trace
841
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
842
+
843
+ // ----- Call the extracting fct
844
+ $p_list = array();
845
+ $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
846
+ $v_remove_all_path, $v_options);
847
+ if ($v_result < 1) {
848
+ unset($p_list);
849
+ PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
850
+ return(0);
851
+ }
852
+
853
+ // ----- Return
854
+ PclTraceFctEnd(__FILE__, __LINE__, $p_list);
855
+ return $p_list;
856
+ }
857
+ // --------------------------------------------------------------------------------
858
+
859
+
860
+ // --------------------------------------------------------------------------------
861
+ // Function :
862
+ // extractByIndex($p_index, $p_path="./", $p_remove_path="")
863
+ // extractByIndex($p_index, [$p_option, $p_option_value, ...])
864
+ // Description :
865
+ // This method supports two synopsis. The first one is historical.
866
+ // This method is doing a partial extract of the archive.
867
+ // The extracted files or folders are identified by their index in the
868
+ // archive (from 0 to n).
869
+ // Note that if the index identify a folder, only the folder entry is
870
+ // extracted, not all the files included in the archive.
871
+ // Parameters :
872
+ // $p_index : A single index (integer) or a string of indexes of files to
873
+ // extract. The form of the string is "0,4-6,8-12" with only numbers
874
+ // and '-' for range or ',' to separate ranges. No spaces or ';'
875
+ // are allowed.
876
+ // $p_path : Path where the files and directories are to be extracted
877
+ // $p_remove_path : First part ('root' part) of the memorized path
878
+ // (if any similar) to remove while extracting.
879
+ // Options :
880
+ // PCLZIP_OPT_PATH :
881
+ // PCLZIP_OPT_ADD_PATH :
882
+ // PCLZIP_OPT_REMOVE_PATH :
883
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
884
+ // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
885
+ // not as files.
886
+ // The resulting content is in a new field 'content' in the file
887
+ // structure.
888
+ // This option must be used alone (any other options are ignored).
889
+ // PCLZIP_CB_PRE_EXTRACT :
890
+ // PCLZIP_CB_POST_EXTRACT :
891
+ // Return Values :
892
+ // 0 on failure,
893
+ // The list of the extracted files, with a status of the action.
894
+ // (see PclZip::listContent() for list entry format)
895
+ // --------------------------------------------------------------------------------
896
+ //function extractByIndex($p_index, options...)
897
+ function extractByIndex($p_index)
898
+ {
899
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::extractByIndex", "index='$p_index', ...");
900
+ $v_result=1;
901
+
902
+ // ----- Reset the error handler
903
+ $this->privErrorReset();
904
+
905
+ // ----- Check archive
906
+ if (!$this->privCheckFormat()) {
907
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
908
+ return(0);
909
+ }
910
+
911
+ // ----- Set default values
912
+ $v_options = array();
913
+ // $v_path = "./";
914
+ $v_path = '';
915
+ $v_remove_path = "";
916
+ $v_remove_all_path = false;
917
+
918
+ // ----- Look for variable options arguments
919
+ $v_size = func_num_args();
920
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
921
+
922
+ // ----- Default values for option
923
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
924
+
925
+ // ----- Look for arguments
926
+ if ($v_size > 1) {
927
+ // ----- Get the arguments
928
+ $v_arg_list = func_get_args();
929
+
930
+ // ----- Remove form the options list the first argument
931
+ array_shift($v_arg_list);
932
+ $v_size--;
933
+
934
+ // ----- Look for first arg
935
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
936
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
937
+
938
+ // ----- Parse the options
939
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
940
+ array (PCLZIP_OPT_PATH => 'optional',
941
+ PCLZIP_OPT_REMOVE_PATH => 'optional',
942
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
943
+ PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
944
+ PCLZIP_OPT_ADD_PATH => 'optional',
945
+ PCLZIP_CB_PRE_EXTRACT => 'optional',
946
+ PCLZIP_CB_POST_EXTRACT => 'optional',
947
+ PCLZIP_OPT_SET_CHMOD => 'optional',
948
+ PCLZIP_OPT_REPLACE_NEWER => 'optional'
949
+ ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
950
+ ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
951
+ PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
952
+ PCLZIP_OPT_TEMP_FILE_ON => 'optional',
953
+ PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
954
+ ));
955
+ if ($v_result != 1) {
956
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
957
+ return 0;
958
+ }
959
+
960
+ // ----- Set the arguments
961
+ if (isset($v_options[PCLZIP_OPT_PATH])) {
962
+ $v_path = $v_options[PCLZIP_OPT_PATH];
963
+ }
964
+ if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
965
+ $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
966
+ }
967
+ if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
968
+ $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
969
+ }
970
+ if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
971
+ // ----- Check for '/' in last path char
972
+ if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
973
+ $v_path .= '/';
974
+ }
975
+ $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
976
+ }
977
+ if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
978
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
979
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING not set.");
980
+ }
981
+ else {
982
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING set.");
983
+ }
984
+ }
985
+
986
+ // ----- Look for 2 args
987
+ // Here we need to support the first historic synopsis of the
988
+ // method.
989
+ else {
990
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
991
+
992
+ // ----- Get the first argument
993
+ $v_path = $v_arg_list[0];
994
+
995
+ // ----- Look for the optional second argument
996
+ if ($v_size == 2) {
997
+ $v_remove_path = $v_arg_list[1];
998
+ }
999
+ else if ($v_size > 2) {
1000
+ // ----- Error log
1001
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
1002
+
1003
+ // ----- Return
1004
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1005
+ return 0;
1006
+ }
1007
+ }
1008
+ }
1009
+
1010
+ // ----- Trace
1011
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "index='$p_index', path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
1012
+
1013
+ // ----- Trick
1014
+ // Here I want to reuse extractByRule(), so I need to parse the $p_index
1015
+ // with privParseOptions()
1016
+ $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
1017
+ $v_options_trick = array();
1018
+ $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
1019
+ array (PCLZIP_OPT_BY_INDEX => 'optional' ));
1020
+ if ($v_result != 1) {
1021
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
1022
+ return 0;
1023
+ }
1024
+ $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
1025
+
1026
+ // ----- Look for default option values
1027
+ $this->privOptionDefaultThreshold($v_options);
1028
+
1029
+ // ----- Call the extracting fct
1030
+ if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
1031
+ PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
1032
+ return(0);
1033
+ }
1034
+
1035
+ // ----- Return
1036
+ PclTraceFctEnd(__FILE__, __LINE__, $p_list);
1037
+ return $p_list;
1038
+ }
1039
+ // --------------------------------------------------------------------------------
1040
+
1041
+ // --------------------------------------------------------------------------------
1042
+ // Function :
1043
+ // delete([$p_option, $p_option_value, ...])
1044
+ // Description :
1045
+ // This method removes files from the archive.
1046
+ // If no parameters are given, then all the archive is emptied.
1047
+ // Parameters :
1048
+ // None or optional arguments.
1049
+ // Options :
1050
+ // PCLZIP_OPT_BY_INDEX :
1051
+ // PCLZIP_OPT_BY_NAME :
1052
+ // PCLZIP_OPT_BY_EREG :
1053
+ // PCLZIP_OPT_BY_PREG :
1054
+ // Return Values :
1055
+ // 0 on failure,
1056
+ // The list of the files which are still present in the archive.
1057
+ // (see PclZip::listContent() for list entry format)
1058
+ // --------------------------------------------------------------------------------
1059
+ function delete()
1060
+ {
1061
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::delete", "");
1062
+ $v_result=1;
1063
+
1064
+ // ----- Reset the error handler
1065
+ $this->privErrorReset();
1066
+
1067
+ // ----- Check archive
1068
+ if (!$this->privCheckFormat()) {
1069
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
1070
+ return(0);
1071
+ }
1072
+
1073
+ // ----- Set default values
1074
+ $v_options = array();
1075
+
1076
+ // ----- Look for variable options arguments
1077
+ $v_size = func_num_args();
1078
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
1079
+
1080
+ // ----- Look for arguments
1081
+ if ($v_size > 0) {
1082
+ // ----- Get the arguments
1083
+ $v_arg_list = func_get_args();
1084
+
1085
+ // ----- Parse the options
1086
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
1087
+ array (PCLZIP_OPT_BY_NAME => 'optional',
1088
+ PCLZIP_OPT_BY_EREG => 'optional',
1089
+ PCLZIP_OPT_BY_PREG => 'optional',
1090
+ PCLZIP_OPT_BY_INDEX => 'optional' ));
1091
+ if ($v_result != 1) {
1092
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
1093
+ return 0;
1094
+ }
1095
+ }
1096
+
1097
+ // ----- Magic quotes trick
1098
+ $this->privDisableMagicQuotes();
1099
+
1100
+ // ----- Call the delete fct
1101
+ $v_list = array();
1102
+ if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
1103
+ $this->privSwapBackMagicQuotes();
1104
+ unset($v_list);
1105
+ PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
1106
+ return(0);
1107
+ }
1108
+
1109
+ // ----- Magic quotes trick
1110
+ $this->privSwapBackMagicQuotes();
1111
+
1112
+ // ----- Return
1113
+ PclTraceFctEnd(__FILE__, __LINE__, $v_list);
1114
+ return $v_list;
1115
+ }
1116
+ // --------------------------------------------------------------------------------
1117
+
1118
+ // --------------------------------------------------------------------------------
1119
+ // Function : deleteByIndex()
1120
+ // Description :
1121
+ // ***** Deprecated *****
1122
+ // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
1123
+ // --------------------------------------------------------------------------------
1124
+ function deleteByIndex($p_index)
1125
+ {
1126
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::deleteByIndex", "index='$p_index'");
1127
+
1128
+ $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
1129
+
1130
+ // ----- Return
1131
+ PclTraceFctEnd(__FILE__, __LINE__, $p_list);
1132
+ return $p_list;
1133
+ }
1134
+ // --------------------------------------------------------------------------------
1135
+
1136
+ // --------------------------------------------------------------------------------
1137
+ // Function : properties()
1138
+ // Description :
1139
+ // This method gives the properties of the archive.
1140
+ // The properties are :
1141
+ // nb : Number of files in the archive
1142
+ // comment : Comment associated with the archive file
1143
+ // status : not_exist, ok
1144
+ // Parameters :
1145
+ // None
1146
+ // Return Values :
1147
+ // 0 on failure,
1148
+ // An array with the archive properties.
1149
+ // --------------------------------------------------------------------------------
1150
+ function properties()
1151
+ {
1152
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::properties", "");
1153
+
1154
+ // ----- Reset the error handler
1155
+ $this->privErrorReset();
1156
+
1157
+ // ----- Magic quotes trick
1158
+ $this->privDisableMagicQuotes();
1159
+
1160
+ // ----- Check archive
1161
+ if (!$this->privCheckFormat()) {
1162
+ $this->privSwapBackMagicQuotes();
1163
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
1164
+ return(0);
1165
+ }
1166
+
1167
+ // ----- Default properties
1168
+ $v_prop = array();
1169
+ $v_prop['comment'] = '';
1170
+ $v_prop['nb'] = 0;
1171
+ $v_prop['status'] = 'not_exist';
1172
+
1173
+ // ----- Look if file exists
1174
+ if (@is_file($this->zipname))
1175
+ {
1176
+ // ----- Open the zip file
1177
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
1178
+ if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
1179
+ {
1180
+ $this->privSwapBackMagicQuotes();
1181
+
1182
+ // ----- Error log
1183
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
1184
+
1185
+ // ----- Return
1186
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), 0);
1187
+ return 0;
1188
+ }
1189
+
1190
+ // ----- Read the central directory informations
1191
+ $v_central_dir = array();
1192
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
1193
+ {
1194
+ $this->privSwapBackMagicQuotes();
1195
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
1196
+ return 0;
1197
+ }
1198
+
1199
+ // ----- Close the zip file
1200
+ $this->privCloseFd();
1201
+
1202
+ // ----- Set the user attributes
1203
+ $v_prop['comment'] = $v_central_dir['comment'];
1204
+ $v_prop['nb'] = $v_central_dir['entries'];
1205
+ $v_prop['status'] = 'ok';
1206
+ }
1207
+
1208
+ // ----- Magic quotes trick
1209
+ $this->privSwapBackMagicQuotes();
1210
+
1211
+ // ----- Return
1212
+ PclTraceFctEnd(__FILE__, __LINE__, $v_prop);
1213
+ return $v_prop;
1214
+ }
1215
+ // --------------------------------------------------------------------------------
1216
+
1217
+ // --------------------------------------------------------------------------------
1218
+ // Function : duplicate()
1219
+ // Description :
1220
+ // This method creates an archive by copying the content of an other one. If
1221
+ // the archive already exist, it is replaced by the new one without any warning.
1222
+ // Parameters :
1223
+ // $p_archive : The filename of a valid archive, or
1224
+ // a valid PclZip object.
1225
+ // Return Values :
1226
+ // 1 on success.
1227
+ // 0 or a negative value on error (error code).
1228
+ // --------------------------------------------------------------------------------
1229
+ function duplicate($p_archive)
1230
+ {
1231
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::duplicate", "");
1232
+ $v_result = 1;
1233
+
1234
+ // ----- Reset the error handler
1235
+ $this->privErrorReset();
1236
+
1237
+ // ----- Look if the $p_archive is a PclZip object
1238
+ if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
1239
+ {
1240
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is valid PclZip object '".$p_archive->zipname."'");
1241
+
1242
+ // ----- Duplicate the archive
1243
+ $v_result = $this->privDuplicate($p_archive->zipname);
1244
+ }
1245
+
1246
+ // ----- Look if the $p_archive is a string (so a filename)
1247
+ else if (is_string($p_archive))
1248
+ {
1249
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is a filename '$p_archive'");
1250
+
1251
+ // ----- Check that $p_archive is a valid zip file
1252
+ // TBC : Should also check the archive format
1253
+ if (!is_file($p_archive)) {
1254
+ // ----- Error log
1255
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
1256
+ $v_result = PCLZIP_ERR_MISSING_FILE;
1257
+ }
1258
+ else {
1259
+ // ----- Duplicate the archive
1260
+ $v_result = $this->privDuplicate($p_archive);
1261
+ }
1262
+ }
1263
+
1264
+ // ----- Invalid variable
1265
+ else
1266
+ {
1267
+ // ----- Error log
1268
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1269
+ $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1270
+ }
1271
+
1272
+ // ----- Return
1273
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1274
+ return $v_result;
1275
+ }
1276
+ // --------------------------------------------------------------------------------
1277
+
1278
+ // --------------------------------------------------------------------------------
1279
+ // Function : merge()
1280
+ // Description :
1281
+ // This method merge the $p_archive_to_add archive at the end of the current
1282
+ // one ($this).
1283
+ // If the archive ($this) does not exist, the merge becomes a duplicate.
1284
+ // If the $p_archive_to_add archive does not exist, the merge is a success.
1285
+ // Parameters :
1286
+ // $p_archive_to_add : It can be directly the filename of a valid zip archive,
1287
+ // or a PclZip object archive.
1288
+ // Return Values :
1289
+ // 1 on success,
1290
+ // 0 or negative values on error (see below).
1291
+ // --------------------------------------------------------------------------------
1292
+ function merge($p_archive_to_add)
1293
+ {
1294
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::merge", "");
1295
+ $v_result = 1;
1296
+
1297
+ // ----- Reset the error handler
1298
+ $this->privErrorReset();
1299
+
1300
+ // ----- Check archive
1301
+ if (!$this->privCheckFormat()) {
1302
+ PclTraceFctEnd(__FILE__, __LINE__, 0);
1303
+ return(0);
1304
+ }
1305
+
1306
+ // ----- Look if the $p_archive_to_add is a PclZip object
1307
+ if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
1308
+ {
1309
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is valid PclZip object");
1310
+
1311
+ // ----- Merge the archive
1312
+ $v_result = $this->privMerge($p_archive_to_add);
1313
+ }
1314
+
1315
+ // ----- Look if the $p_archive_to_add is a string (so a filename)
1316
+ else if (is_string($p_archive_to_add))
1317
+ {
1318
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is a filename");
1319
+
1320
+ // ----- Create a temporary archive
1321
+ $v_object_archive = new PclZip($p_archive_to_add);
1322
+
1323
+ // ----- Merge the archive
1324
+ $v_result = $this->privMerge($v_object_archive);
1325
+ }
1326
+
1327
+ // ----- Invalid variable
1328
+ else
1329
+ {
1330
+ // ----- Error log
1331
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1332
+ $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1333
+ }
1334
+
1335
+ // ----- Return
1336
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1337
+ return $v_result;
1338
+ }
1339
+ // --------------------------------------------------------------------------------
1340
+
1341
+
1342
+
1343
+ // --------------------------------------------------------------------------------
1344
+ // Function : errorCode()
1345
+ // Description :
1346
+ // Parameters :
1347
+ // --------------------------------------------------------------------------------
1348
+ function errorCode()
1349
+ {
1350
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
1351
+ return(PclErrorCode());
1352
+ }
1353
+ else {
1354
+ return($this->error_code);
1355
+ }
1356
+ }
1357
+ // --------------------------------------------------------------------------------
1358
+
1359
+ // --------------------------------------------------------------------------------
1360
+ // Function : errorName()
1361
+ // Description :
1362
+ // Parameters :
1363
+ // --------------------------------------------------------------------------------
1364
+ function errorName($p_with_code=false)
1365
+ {
1366
+ $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
1367
+ PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
1368
+ PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
1369
+ PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
1370
+ PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
1371
+ PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
1372
+ PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
1373
+ PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
1374
+ PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
1375
+ PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
1376
+ PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
1377
+ PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
1378
+ PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
1379
+ PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
1380
+ PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1381
+ PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
1382
+ PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
1383
+ PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
1384
+ PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
1385
+ ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
1386
+ ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
1387
+ );
1388
+
1389
+ if (isset($v_name[$this->error_code])) {
1390
+ $v_value = $v_name[$this->error_code];
1391
+ }
1392
+ else {
1393
+ $v_value = 'NoName';
1394
+ }
1395
+
1396
+ if ($p_with_code) {
1397
+ return($v_value.' ('.$this->error_code.')');
1398
+ }
1399
+ else {
1400
+ return($v_value);
1401
+ }
1402
+ }
1403
+ // --------------------------------------------------------------------------------
1404
+
1405
+ // --------------------------------------------------------------------------------
1406
+ // Function : errorInfo()
1407
+ // Description :
1408
+ // Parameters :
1409
+ // --------------------------------------------------------------------------------
1410
+ function errorInfo($p_full=false)
1411
+ {
1412
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
1413
+ return(PclErrorString());
1414
+ }
1415
+ else {
1416
+ if ($p_full) {
1417
+ return($this->errorName(true)." : ".$this->error_string);
1418
+ }
1419
+ else {
1420
+ return($this->error_string." [code ".$this->error_code."]");
1421
+ }
1422
+ }
1423
+ }
1424
+ // --------------------------------------------------------------------------------
1425
+
1426
+
1427
+ // --------------------------------------------------------------------------------
1428
+ // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1429
+ // ***** *****
1430
+ // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
1431
+ // --------------------------------------------------------------------------------
1432
+
1433
+
1434
+
1435
+ // --------------------------------------------------------------------------------
1436
+ // Function : privCheckFormat()
1437
+ // Description :
1438
+ // This method check that the archive exists and is a valid zip archive.
1439
+ // Several level of check exists. (futur)
1440
+ // Parameters :
1441
+ // $p_level : Level of check. Default 0.
1442
+ // 0 : Check the first bytes (magic codes) (default value))
1443
+ // 1 : 0 + Check the central directory (futur)
1444
+ // 2 : 1 + Check each file header (futur)
1445
+ // Return Values :
1446
+ // true on success,
1447
+ // false on error, the error code is set.
1448
+ // --------------------------------------------------------------------------------
1449
+ function privCheckFormat($p_level=0)
1450
+ {
1451
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFormat", "");
1452
+ $v_result = true;
1453
+
1454
+ // ----- Reset the file system cache
1455
+ clearstatcache();
1456
+
1457
+ // ----- Reset the error handler
1458
+ $this->privErrorReset();
1459
+
1460
+ // ----- Look if the file exits
1461
+ if (!is_file($this->zipname)) {
1462
+ // ----- Error log
1463
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
1464
+ PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
1465
+ return(false);
1466
+ }
1467
+
1468
+ // ----- Check that the file is readeable
1469
+ if (!is_readable($this->zipname)) {
1470
+ // ----- Error log
1471
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
1472
+ PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
1473
+ return(false);
1474
+ }
1475
+
1476
+ // ----- Check the magic code
1477
+ // TBC
1478
+
1479
+ // ----- Check the central header
1480
+ // TBC
1481
+
1482
+ // ----- Check each file header
1483
+ // TBC
1484
+
1485
+ // ----- Return
1486
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1487
+ return $v_result;
1488
+ }
1489
+ // --------------------------------------------------------------------------------
1490
+
1491
+ // --------------------------------------------------------------------------------
1492
+ // Function : privParseOptions()
1493
+ // Description :
1494
+ // This internal methods reads the variable list of arguments ($p_options_list,
1495
+ // $p_size) and generate an array with the options and values ($v_result_list).
1496
+ // $v_requested_options contains the options that can be present and those that
1497
+ // must be present.
1498
+ // $v_requested_options is an array, with the option value as key, and 'optional',
1499
+ // or 'mandatory' as value.
1500
+ // Parameters :
1501
+ // See above.
1502
+ // Return Values :
1503
+ // 1 on success.
1504
+ // 0 on failure.
1505
+ // --------------------------------------------------------------------------------
1506
+ function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
1507
+ {
1508
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privParseOptions", "");
1509
+ $v_result=1;
1510
+
1511
+ // ----- Read the options
1512
+ $i=0;
1513
+ while ($i<$p_size) {
1514
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Looking for table index $i, option = '".PclZipUtilOptionText($p_options_list[$i])."(".$p_options_list[$i].")'");
1515
+
1516
+ // ----- Check if the option is supported
1517
+ if (!isset($v_requested_options[$p_options_list[$i]])) {
1518
+ // ----- Error log
1519
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1520
+
1521
+ // ----- Return
1522
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1523
+ return PclZip::errorCode();
1524
+ }
1525
+
1526
+ // ----- Look for next option
1527
+ switch ($p_options_list[$i]) {
1528
+ // ----- Look for options that request a path value
1529
+ case PCLZIP_OPT_PATH :
1530
+ case PCLZIP_OPT_REMOVE_PATH :
1531
+ case PCLZIP_OPT_ADD_PATH :
1532
+ // ----- Check the number of parameters
1533
+ if (($i+1) >= $p_size) {
1534
+ // ----- Error log
1535
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1536
+
1537
+ // ----- Return
1538
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1539
+ return PclZip::errorCode();
1540
+ }
1541
+
1542
+ // ----- Get the value
1543
+ $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1544
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1545
+ $i++;
1546
+ break;
1547
+
1548
+ case PCLZIP_OPT_TEMP_FILE_THRESHOLD :
1549
+ // ----- Check the number of parameters
1550
+ if (($i+1) >= $p_size) {
1551
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1552
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1553
+ return PclZip::errorCode();
1554
+ }
1555
+
1556
+ // ----- Check for incompatible options
1557
+ if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1558
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1559
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1560
+ return PclZip::errorCode();
1561
+ }
1562
+
1563
+ // ----- Check the value
1564
+ $v_value = $p_options_list[$i+1];
1565
+ if ((!is_integer($v_value)) || ($v_value<0)) {
1566
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1567
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1568
+ return PclZip::errorCode();
1569
+ }
1570
+
1571
+ // ----- Get the value (and convert it in bytes)
1572
+ $v_result_list[$p_options_list[$i]] = $v_value*1048576;
1573
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1574
+ $i++;
1575
+ break;
1576
+
1577
+ case PCLZIP_OPT_TEMP_FILE_ON :
1578
+ // ----- Check for incompatible options
1579
+ if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1580
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1581
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1582
+ return PclZip::errorCode();
1583
+ }
1584
+
1585
+ $v_result_list[$p_options_list[$i]] = true;
1586
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1587
+ break;
1588
+
1589
+ case PCLZIP_OPT_TEMP_FILE_OFF :
1590
+ // ----- Check for incompatible options
1591
+ if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
1592
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
1593
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1594
+ return PclZip::errorCode();
1595
+ }
1596
+ // ----- Check for incompatible options
1597
+ if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1598
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
1599
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1600
+ return PclZip::errorCode();
1601
+ }
1602
+
1603
+ $v_result_list[$p_options_list[$i]] = true;
1604
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1605
+ break;
1606
+
1607
+ case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
1608
+ // ----- Check the number of parameters
1609
+ if (($i+1) >= $p_size) {
1610
+ // ----- Error log
1611
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1612
+
1613
+ // ----- Return
1614
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1615
+ return PclZip::errorCode();
1616
+ }
1617
+
1618
+ // ----- Get the value
1619
+ if ( is_string($p_options_list[$i+1])
1620
+ && ($p_options_list[$i+1] != '')) {
1621
+ $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1622
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1623
+ $i++;
1624
+ }
1625
+ else {
1626
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." set with an empty value is ignored.");
1627
+ }
1628
+ break;
1629
+
1630
+ // ----- Look for options that request an array of string for value
1631
+ case PCLZIP_OPT_BY_NAME :
1632
+ // ----- Check the number of parameters
1633
+ if (($i+1) >= $p_size) {
1634
+ // ----- Error log
1635
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1636
+
1637
+ // ----- Return
1638
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1639
+ return PclZip::errorCode();
1640
+ }
1641
+
1642
+ // ----- Get the value
1643
+ if (is_string($p_options_list[$i+1])) {
1644
+ $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1645
+ }
1646
+ else if (is_array($p_options_list[$i+1])) {
1647
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1648
+ }
1649
+ else {
1650
+ // ----- Error log
1651
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1652
+
1653
+ // ----- Return
1654
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1655
+ return PclZip::errorCode();
1656
+ }
1657
+ //PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1658
+ $i++;
1659
+ break;
1660
+
1661
+ // ----- Look for options that request an EREG or PREG expression
1662
+ case PCLZIP_OPT_BY_EREG :
1663
+ // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
1664
+ // to PCLZIP_OPT_BY_PREG
1665
+ $p_options_list[$i] = PCLZIP_OPT_BY_PREG;
1666
+ case PCLZIP_OPT_BY_PREG :
1667
+ //case PCLZIP_OPT_CRYPT :
1668
+ // ----- Check the number of parameters
1669
+ if (($i+1) >= $p_size) {
1670
+ // ----- Error log
1671
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1672
+
1673
+ // ----- Return
1674
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1675
+ return PclZip::errorCode();
1676
+ }
1677
+
1678
+ // ----- Get the value
1679
+ if (is_string($p_options_list[$i+1])) {
1680
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1681
+ }
1682
+ else {
1683
+ // ----- Error log
1684
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1685
+
1686
+ // ----- Return
1687
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1688
+ return PclZip::errorCode();
1689
+ }
1690
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1691
+ $i++;
1692
+ break;
1693
+
1694
+ // ----- Look for options that takes a string
1695
+ case PCLZIP_OPT_COMMENT :
1696
+ case PCLZIP_OPT_ADD_COMMENT :
1697
+ case PCLZIP_OPT_PREPEND_COMMENT :
1698
+ // ----- Check the number of parameters
1699
+ if (($i+1) >= $p_size) {
1700
+ // ----- Error log
1701
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
1702
+ "Missing parameter value for option '"
1703
+ .PclZipUtilOptionText($p_options_list[$i])
1704
+ ."'");
1705
+
1706
+ // ----- Return
1707
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1708
+ return PclZip::errorCode();
1709
+ }
1710
+
1711
+ // ----- Get the value
1712
+ if (is_string($p_options_list[$i+1])) {
1713
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1714
+ }
1715
+ else {
1716
+ // ----- Error log
1717
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
1718
+ "Wrong parameter value for option '"
1719
+ .PclZipUtilOptionText($p_options_list[$i])
1720
+ ."'");
1721
+
1722
+ // ----- Return
1723
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1724
+ return PclZip::errorCode();
1725
+ }
1726
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1727
+ $i++;
1728
+ break;
1729
+
1730
+ // ----- Look for options that request an array of index
1731
+ case PCLZIP_OPT_BY_INDEX :
1732
+ // ----- Check the number of parameters
1733
+ if (($i+1) >= $p_size) {
1734
+ // ----- Error log
1735
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1736
+
1737
+ // ----- Return
1738
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1739
+ return PclZip::errorCode();
1740
+ }
1741
+
1742
+ // ----- Get the value
1743
+ $v_work_list = array();
1744
+ if (is_string($p_options_list[$i+1])) {
1745
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is a string '".$p_options_list[$i+1]."'");
1746
+
1747
+ // ----- Remove spaces
1748
+ $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
1749
+
1750
+ // ----- Parse items
1751
+ $v_work_list = explode(",", $p_options_list[$i+1]);
1752
+ }
1753
+ else if (is_integer($p_options_list[$i+1])) {
1754
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an integer '".$p_options_list[$i+1]."'");
1755
+ $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1756
+ }
1757
+ else if (is_array($p_options_list[$i+1])) {
1758
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an array");
1759
+ $v_work_list = $p_options_list[$i+1];
1760
+ }
1761
+ else {
1762
+ // ----- Error log
1763
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1764
+
1765
+ // ----- Return
1766
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1767
+ return PclZip::errorCode();
1768
+ }
1769
+
1770
+ // ----- Reduce the index list
1771
+ // each index item in the list must be a couple with a start and
1772
+ // an end value : [0,3], [5-5], [8-10], ...
1773
+ // ----- Check the format of each item
1774
+ $v_sort_flag=false;
1775
+ $v_sort_value=0;
1776
+ for ($j=0; $j<sizeof($v_work_list); $j++) {
1777
+ // ----- Explode the item
1778
+ $v_item_list = explode("-", $v_work_list[$j]);
1779
+ $v_size_item_list = sizeof($v_item_list);
1780
+
1781
+ // ----- TBC : Here we might check that each item is a
1782
+ // real integer ...
1783
+
1784
+ // ----- Look for single value
1785
+ if ($v_size_item_list == 1) {
1786
+ // ----- Set the option value
1787
+ $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1788
+ $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1789
+ }
1790
+ elseif ($v_size_item_list == 2) {
1791
+ // ----- Set the option value
1792
+ $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1793
+ $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1794
+ }
1795
+ else {
1796
+ // ----- Error log
1797
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1798
+
1799
+ // ----- Return
1800
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1801
+ return PclZip::errorCode();
1802
+ }
1803
+
1804
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extracted index item = [".$v_result_list[$p_options_list[$i]][$j]['start'].",".$v_result_list[$p_options_list[$i]][$j]['end']."]");
1805
+
1806
+ // ----- Look for list sort
1807
+ if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1808
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The list should be sorted ...");
1809
+ $v_sort_flag=true;
1810
+
1811
+ // ----- TBC : An automatic sort should be writen ...
1812
+ // ----- Error log
1813
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1814
+
1815
+ // ----- Return
1816
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1817
+ return PclZip::errorCode();
1818
+ }
1819
+ $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1820
+ }
1821
+
1822
+ // ----- Sort the items
1823
+ if ($v_sort_flag) {
1824
+ // TBC : To Be Completed
1825
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "List sorting is not yet write ...");
1826
+ }
1827
+
1828
+ // ----- Next option
1829
+ $i++;
1830
+ break;
1831
+
1832
+ // ----- Look for options that request no value
1833
+ case PCLZIP_OPT_REMOVE_ALL_PATH :
1834
+ case PCLZIP_OPT_EXTRACT_AS_STRING :
1835
+ case PCLZIP_OPT_NO_COMPRESSION :
1836
+ case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
1837
+ case PCLZIP_OPT_REPLACE_NEWER :
1838
+ case PCLZIP_OPT_STOP_ON_ERROR :
1839
+ $v_result_list[$p_options_list[$i]] = true;
1840
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1841
+ break;
1842
+
1843
+ // ----- Look for options that request an octal value
1844
+ case PCLZIP_OPT_SET_CHMOD :
1845
+ // ----- Check the number of parameters
1846
+ if (($i+1) >= $p_size) {
1847
+ // ----- Error log
1848
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1849
+
1850
+ // ----- Return
1851
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1852
+ return PclZip::errorCode();
1853
+ }
1854
+
1855
+ // ----- Get the value
1856
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1857
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1858
+ $i++;
1859
+ break;
1860
+
1861
+ // ----- Look for options that request a call-back
1862
+ case PCLZIP_CB_PRE_EXTRACT :
1863
+ case PCLZIP_CB_POST_EXTRACT :
1864
+ case PCLZIP_CB_PRE_ADD :
1865
+ case PCLZIP_CB_POST_ADD :
1866
+ /* for futur use
1867
+ case PCLZIP_CB_PRE_DELETE :
1868
+ case PCLZIP_CB_POST_DELETE :
1869
+ case PCLZIP_CB_PRE_LIST :
1870
+ case PCLZIP_CB_POST_LIST :
1871
+ */
1872
+ // ----- Check the number of parameters
1873
+ if (($i+1) >= $p_size) {
1874
+ // ----- Error log
1875
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1876
+
1877
+ // ----- Return
1878
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1879
+ return PclZip::errorCode();
1880
+ }
1881
+
1882
+ // ----- Get the value
1883
+ $v_function_name = $p_options_list[$i+1];
1884
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "call-back ".PclZipUtilOptionText($p_options_list[$i])." = '".$v_function_name."'");
1885
+
1886
+ // ----- Check that the value is a valid existing function
1887
+ if (!function_exists($v_function_name)) {
1888
+ // ----- Error log
1889
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1890
+
1891
+ // ----- Return
1892
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1893
+ return PclZip::errorCode();
1894
+ }
1895
+
1896
+ // ----- Set the attribute
1897
+ $v_result_list[$p_options_list[$i]] = $v_function_name;
1898
+ $i++;
1899
+ break;
1900
+
1901
+ default :
1902
+ // ----- Error log
1903
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1904
+ "Unknown parameter '"
1905
+ .$p_options_list[$i]."'");
1906
+
1907
+ // ----- Return
1908
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1909
+ return PclZip::errorCode();
1910
+ }
1911
+
1912
+ // ----- Next options
1913
+ $i++;
1914
+ }
1915
+
1916
+ // ----- Look for mandatory options
1917
+ if ($v_requested_options !== false) {
1918
+ for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1919
+ // ----- Look for mandatory option
1920
+ if ($v_requested_options[$key] == 'mandatory') {
1921
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
1922
+ // ----- Look if present
1923
+ if (!isset($v_result_list[$key])) {
1924
+ // ----- Error log
1925
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1926
+
1927
+ // ----- Return
1928
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1929
+ return PclZip::errorCode();
1930
+ }
1931
+ }
1932
+ }
1933
+ }
1934
+
1935
+ // ----- Look for default values
1936
+ if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1937
+ PclTraceFctMessage(__FILE__, __LINE__, 3,"Calculate auto threshold");
1938
+
1939
+ }
1940
+
1941
+ // ----- Return
1942
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1943
+ return $v_result;
1944
+ }
1945
+ // --------------------------------------------------------------------------------
1946
+
1947
+ // --------------------------------------------------------------------------------
1948
+ // Function : privOptionDefaultThreshold()
1949
+ // Description :
1950
+ // Parameters :
1951
+ // Return Values :
1952
+ // --------------------------------------------------------------------------------
1953
+ function privOptionDefaultThreshold(&$p_options)
1954
+ {
1955
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOptionDefaultThreshold", "");
1956
+ $v_result=1;
1957
+
1958
+ if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
1959
+ || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) {
1960
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1961
+ return $v_result;
1962
+ }
1963
+
1964
+ PclTraceFctMessage(__FILE__, __LINE__, 3,"Create an auto-threshold for use of temporay files");
1965
+ // ----- Get 'memory_limit' configuration value
1966
+ $v_memory_limit = ini_get('memory_limit');
1967
+ $v_memory_limit = trim($v_memory_limit);
1968
+ $last = strtolower(substr($v_memory_limit, -1));
1969
+
1970
+ if($last == 'g')
1971
+ //$v_memory_limit = $v_memory_limit*1024*1024*1024;
1972
+ $v_memory_limit = $v_memory_limit*1073741824;
1973
+ if($last == 'm')
1974
+ //$v_memory_limit = $v_memory_limit*1024*1024;
1975
+ $v_memory_limit = $v_memory_limit*1048576;
1976
+ if($last == 'k')
1977
+ $v_memory_limit = $v_memory_limit*1024;
1978
+
1979
+ $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO);
1980
+
1981
+ PclTraceFctMessage(__FILE__, __LINE__, 3,"Current memory usage : ".memory_get_usage(TRUE)." bytes");
1982
+ PclTraceFctMessage(__FILE__, __LINE__, 3,"Threshold value is : ".$p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]." bytes");
1983
+
1984
+ // ----- Sanity check : No threshold if value lower than 1M
1985
+ if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
1986
+ PclTraceFctMessage(__FILE__, __LINE__, 3,"Unset the threshold (value ".$p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD].") because under 1Mo sanity check)");
1987
+ unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
1988
+ }
1989
+
1990
+ // ----- Return
1991
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1992
+ return $v_result;
1993
+ }
1994
+ // --------------------------------------------------------------------------------
1995
+
1996
+ // --------------------------------------------------------------------------------
1997
+ // Function : privFileDescrParseAtt()
1998
+ // Description :
1999
+ // Parameters :
2000
+ // Return Values :
2001
+ // 1 on success.
2002
+ // 0 on failure.
2003
+ // --------------------------------------------------------------------------------
2004
+ function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
2005
+ {
2006
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrParseAtt", "");
2007
+ $v_result=1;
2008
+
2009
+ // ----- For each file in the list check the attributes
2010
+ foreach ($p_file_list as $v_key => $v_value) {
2011
+
2012
+ // ----- Check if the option is supported
2013
+ if (!isset($v_requested_options[$v_key])) {
2014
+ // ----- Error log
2015
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
2016
+
2017
+ // ----- Return
2018
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2019
+ return PclZip::errorCode();
2020
+ }
2021
+
2022
+ // ----- Look for attribute
2023
+ switch ($v_key) {
2024
+ case PCLZIP_ATT_FILE_NAME :
2025
+ if (!is_string($v_value)) {
2026
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
2027
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2028
+ return PclZip::errorCode();
2029
+ }
2030
+
2031
+ $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
2032
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
2033
+
2034
+ if ($p_filedescr['filename'] == '') {
2035
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
2036
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2037
+ return PclZip::errorCode();
2038
+ }
2039
+
2040
+ break;
2041
+
2042
+ case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
2043
+ if (!is_string($v_value)) {
2044
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
2045
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2046
+ return PclZip::errorCode();
2047
+ }
2048
+
2049
+ $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
2050
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
2051
+
2052
+ if ($p_filedescr['new_short_name'] == '') {
2053
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
2054
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2055
+ return PclZip::errorCode();
2056
+ }
2057
+ break;
2058
+
2059
+ case PCLZIP_ATT_FILE_NEW_FULL_NAME :
2060
+ if (!is_string($v_value)) {
2061
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
2062
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2063
+ return PclZip::errorCode();
2064
+ }
2065
+
2066
+ $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
2067
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
2068
+
2069
+ if ($p_filedescr['new_full_name'] == '') {
2070
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
2071
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2072
+ return PclZip::errorCode();
2073
+ }
2074
+ break;
2075
+
2076
+ // ----- Look for options that takes a string
2077
+ case PCLZIP_ATT_FILE_COMMENT :
2078
+ if (!is_string($v_value)) {
2079
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
2080
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2081
+ return PclZip::errorCode();
2082
+ }
2083
+
2084
+ $p_filedescr['comment'] = $v_value;
2085
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
2086
+ break;
2087
+
2088
+ case PCLZIP_ATT_FILE_MTIME :
2089
+ if (!is_integer($v_value)) {
2090
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'");
2091
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2092
+ return PclZip::errorCode();
2093
+ }
2094
+
2095
+ $p_filedescr['mtime'] = $v_value;
2096
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
2097
+ break;
2098
+
2099
+ case PCLZIP_ATT_FILE_CONTENT :
2100
+ $p_filedescr['content'] = $v_value;
2101
+ //PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
2102
+ break;
2103
+
2104
+ default :
2105
+ // ----- Error log
2106
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
2107
+ "Unknown parameter '".$v_key."'");
2108
+
2109
+ // ----- Return
2110
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2111
+ return PclZip::errorCode();
2112
+ }
2113
+
2114
+ // ----- Look for mandatory options
2115
+ if ($v_requested_options !== false) {
2116
+ for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
2117
+ // ----- Look for mandatory option
2118
+ if ($v_requested_options[$key] == 'mandatory') {
2119
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
2120
+ // ----- Look if present
2121
+ if (!isset($p_file_list[$key])) {
2122
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
2123
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2124
+ return PclZip::errorCode();
2125
+ }
2126
+ }
2127
+ }
2128
+ }
2129
+
2130
+ // end foreach
2131
+ }
2132
+
2133
+ // ----- Return
2134
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2135
+ return $v_result;
2136
+ }
2137
+ // --------------------------------------------------------------------------------
2138
+
2139
+ // --------------------------------------------------------------------------------
2140
+ // Function : privFileDescrExpand()
2141
+ // Description :
2142
+ // This method look for each item of the list to see if its a file, a folder
2143
+ // or a string to be added as file. For any other type of files (link, other)
2144
+ // just ignore the item.
2145
+ // Then prepare the information that will be stored for that file.
2146
+ // When its a folder, expand the folder with all the files that are in that
2147
+ // folder (recursively).
2148
+ // Parameters :
2149
+ // Return Values :
2150
+ // 1 on success.
2151
+ // 0 on failure.
2152
+ // --------------------------------------------------------------------------------
2153
+ function privFileDescrExpand(&$p_filedescr_list, &$p_options)
2154
+ {
2155
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrExpand", "");
2156
+ $v_result=1;
2157
+
2158
+ // ----- Create a result list
2159
+ $v_result_list = array();
2160
+
2161
+ // ----- Look each entry
2162
+ for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
2163
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for file ".$i.".");
2164
+
2165
+ // ----- Get filedescr
2166
+ $v_descr = $p_filedescr_list[$i];
2167
+
2168
+ // ----- Reduce the filename
2169
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Filedescr before reduction :'".$v_descr['filename']."'");
2170
+ $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
2171
+ $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
2172
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Filedescr after reduction :'".$v_descr['filename']."'");
2173
+
2174
+ // ----- Look for real file or folder
2175
+ if (file_exists($v_descr['filename'])) {
2176
+ if (@is_file($v_descr['filename'])) {
2177
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a file");
2178
+ $v_descr['type'] = 'file';
2179
+ }
2180
+ else if (@is_dir($v_descr['filename'])) {
2181
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a folder");
2182
+ $v_descr['type'] = 'folder';
2183
+ }
2184
+ else if (@is_link($v_descr['filename'])) {
2185
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Unsupported file type : link");
2186
+ // skip
2187
+ continue;
2188
+ }
2189
+ else {
2190
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Unsupported file type : unknown type");
2191
+ // skip
2192
+ continue;
2193
+ }
2194
+ }
2195
+
2196
+ // ----- Look for string added as file
2197
+ else if (isset($v_descr['content'])) {
2198
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a string added as a file");
2199
+ $v_descr['type'] = 'virtual_file';
2200
+ }
2201
+
2202
+ // ----- Missing file
2203
+ else {
2204
+ // ----- Error log
2205
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_descr['filename']."' does not exist");
2206
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
2207
+
2208
+ // ----- Return
2209
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2210
+ return PclZip::errorCode();
2211
+ }
2212
+
2213
+ // ----- Calculate the stored filename
2214
+ $this->privCalculateStoredFilename($v_descr, $p_options);
2215
+
2216
+ // ----- Add the descriptor in result list
2217
+ $v_result_list[sizeof($v_result_list)] = $v_descr;
2218
+
2219
+ // ----- Look for folder
2220
+ if ($v_descr['type'] == 'folder') {
2221
+ // ----- List of items in folder
2222
+ $v_dirlist_descr = array();
2223
+ $v_dirlist_nb = 0;
2224
+ if ($v_folder_handler = @opendir($v_descr['filename'])) {
2225
+ while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
2226
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for '".$v_item_handler."' in the directory");
2227
+
2228
+ // ----- Skip '.' and '..'
2229
+ if (($v_item_handler == '.') || ($v_item_handler == '..')) {
2230
+ continue;
2231
+ }
2232
+
2233
+ // ----- Compose the full filename
2234
+ $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
2235
+
2236
+ // ----- Look for different stored filename
2237
+ // Because the name of the folder was changed, the name of the
2238
+ // files/sub-folders also change
2239
+ if (($v_descr['stored_filename'] != $v_descr['filename'])
2240
+ && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
2241
+ PclTraceFctMessage(__FILE__, __LINE__, 3,"Inherite parent folder stored path");
2242
+ if ($v_descr['stored_filename'] != '') {
2243
+ $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
2244
+ }
2245
+ else {
2246
+ $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
2247
+ }
2248
+ }
2249
+
2250
+ $v_dirlist_nb++;
2251
+ }
2252
+
2253
+ @closedir($v_folder_handler);
2254
+ }
2255
+ else {
2256
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to open dir '".$v_descr['filename']."' in read mode. Skipped.");
2257
+ // TBC : unable to open folder in read mode
2258
+ }
2259
+
2260
+ // ----- Expand each element of the list
2261
+ if ($v_dirlist_nb != 0) {
2262
+ // ----- Expand
2263
+ if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
2264
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2265
+ return $v_result;
2266
+ }
2267
+
2268
+ // ----- Concat the resulting list
2269
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Merging result list (size '".sizeof($v_result_list)."') with dirlist (size '".sizeof($v_dirlist_descr)."')");
2270
+ $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
2271
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "merged result list is size '".sizeof($v_result_list)."'");
2272
+ }
2273
+ else {
2274
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Nothing in this folder to expand.");
2275
+ }
2276
+
2277
+ // ----- Free local array
2278
+ unset($v_dirlist_descr);
2279
+ }
2280
+ }
2281
+
2282
+ // ----- Get the result list
2283
+ $p_filedescr_list = $v_result_list;
2284
+
2285
+ // ----- Return
2286
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2287
+ return $v_result;
2288
+ }
2289
+ // --------------------------------------------------------------------------------
2290
+
2291
+ // --------------------------------------------------------------------------------
2292
+ // Function : privCreate()
2293
+ // Description :
2294
+ // Parameters :
2295
+ // Return Values :
2296
+ // --------------------------------------------------------------------------------
2297
+ function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
2298
+ {
2299
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCreate", "list");
2300
+ $v_result=1;
2301
+ $v_list_detail = array();
2302
+
2303
+ // ----- Magic quotes trick
2304
+ $this->privDisableMagicQuotes();
2305
+
2306
+ // ----- Open the file in write mode
2307
+ if (($v_result = $this->privOpenFd('wb')) != 1)
2308
+ {
2309
+ // ----- Return
2310
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2311
+ return $v_result;
2312
+ }
2313
+
2314
+ // ----- Add the list of files
2315
+ $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
2316
+
2317
+ // ----- Close
2318
+ $this->privCloseFd();
2319
+
2320
+ // ----- Magic quotes trick
2321
+ $this->privSwapBackMagicQuotes();
2322
+
2323
+ // ----- Return
2324
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2325
+ return $v_result;
2326
+ }
2327
+ // --------------------------------------------------------------------------------
2328
+
2329
+ // --------------------------------------------------------------------------------
2330
+ // Function : privAdd()
2331
+ // Description :
2332
+ // Parameters :
2333
+ // Return Values :
2334
+ // --------------------------------------------------------------------------------
2335
+ function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
2336
+ {
2337
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAdd", "list");
2338
+ $v_result=1;
2339
+ $v_list_detail = array();
2340
+
2341
+ // ----- Look if the archive exists or is empty
2342
+ if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
2343
+ {
2344
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, or is empty, create it.");
2345
+
2346
+ // ----- Do a create
2347
+ $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
2348
+
2349
+ // ----- Return
2350
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2351
+ return $v_result;
2352
+ }
2353
+ // ----- Magic quotes trick
2354
+ $this->privDisableMagicQuotes();
2355
+
2356
+ // ----- Open the zip file
2357
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2358
+ if (($v_result=$this->privOpenFd('rb')) != 1)
2359
+ {
2360
+ // ----- Magic quotes trick
2361
+ $this->privSwapBackMagicQuotes();
2362
+
2363
+ // ----- Return
2364
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2365
+ return $v_result;
2366
+ }
2367
+
2368
+ // ----- Read the central directory informations
2369
+ $v_central_dir = array();
2370
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
2371
+ {
2372
+ $this->privCloseFd();
2373
+ $this->privSwapBackMagicQuotes();
2374
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2375
+ return $v_result;
2376
+ }
2377
+
2378
+ // ----- Go to beginning of File
2379
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
2380
+ @rewind($this->zip_fd);
2381
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
2382
+
2383
+ // ----- Creates a temporay file
2384
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
2385
+
2386
+ // ----- Open the temporary file in write mode
2387
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2388
+ if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
2389
+ {
2390
+ $this->privCloseFd();
2391
+ $this->privSwapBackMagicQuotes();
2392
+
2393
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
2394
+
2395
+ // ----- Return
2396
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2397
+ return PclZip::errorCode();
2398
+ }
2399
+
2400
+ // ----- Copy the files from the archive to the temporary file
2401
+ // TBC : Here I should better append the file and go back to erase the central dir
2402
+ $v_size = $v_central_dir['offset'];
2403
+ while ($v_size != 0)
2404
+ {
2405
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2406
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
2407
+ $v_buffer = fread($this->zip_fd, $v_read_size);
2408
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
2409
+ $v_size -= $v_read_size;
2410
+ }
2411
+
2412
+ // ----- Swap the file descriptor
2413
+ // Here is a trick : I swap the temporary fd with the zip fd, in order to use
2414
+ // the following methods on the temporary fil and not the real archive
2415
+ $v_swap = $this->zip_fd;
2416
+ $this->zip_fd = $v_zip_temp_fd;
2417
+ $v_zip_temp_fd = $v_swap;
2418
+
2419
+ // ----- Add the files
2420
+ $v_header_list = array();
2421
+ if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2422
+ {
2423
+ fclose($v_zip_temp_fd);
2424
+ $this->privCloseFd();
2425
+ @unlink($v_zip_temp_name);
2426
+ $this->privSwapBackMagicQuotes();
2427
+
2428
+ // ----- Return
2429
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2430
+ return $v_result;
2431
+ }
2432
+
2433
+ // ----- Store the offset of the central dir
2434
+ $v_offset = @ftell($this->zip_fd);
2435
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
2436
+
2437
+ // ----- Copy the block of file headers from the old archive
2438
+ $v_size = $v_central_dir['size'];
2439
+ while ($v_size != 0)
2440
+ {
2441
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2442
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
2443
+ $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
2444
+ @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2445
+ $v_size -= $v_read_size;
2446
+ }
2447
+
2448
+ // ----- Create the Central Dir files header
2449
+ for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
2450
+ {
2451
+ // ----- Create the file header
2452
+ if ($v_header_list[$i]['status'] == 'ok') {
2453
+ if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2454
+ fclose($v_zip_temp_fd);
2455
+ $this->privCloseFd();
2456
+ @unlink($v_zip_temp_name);
2457
+ $this->privSwapBackMagicQuotes();
2458
+
2459
+ // ----- Return
2460
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2461
+ return $v_result;
2462
+ }
2463
+ $v_count++;
2464
+ }
2465
+
2466
+ // ----- Transform the header to a 'usable' info
2467
+ $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2468
+ }
2469
+
2470
+ // ----- Zip file comment
2471
+ $v_comment = $v_central_dir['comment'];
2472
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2473
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2474
+ }
2475
+ if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
2476
+ $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
2477
+ }
2478
+ if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
2479
+ $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
2480
+ }
2481
+
2482
+ // ----- Calculate the size of the central header
2483
+ $v_size = @ftell($this->zip_fd)-$v_offset;
2484
+
2485
+ // ----- Create the central dir footer
2486
+ if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
2487
+ {
2488
+ // ----- Reset the file list
2489
+ unset($v_header_list);
2490
+ $this->privSwapBackMagicQuotes();
2491
+
2492
+ // ----- Return
2493
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2494
+ return $v_result;
2495
+ }
2496
+
2497
+ // ----- Swap back the file descriptor
2498
+ $v_swap = $this->zip_fd;
2499
+ $this->zip_fd = $v_zip_temp_fd;
2500
+ $v_zip_temp_fd = $v_swap;
2501
+
2502
+ // ----- Close
2503
+ $this->privCloseFd();
2504
+
2505
+ // ----- Close the temporary file
2506
+ @fclose($v_zip_temp_fd);
2507
+
2508
+ // ----- Magic quotes trick
2509
+ $this->privSwapBackMagicQuotes();
2510
+
2511
+ // ----- Delete the zip file
2512
+ // TBC : I should test the result ...
2513
+ @unlink($this->zipname);
2514
+
2515
+ // ----- Rename the temporary file
2516
+ // TBC : I should test the result ...
2517
+ //@rename($v_zip_temp_name, $this->zipname);
2518
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
2519
+
2520
+ // ----- Return
2521
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2522
+ return $v_result;
2523
+ }
2524
+ // --------------------------------------------------------------------------------
2525
+
2526
+ // --------------------------------------------------------------------------------
2527
+ // Function : privOpenFd()
2528
+ // Description :
2529
+ // Parameters :
2530
+ // --------------------------------------------------------------------------------
2531
+ function privOpenFd($p_mode)
2532
+ {
2533
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOpenFd", 'mode='.$p_mode);
2534
+ $v_result=1;
2535
+
2536
+ // ----- Look if already open
2537
+ if ($this->zip_fd != 0)
2538
+ {
2539
+ // ----- Error log
2540
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
2541
+
2542
+ // ----- Return
2543
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2544
+ return PclZip::errorCode();
2545
+ }
2546
+
2547
+ // ----- Open the zip file
2548
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Open file in '.$p_mode.' mode');
2549
+ if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
2550
+ {
2551
+ // ----- Error log
2552
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
2553
+
2554
+ // ----- Return
2555
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2556
+ return PclZip::errorCode();
2557
+ }
2558
+
2559
+ // ----- Return
2560
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2561
+ return $v_result;
2562
+ }
2563
+ // --------------------------------------------------------------------------------
2564
+
2565
+ // --------------------------------------------------------------------------------
2566
+ // Function : privCloseFd()
2567
+ // Description :
2568
+ // Parameters :
2569
+ // --------------------------------------------------------------------------------
2570
+ function privCloseFd()
2571
+ {
2572
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCloseFd", "");
2573
+ $v_result=1;
2574
+
2575
+ if ($this->zip_fd != 0)
2576
+ @fclose($this->zip_fd);
2577
+ $this->zip_fd = 0;
2578
+
2579
+ // ----- Return
2580
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2581
+ return $v_result;
2582
+ }
2583
+ // --------------------------------------------------------------------------------
2584
+
2585
+ // --------------------------------------------------------------------------------
2586
+ // Function : privAddList()
2587
+ // Description :
2588
+ // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2589
+ // different from the real path of the file. This is usefull if you want to have PclTar
2590
+ // running in any directory, and memorize relative path from an other directory.
2591
+ // Parameters :
2592
+ // $p_list : An array containing the file or directory names to add in the tar
2593
+ // $p_result_list : list of added files with their properties (specially the status field)
2594
+ // $p_add_dir : Path to add in the filename path archived
2595
+ // $p_remove_dir : Path to remove in the filename path archived
2596
+ // Return Values :
2597
+ // --------------------------------------------------------------------------------
2598
+ // function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2599
+ function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
2600
+ {
2601
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddList", "list");
2602
+ $v_result=1;
2603
+
2604
+ // ----- Add the files
2605
+ $v_header_list = array();
2606
+ if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2607
+ {
2608
+ // ----- Return
2609
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2610
+ return $v_result;
2611
+ }
2612
+
2613
+ // ----- Store the offset of the central dir
2614
+ $v_offset = @ftell($this->zip_fd);
2615
+
2616
+ // ----- Create the Central Dir files header
2617
+ for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
2618
+ {
2619
+ // ----- Create the file header
2620
+ if ($v_header_list[$i]['status'] == 'ok') {
2621
+ if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2622
+ // ----- Return
2623
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2624
+ return $v_result;
2625
+ }
2626
+ $v_count++;
2627
+ }
2628
+
2629
+ // ----- Transform the header to a 'usable' info
2630
+ $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2631
+ }
2632
+
2633
+ // ----- Zip file comment
2634
+ $v_comment = '';
2635
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2636
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2637
+ }
2638
+
2639
+ // ----- Calculate the size of the central header
2640
+ $v_size = @ftell($this->zip_fd)-$v_offset;
2641
+
2642
+ // ----- Create the central dir footer
2643
+ if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
2644
+ {
2645
+ // ----- Reset the file list
2646
+ unset($v_header_list);
2647
+
2648
+ // ----- Return
2649
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2650
+ return $v_result;
2651
+ }
2652
+
2653
+ // ----- Return
2654
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2655
+ return $v_result;
2656
+ }
2657
+ // --------------------------------------------------------------------------------
2658
+
2659
+ // --------------------------------------------------------------------------------
2660
+ // Function : privAddFileList()
2661
+ // Description :
2662
+ // Parameters :
2663
+ // $p_filedescr_list : An array containing the file description
2664
+ // or directory names to add in the zip
2665
+ // $p_result_list : list of added files with their properties (specially the status field)
2666
+ // Return Values :
2667
+ // --------------------------------------------------------------------------------
2668
+ function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
2669
+ {
2670
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileList", "filedescr_list");
2671
+ $v_result=1;
2672
+ $v_header = array();
2673
+
2674
+ // ----- Recuperate the current number of elt in list
2675
+ $v_nb = sizeof($p_result_list);
2676
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Before add, list have ".$v_nb." elements");
2677
+
2678
+ // ----- Loop on the files
2679
+ for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
2680
+ // ----- Format the filename
2681
+ $p_filedescr_list[$j]['filename']
2682
+ = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
2683
+
2684
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for file '".$p_filedescr_list[$j]['filename']."'");
2685
+
2686
+ // ----- Skip empty file names
2687
+ // TBC : Can this be possible ? not checked in DescrParseAtt ?
2688
+ if ($p_filedescr_list[$j]['filename'] == "") {
2689
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Skip empty filename");
2690
+ continue;
2691
+ }
2692
+
2693
+ // ----- Check the filename
2694
+ if ( ($p_filedescr_list[$j]['type'] != 'virtual_file')
2695
+ && (!file_exists($p_filedescr_list[$j]['filename']))) {
2696
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
2697
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
2698
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2699
+ return PclZip::errorCode();
2700
+ }
2701
+
2702
+ // ----- Look if it is a file or a dir with no all path remove option
2703
+ // or a dir with all its path removed
2704
+ // if ( (is_file($p_filedescr_list[$j]['filename']))
2705
+ // || ( is_dir($p_filedescr_list[$j]['filename'])
2706
+ if ( ($p_filedescr_list[$j]['type'] == 'file')
2707
+ || ($p_filedescr_list[$j]['type'] == 'virtual_file')
2708
+ || ( ($p_filedescr_list[$j]['type'] == 'folder')
2709
+ && ( !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
2710
+ || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
2711
+ ) {
2712
+
2713
+ // ----- Add the file
2714
+ $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
2715
+ $p_options);
2716
+ if ($v_result != 1) {
2717
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2718
+ return $v_result;
2719
+ }
2720
+
2721
+ // ----- Store the file infos
2722
+ $p_result_list[$v_nb++] = $v_header;
2723
+ }
2724
+ }
2725
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "After add, list have ".$v_nb." elements");
2726
+
2727
+ // ----- Return
2728
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2729
+ return $v_result;
2730
+ }
2731
+ // --------------------------------------------------------------------------------
2732
+
2733
+ // --------------------------------------------------------------------------------
2734
+ // Function : privAddFile()
2735
+ // Description :
2736
+ // Parameters :
2737
+ // Return Values :
2738
+ // --------------------------------------------------------------------------------
2739
+ function privAddFile($p_filedescr, &$p_header, &$p_options)
2740
+ {
2741
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFile", "filename='".$p_filedescr['filename']."'");
2742
+ $v_result=1;
2743
+
2744
+ // ----- Working variable
2745
+ $p_filename = $p_filedescr['filename'];
2746
+
2747
+ // TBC : Already done in the fileAtt check ... ?
2748
+ if ($p_filename == "") {
2749
+ // ----- Error log
2750
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
2751
+
2752
+ // ----- Return
2753
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2754
+ return PclZip::errorCode();
2755
+ }
2756
+
2757
+ // ----- Look for a stored different filename
2758
+ /* TBC : Removed
2759
+ if (isset($p_filedescr['stored_filename'])) {
2760
+ $v_stored_filename = $p_filedescr['stored_filename'];
2761
+ PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is NOT the same "'.$v_stored_filename.'"');
2762
+ }
2763
+ else {
2764
+ $v_stored_filename = $p_filedescr['stored_filename'];
2765
+ PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is the same');
2766
+ }
2767
+ */
2768
+
2769
+ // ----- Set the file properties
2770
+ clearstatcache();
2771
+ $p_header['version'] = 20;
2772
+ $p_header['version_extracted'] = 10;
2773
+ $p_header['flag'] = 0;
2774
+ $p_header['compression'] = 0;
2775
+ $p_header['crc'] = 0;
2776
+ $p_header['compressed_size'] = 0;
2777
+ $p_header['filename_len'] = strlen($p_filename);
2778
+ $p_header['extra_len'] = 0;
2779
+ $p_header['disk'] = 0;
2780
+ $p_header['internal'] = 0;
2781
+ $p_header['offset'] = 0;
2782
+ $p_header['filename'] = $p_filename;
2783
+ // TBC : Removed $p_header['stored_filename'] = $v_stored_filename;
2784
+ $p_header['stored_filename'] = $p_filedescr['stored_filename'];
2785
+ $p_header['extra'] = '';
2786
+ $p_header['status'] = 'ok';
2787
+ $p_header['index'] = -1;
2788
+
2789
+ // ----- Look for regular file
2790
+ if ($p_filedescr['type']=='file') {
2791
+ $p_header['external'] = 0x00000000;
2792
+ $p_header['size'] = filesize($p_filename);
2793
+ }
2794
+
2795
+ // ----- Look for regular folder
2796
+ else if ($p_filedescr['type']=='folder') {
2797
+ $p_header['external'] = 0x00000010;
2798
+ $p_header['mtime'] = filemtime($p_filename);
2799
+ $p_header['size'] = filesize($p_filename);
2800
+ }
2801
+
2802
+ // ----- Look for virtual file
2803
+ else if ($p_filedescr['type'] == 'virtual_file') {
2804
+ $p_header['external'] = 0x00000000;
2805
+ $p_header['size'] = strlen($p_filedescr['content']);
2806
+ }
2807
+
2808
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Header external extension '".sprintf("0x%X",$p_header['external'])."'");
2809
+
2810
+ // ----- Look for filetime
2811
+ if (isset($p_filedescr['mtime'])) {
2812
+ PclTraceFctMessage(__FILE__, __LINE__, 3,"Overload mtime value with :'".$p_filedescr['mtime']."'");
2813
+ $p_header['mtime'] = $p_filedescr['mtime'];
2814
+ }
2815
+ else if ($p_filedescr['type'] == 'virtual_file') {
2816
+ $p_header['mtime'] = time();
2817
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Virtual file : use current time '".$p_header['mtime']."' for mtime value.");
2818
+ }
2819
+ else {
2820
+ $p_header['mtime'] = filemtime($p_filename);
2821
+ }
2822
+
2823
+ // ------ Look for file comment
2824
+ if (isset($p_filedescr['comment'])) {
2825
+ $p_header['comment_len'] = strlen($p_filedescr['comment']);
2826
+ $p_header['comment'] = $p_filedescr['comment'];
2827
+ }
2828
+ else {
2829
+ $p_header['comment_len'] = 0;
2830
+ $p_header['comment'] = '';
2831
+ }
2832
+
2833
+ // ----- Look for pre-add callback
2834
+ if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
2835
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_ADD]."()') is defined for the extraction");
2836
+
2837
+ // ----- Generate a local information
2838
+ $v_local_header = array();
2839
+ $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2840
+
2841
+ // ----- Call the callback
2842
+ // Here I do not use call_user_func() because I need to send a reference to the
2843
+ // header.
2844
+ // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
2845
+ $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
2846
+ if ($v_result == 0) {
2847
+ // ----- Change the file status
2848
+ $p_header['status'] = "skipped";
2849
+ $v_result = 1;
2850
+ }
2851
+
2852
+ // ----- Update the informations
2853
+ // Only some fields can be modified
2854
+ if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2855
+ $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
2856
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "New stored filename is '".$p_header['stored_filename']."'");
2857
+ }
2858
+ }
2859
+
2860
+ // ----- Look for empty stored filename
2861
+ if ($p_header['stored_filename'] == "") {
2862
+ $p_header['status'] = "filtered";
2863
+ }
2864
+
2865
+ // ----- Check the path length
2866
+ if (strlen($p_header['stored_filename']) > 0xFF) {
2867
+ $p_header['status'] = 'filename_too_long';
2868
+ }
2869
+
2870
+ // ----- Look if no error, or file not skipped
2871
+ if ($p_header['status'] == 'ok') {
2872
+
2873
+ // ----- Look for a file
2874
+ if ($p_filedescr['type'] == 'file') {
2875
+ // ----- Look for using temporary file to zip
2876
+ if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
2877
+ && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
2878
+ || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
2879
+ && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) {
2880
+ $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
2881
+ if ($v_result < PCLZIP_ERR_NO_ERROR) {
2882
+ return $v_result;
2883
+ }
2884
+ }
2885
+
2886
+ // ----- Use "in memory" zip algo
2887
+ else {
2888
+ PclTraceFctMessage(__FILE__, __LINE__, 2,"In memory compression.");
2889
+ PclTraceFctMessage(__FILE__, __LINE__, 2,"Current memory usage : ".memory_get_usage(TRUE)." bytes");
2890
+ PclTraceFctMessage(__FILE__, __LINE__, 2,"Current memory peak : ".memory_get_peak_usage(TRUE)." bytes");
2891
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a file");
2892
+
2893
+ // ----- Open the source file
2894
+ if (($v_file = @fopen($p_filename, "rb")) == 0) {
2895
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2896
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2897
+ return PclZip::errorCode();
2898
+ }
2899
+
2900
+ // ----- Read the file content
2901
+ $v_content = @fread($v_file, $p_header['size']);
2902
+ PclTraceFctMessage(__FILE__, __LINE__, 2,"Memory usage after reading file : ".memory_get_usage(TRUE)." bytes");
2903
+ PclTraceFctMessage(__FILE__, __LINE__, 2,"Memory peak after reading file : ".memory_get_peak_usage(TRUE)." bytes");
2904
+
2905
+ // ----- Close the file
2906
+ @fclose($v_file);
2907
+
2908
+ // ----- Calculate the CRC
2909
+ $p_header['crc'] = @crc32($v_content);
2910
+
2911
+ // ----- Look for no compression
2912
+ if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2913
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be compressed");
2914
+ // ----- Set header parameters
2915
+ $p_header['compressed_size'] = $p_header['size'];
2916
+ $p_header['compression'] = 0;
2917
+ }
2918
+
2919
+ // ----- Look for normal compression
2920
+ else {
2921
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File will be compressed");
2922
+ // ----- Compress the content
2923
+ $v_content = @gzdeflate($v_content);
2924
+ PclTraceFctMessage(__FILE__, __LINE__, 2,"Memory usage after gzdeflate : ".memory_get_usage(TRUE)." bytes");
2925
+ PclTraceFctMessage(__FILE__, __LINE__, 2,"Memory peak after gzdeflate : ".memory_get_peak_usage(TRUE)." bytes");
2926
+
2927
+ // ----- Set header parameters
2928
+ $p_header['compressed_size'] = strlen($v_content);
2929
+ $p_header['compression'] = 8;
2930
+ }
2931
+
2932
+ // ----- Call the header generation
2933
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2934
+ @fclose($v_file);
2935
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2936
+ return $v_result;
2937
+ }
2938
+
2939
+ // ----- Write the compressed (or not) content
2940
+ @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2941
+
2942
+ }
2943
+
2944
+ }
2945
+
2946
+ // ----- Look for a virtual file (a file from string)
2947
+ else if ($p_filedescr['type'] == 'virtual_file') {
2948
+
2949
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Add by string");
2950
+ $v_content = $p_filedescr['content'];
2951
+
2952
+ // ----- Calculate the CRC
2953
+ $p_header['crc'] = @crc32($v_content);
2954
+
2955
+ // ----- Look for no compression
2956
+ if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2957
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be compressed");
2958
+ // ----- Set header parameters
2959
+ $p_header['compressed_size'] = $p_header['size'];
2960
+ $p_header['compression'] = 0;
2961
+ }
2962
+
2963
+ // ----- Look for normal compression
2964
+ else {
2965
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File will be compressed");
2966
+ // ----- Compress the content
2967
+ $v_content = @gzdeflate($v_content);
2968
+
2969
+ // ----- Set header parameters
2970
+ $p_header['compressed_size'] = strlen($v_content);
2971
+ $p_header['compression'] = 8;
2972
+ }
2973
+
2974
+ // ----- Call the header generation
2975
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2976
+ @fclose($v_file);
2977
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2978
+ return $v_result;
2979
+ }
2980
+
2981
+ // ----- Write the compressed (or not) content
2982
+ @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2983
+ }
2984
+
2985
+ // ----- Look for a directory
2986
+ else if ($p_filedescr['type'] == 'folder') {
2987
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a folder");
2988
+ // ----- Look for directory last '/'
2989
+ if (@substr($p_header['stored_filename'], -1) != '/') {
2990
+ $p_header['stored_filename'] .= '/';
2991
+ }
2992
+
2993
+ // ----- Set the file properties
2994
+ $p_header['size'] = 0;
2995
+ //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
2996
+ $p_header['external'] = 0x00000010; // Value for a folder : to be checked
2997
+
2998
+ // ----- Call the header generation
2999
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
3000
+ {
3001
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3002
+ return $v_result;
3003
+ }
3004
+ }
3005
+ }
3006
+
3007
+ // ----- Look for post-add callback
3008
+ if (isset($p_options[PCLZIP_CB_POST_ADD])) {
3009
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_ADD]."()') is defined for the extraction");
3010
+
3011
+ // ----- Generate a local information
3012
+ $v_local_header = array();
3013
+ $this->privConvertHeader2FileInfo($p_header, $v_local_header);
3014
+
3015
+ // ----- Call the callback
3016
+ // Here I do not use call_user_func() because I need to send a reference to the
3017
+ // header.
3018
+ // eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
3019
+ $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header);
3020
+ if ($v_result == 0) {
3021
+ // ----- Ignored
3022
+ $v_result = 1;
3023
+ }
3024
+
3025
+ // ----- Update the informations
3026
+ // Nothing can be modified
3027
+ }
3028
+
3029
+ // ----- Return
3030
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3031
+ return $v_result;
3032
+ }
3033
+ // --------------------------------------------------------------------------------
3034
+
3035
+ // --------------------------------------------------------------------------------
3036
+ // Function : privAddFileUsingTempFile()
3037
+ // Description :
3038
+ // Parameters :
3039
+ // Return Values :
3040
+ // --------------------------------------------------------------------------------
3041
+ function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
3042
+ {
3043
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileUsingTempFile", "filename='".$p_filedescr['filename']."'");
3044
+ $v_result=PCLZIP_ERR_NO_ERROR;
3045
+
3046
+ // ----- Working variable
3047
+ $p_filename = $p_filedescr['filename'];
3048
+
3049
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a file");
3050
+
3051
+ // ----- Open the source file
3052
+ if (($v_file = @fopen($p_filename, "rb")) == 0) {
3053
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
3054
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3055
+ return PclZip::errorCode();
3056
+ }
3057
+
3058
+ // ----- Creates a compressed temporary file
3059
+ $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
3060
+ if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
3061
+ fclose($v_file);
3062
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
3063
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3064
+ return PclZip::errorCode();
3065
+ }
3066
+
3067
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3068
+ $v_size = filesize($p_filename);
3069
+ while ($v_size != 0) {
3070
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3071
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read ".$v_read_size." bytes");
3072
+ $v_buffer = @fread($v_file, $v_read_size);
3073
+ //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3074
+ @gzputs($v_file_compressed, $v_buffer, $v_read_size);
3075
+ $v_size -= $v_read_size;
3076
+ }
3077
+
3078
+ // ----- Close the file
3079
+ @fclose($v_file);
3080
+ @gzclose($v_file_compressed);
3081
+
3082
+ // ----- Check the minimum file size
3083
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "gzip file size ".filesize($v_gzip_temp_name));
3084
+ if (filesize($v_gzip_temp_name) < 18) {
3085
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
3086
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3087
+ return PclZip::errorCode();
3088
+ }
3089
+
3090
+ // ----- Extract the compressed attributes
3091
+ if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
3092
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
3093
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3094
+ return PclZip::errorCode();
3095
+ }
3096
+
3097
+ // ----- Read the gzip file header
3098
+ $v_binary_data = @fread($v_file_compressed, 10);
3099
+ $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
3100
+
3101
+ // ----- Check some parameters
3102
+ PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[id1]='.bin2hex($v_data_header['id1']));
3103
+ PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[id2]='.bin2hex($v_data_header['id2']));
3104
+ PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[cm]='.bin2hex($v_data_header['cm']));
3105
+ PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[flag]='.bin2hex($v_data_header['flag']));
3106
+ PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[mtime]='.$v_data_header['mtime']);
3107
+ PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[xfl]='.bin2hex($v_data_header['xfl']));
3108
+ PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[os]='.bin2hex($v_data_header['os']));
3109
+ $v_data_header['os'] = bin2hex($v_data_header['os']);
3110
+
3111
+ // ----- Read the gzip file footer
3112
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "File position after header ".ftell($v_file_compressed));
3113
+ @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8);
3114
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "File position at beginning of footer ".ftell($v_file_compressed));
3115
+ $v_binary_data = @fread($v_file_compressed, 8);
3116
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "File position after footer ".ftell($v_file_compressed));
3117
+ $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);
3118
+
3119
+ // ----- Set the attributes
3120
+ $p_header['compression'] = ord($v_data_header['cm']);
3121
+ //$p_header['mtime'] = $v_data_header['mtime'];
3122
+ $p_header['crc'] = $v_data_footer['crc'];
3123
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Compressed size ".(filesize($v_gzip_temp_name)-18));
3124
+ $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18;
3125
+
3126
+ // ----- Close the file
3127
+ @fclose($v_file_compressed);
3128
+
3129
+ // ----- Call the header generation
3130
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
3131
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3132
+ return $v_result;
3133
+ }
3134
+
3135
+ // ----- Add the compressed data
3136
+ if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0)
3137
+ {
3138
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
3139
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3140
+ return PclZip::errorCode();
3141
+ }
3142
+
3143
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3144
+ fseek($v_file_compressed, 10);
3145
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "File position before reading compressed data ".ftell($v_file_compressed));
3146
+ PclTraceFctMessage(__FILE__, __LINE__, 4, ' '.$p_header['compressed_size'].' bytes to read');
3147
+ $v_size = $p_header['compressed_size'];
3148
+ while ($v_size != 0)
3149
+ {
3150
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3151
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read ".$v_read_size." bytes");
3152
+ $v_buffer = @fread($v_file_compressed, $v_read_size);
3153
+ //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3154
+ @fwrite($this->zip_fd, $v_buffer, $v_read_size);
3155
+ $v_size -= $v_read_size;
3156
+ }
3157
+
3158
+ // ----- Close the file
3159
+ @fclose($v_file_compressed);
3160
+
3161
+ // ----- Unlink the temporary file
3162
+ @unlink($v_gzip_temp_name);
3163
+
3164
+ // ----- Return
3165
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3166
+ return $v_result;
3167
+ }
3168
+ // --------------------------------------------------------------------------------
3169
+
3170
+ // --------------------------------------------------------------------------------
3171
+ // Function : privCalculateStoredFilename()
3172
+ // Description :
3173
+ // Based on file descriptor properties and global options, this method
3174
+ // calculate the filename that will be stored in the archive.
3175
+ // Parameters :
3176
+ // Return Values :
3177
+ // --------------------------------------------------------------------------------
3178
+ function privCalculateStoredFilename(&$p_filedescr, &$p_options)
3179
+ {
3180
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCalculateStoredFilename", "filename='".$p_filedescr['filename']."'");
3181
+ $v_result=1;
3182
+
3183
+ // ----- Working variables
3184
+ $p_filename = $p_filedescr['filename'];
3185
+ if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
3186
+ $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH];
3187
+ }
3188
+ else {
3189
+ $p_add_dir = '';
3190
+ }
3191
+ if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) {
3192
+ $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH];
3193
+ }
3194
+ else {
3195
+ $p_remove_dir = '';
3196
+ }
3197
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Remove path ='".$p_remove_dir."'");
3198
+ if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
3199
+ $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
3200
+ }
3201
+ else {
3202
+ $p_remove_all_dir = 0;
3203
+ }
3204
+
3205
+
3206
+ // ----- Look for full name change
3207
+ if (isset($p_filedescr['new_full_name'])) {
3208
+ // ----- Remove drive letter if any
3209
+ $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
3210
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing full name of '".$p_filename."' for '".$v_stored_filename."'");
3211
+ }
3212
+
3213
+ // ----- Look for path and/or short name change
3214
+ else {
3215
+
3216
+ // ----- Look for short name change
3217
+ // Its when we cahnge just the filename but not the path
3218
+ if (isset($p_filedescr['new_short_name'])) {
3219
+ $v_path_info = pathinfo($p_filename);
3220
+ $v_dir = '';
3221
+ if ($v_path_info['dirname'] != '') {
3222
+ $v_dir = $v_path_info['dirname'].'/';
3223
+ }
3224
+ $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
3225
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing short name of '".$p_filename."' for '".$v_stored_filename."'");
3226
+ }
3227
+ else {
3228
+ // ----- Calculate the stored filename
3229
+ $v_stored_filename = $p_filename;
3230
+ }
3231
+
3232
+ // ----- Look for all path to remove
3233
+ if ($p_remove_all_dir) {
3234
+ $v_stored_filename = basename($p_filename);
3235
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove all path selected change '".$p_filename."' for '".$v_stored_filename."'");
3236
+ }
3237
+ // ----- Look for partial path remove
3238
+ else if ($p_remove_dir != "") {
3239
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Partial path to remove");
3240
+ if (substr($p_remove_dir, -1) != '/')
3241
+ $p_remove_dir .= "/";
3242
+
3243
+ if ( (substr($p_filename, 0, 2) == "./")
3244
+ || (substr($p_remove_dir, 0, 2) == "./")) {
3245
+
3246
+ if ( (substr($p_filename, 0, 2) == "./")
3247
+ && (substr($p_remove_dir, 0, 2) != "./")) {
3248
+ $p_remove_dir = "./".$p_remove_dir;
3249
+ }
3250
+ if ( (substr($p_filename, 0, 2) != "./")
3251
+ && (substr($p_remove_dir, 0, 2) == "./")) {
3252
+ $p_remove_dir = substr($p_remove_dir, 2);
3253
+ }
3254
+ }
3255
+
3256
+ $v_compare = PclZipUtilPathInclusion($p_remove_dir,
3257
+ $v_stored_filename);
3258
+ if ($v_compare > 0) {
3259
+ if ($v_compare == 2) {
3260
+ $v_stored_filename = "";
3261
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Path to remove is the current folder");
3262
+ }
3263
+ else {
3264
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove path '$p_remove_dir' in file '$v_stored_filename'");
3265
+ $v_stored_filename = substr($v_stored_filename,
3266
+ strlen($p_remove_dir));
3267
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Result is '$v_stored_filename'");
3268
+ }
3269
+ }
3270
+ }
3271
+
3272
+ // ----- Remove drive letter if any
3273
+ $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename);
3274
+
3275
+ // ----- Look for path to add
3276
+ if ($p_add_dir != "") {
3277
+ if (substr($p_add_dir, -1) == "/")
3278
+ $v_stored_filename = $p_add_dir.$v_stored_filename;
3279
+ else
3280
+ $v_stored_filename = $p_add_dir."/".$v_stored_filename;
3281
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
3282
+ }
3283
+ }
3284
+
3285
+ // ----- Filename (reduce the path of stored name)
3286
+ $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
3287
+ $p_filedescr['stored_filename'] = $v_stored_filename;
3288
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Stored filename will be '".$p_filedescr['stored_filename']."', strlen ".strlen($p_filedescr['stored_filename']));
3289
+
3290
+ // ----- Return
3291
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3292
+ return $v_result;
3293
+ }
3294
+ // --------------------------------------------------------------------------------
3295
+
3296
+ // --------------------------------------------------------------------------------
3297
+ // Function : privWriteFileHeader()
3298
+ // Description :
3299
+ // Parameters :
3300
+ // Return Values :
3301
+ // --------------------------------------------------------------------------------
3302
+ function privWriteFileHeader(&$p_header)
3303
+ {
3304
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
3305
+ $v_result=1;
3306
+
3307
+ // ----- Store the offset position of the file
3308
+ $p_header['offset'] = ftell($this->zip_fd);
3309
+ PclTraceFctMessage(__FILE__, __LINE__, 2, 'File offset of the header :'.$p_header['offset']);
3310
+
3311
+ // ----- Transform UNIX mtime to DOS format mdate/mtime
3312
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
3313
+ $v_date = getdate($p_header['mtime']);
3314
+ $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3315
+ $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3316
+
3317
+ // ----- Packed data
3318
+ $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
3319
+ $p_header['version_extracted'], $p_header['flag'],
3320
+ $p_header['compression'], $v_mtime, $v_mdate,
3321
+ $p_header['crc'], $p_header['compressed_size'],
3322
+ $p_header['size'],
3323
+ strlen($p_header['stored_filename']),
3324
+ $p_header['extra_len']);
3325
+
3326
+ // ----- Write the first 148 bytes of the header in the archive
3327
+ fputs($this->zip_fd, $v_binary_data, 30);
3328
+
3329
+ // ----- Write the variable fields
3330
+ if (strlen($p_header['stored_filename']) != 0)
3331
+ {
3332
+ fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3333
+ }
3334
+ if ($p_header['extra_len'] != 0)
3335
+ {
3336
+ fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3337
+ }
3338
+
3339
+ // ----- Return
3340
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3341
+ return $v_result;
3342
+ }
3343
+ // --------------------------------------------------------------------------------
3344
+
3345
+ // --------------------------------------------------------------------------------
3346
+ // Function : privWriteCentralFileHeader()
3347
+ // Description :
3348
+ // Parameters :
3349
+ // Return Values :
3350
+ // --------------------------------------------------------------------------------
3351
+ function privWriteCentralFileHeader(&$p_header)
3352
+ {
3353
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
3354
+ $v_result=1;
3355
+
3356
+ // TBC
3357
+ //for(reset($p_header); $key = key($p_header); next($p_header)) {
3358
+ // PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
3359
+ //}
3360
+
3361
+ // ----- Transform UNIX mtime to DOS format mdate/mtime
3362
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
3363
+ $v_date = getdate($p_header['mtime']);
3364
+ $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3365
+ $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3366
+
3367
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment size : \''.$p_header['comment_len'].'\'');
3368
+
3369
+ // ----- Packed data
3370
+ $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
3371
+ $p_header['version'], $p_header['version_extracted'],
3372
+ $p_header['flag'], $p_header['compression'],
3373
+ $v_mtime, $v_mdate, $p_header['crc'],
3374
+ $p_header['compressed_size'], $p_header['size'],
3375
+ strlen($p_header['stored_filename']),
3376
+ $p_header['extra_len'], $p_header['comment_len'],
3377
+ $p_header['disk'], $p_header['internal'],
3378
+ $p_header['external'], $p_header['offset']);
3379
+
3380
+ // ----- Write the 42 bytes of the header in the zip file
3381
+ fputs($this->zip_fd, $v_binary_data, 46);
3382
+
3383
+ // ----- Write the variable fields
3384
+ if (strlen($p_header['stored_filename']) != 0)
3385
+ {
3386
+ fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3387
+ }
3388
+ if ($p_header['extra_len'] != 0)
3389
+ {
3390
+ fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3391
+ }
3392
+ if ($p_header['comment_len'] != 0)
3393
+ {
3394
+ fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
3395
+ }
3396
+
3397
+ // ----- Return
3398
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3399
+ return $v_result;
3400
+ }
3401
+ // --------------------------------------------------------------------------------
3402
+
3403
+ // --------------------------------------------------------------------------------
3404
+ // Function : privWriteCentralHeader()
3405
+ // Description :
3406
+ // Parameters :
3407
+ // Return Values :
3408
+ // --------------------------------------------------------------------------------
3409
+ function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
3410
+ {
3411
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralHeader", 'nb_entries='.$p_nb_entries.', size='.$p_size.', offset='.$p_offset.', comment="'.$p_comment.'"');
3412
+ $v_result=1;
3413
+
3414
+ // ----- Packed data
3415
+ $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
3416
+ $p_nb_entries, $p_size,
3417
+ $p_offset, strlen($p_comment));
3418
+
3419
+ // ----- Write the 22 bytes of the header in the zip file
3420
+ fputs($this->zip_fd, $v_binary_data, 22);
3421
+
3422
+ // ----- Write the variable fields
3423
+ if (strlen($p_comment) != 0)
3424
+ {
3425
+ fputs($this->zip_fd, $p_comment, strlen($p_comment));
3426
+ }
3427
+
3428
+ // ----- Return
3429
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3430
+ return $v_result;
3431
+ }
3432
+ // --------------------------------------------------------------------------------
3433
+
3434
+ // --------------------------------------------------------------------------------
3435
+ // Function : privList()
3436
+ // Description :
3437
+ // Parameters :
3438
+ // Return Values :
3439
+ // --------------------------------------------------------------------------------
3440
+ function privList(&$p_list)
3441
+ {
3442
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privList", "list");
3443
+ $v_result=1;
3444
+
3445
+ // ----- Magic quotes trick
3446
+ $this->privDisableMagicQuotes();
3447
+
3448
+ // ----- Open the zip file
3449
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
3450
+ if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
3451
+ {
3452
+ // ----- Magic quotes trick
3453
+ $this->privSwapBackMagicQuotes();
3454
+
3455
+ // ----- Error log
3456
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
3457
+
3458
+ // ----- Return
3459
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3460
+ return PclZip::errorCode();
3461
+ }
3462
+
3463
+ // ----- Read the central directory informations
3464
+ $v_central_dir = array();
3465
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3466
+ {
3467
+ $this->privSwapBackMagicQuotes();
3468
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3469
+ return $v_result;
3470
+ }
3471
+
3472
+ // ----- Go to beginning of Central Dir
3473
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset : ".$v_central_dir['offset']."'");
3474
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
3475
+ @rewind($this->zip_fd);
3476
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
3477
+ if (@fseek($this->zip_fd, $v_central_dir['offset']))
3478
+ {
3479
+ $this->privSwapBackMagicQuotes();
3480
+
3481
+ // ----- Error log
3482
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3483
+
3484
+ // ----- Return
3485
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3486
+ return PclZip::errorCode();
3487
+ }
3488
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
3489
+
3490
+ // ----- Read each entry
3491
+ for ($i=0; $i<$v_central_dir['entries']; $i++)
3492
+ {
3493
+ // ----- Read the file header
3494
+ if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3495
+ {
3496
+ $this->privSwapBackMagicQuotes();
3497
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3498
+ return $v_result;
3499
+ }
3500
+ $v_header['index'] = $i;
3501
+
3502
+ // ----- Get the only interesting attributes
3503
+ $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
3504
+ unset($v_header);
3505
+ }
3506
+
3507
+ // ----- Close the zip file
3508
+ $this->privCloseFd();
3509
+
3510
+ // ----- Magic quotes trick
3511
+ $this->privSwapBackMagicQuotes();
3512
+
3513
+ // ----- Return
3514
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3515
+ return $v_result;
3516
+ }
3517
+ // --------------------------------------------------------------------------------
3518
+
3519
+ // --------------------------------------------------------------------------------
3520
+ // Function : privConvertHeader2FileInfo()
3521
+ // Description :
3522
+ // This function takes the file informations from the central directory
3523
+ // entries and extract the interesting parameters that will be given back.
3524
+ // The resulting file infos are set in the array $p_info
3525
+ // $p_info['filename'] : Filename with full path. Given by user (add),
3526
+ // extracted in the filesystem (extract).
3527
+ // $p_info['stored_filename'] : Stored filename in the archive.
3528
+ // $p_info['size'] = Size of the file.
3529
+ // $p_info['compressed_size'] = Compressed size of the file.
3530
+ // $p_info['mtime'] = Last modification date of the file.
3531
+ // $p_info['comment'] = Comment associated with the file.
3532
+ // $p_info['folder'] = true/false : indicates if the entry is a folder or not.
3533
+ // $p_info['status'] = status of the action on the file.
3534
+ // $p_info['crc'] = CRC of the file content.
3535
+ // Parameters :
3536
+ // Return Values :
3537
+ // --------------------------------------------------------------------------------
3538
+ function privConvertHeader2FileInfo($p_header, &$p_info)
3539
+ {
3540
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privConvertHeader2FileInfo", "Filename='".$p_header['filename']."'");
3541
+ $v_result=1;
3542
+
3543
+ // ----- Get the interesting attributes
3544
+ $v_temp_path = PclZipUtilPathReduction($p_header['filename']);
3545
+ $p_info['filename'] = $v_temp_path;
3546
+ $v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']);
3547
+ $p_info['stored_filename'] = $v_temp_path;
3548
+ $p_info['size'] = $p_header['size'];
3549
+ $p_info['compressed_size'] = $p_header['compressed_size'];
3550
+ $p_info['mtime'] = $p_header['mtime'];
3551
+ $p_info['comment'] = $p_header['comment'];
3552
+ $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
3553
+ $p_info['index'] = $p_header['index'];
3554
+ $p_info['status'] = $p_header['status'];
3555
+ $p_info['crc'] = $p_header['crc'];
3556
+
3557
+ // ----- Return
3558
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3559
+ return $v_result;
3560
+ }
3561
+ // --------------------------------------------------------------------------------
3562
+
3563
+ // --------------------------------------------------------------------------------
3564
+ // Function : privExtractByRule()
3565
+ // Description :
3566
+ // Extract a file or directory depending of rules (by index, by name, ...)
3567
+ // Parameters :
3568
+ // $p_file_list : An array where will be placed the properties of each
3569
+ // extracted file
3570
+ // $p_path : Path to add while writing the extracted files
3571
+ // $p_remove_path : Path to remove (from the file memorized path) while writing the
3572
+ // extracted files. If the path does not match the file path,
3573
+ // the file is extracted with its memorized path.
3574
+ // $p_remove_path does not apply to 'list' mode.
3575
+ // $p_path and $p_remove_path are commulative.
3576
+ // Return Values :
3577
+ // 1 on success,0 or less on error (see error code list)
3578
+ // --------------------------------------------------------------------------------
3579
+ function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3580
+ {
3581
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtractByRule", "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
3582
+ $v_result=1;
3583
+
3584
+ // ----- Magic quotes trick
3585
+ $this->privDisableMagicQuotes();
3586
+
3587
+ // ----- Check the path
3588
+ if ( ($p_path == "")
3589
+ || ( (substr($p_path, 0, 1) != "/")
3590
+ && (substr($p_path, 0, 3) != "../")
3591
+ && (substr($p_path,1,2)!=":/")))
3592
+ $p_path = "./".$p_path;
3593
+
3594
+ // ----- Reduce the path last (and duplicated) '/'
3595
+ if (($p_path != "./") && ($p_path != "/"))
3596
+ {
3597
+ // ----- Look for the path end '/'
3598
+ while (substr($p_path, -1) == "/")
3599
+ {
3600
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
3601
+ $p_path = substr($p_path, 0, strlen($p_path)-1);
3602
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
3603
+ }
3604
+ }
3605
+
3606
+ // ----- Look for path to remove format (should end by /)
3607
+ if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
3608
+ {
3609
+ $p_remove_path .= '/';
3610
+ }
3611
+ $p_remove_path_size = strlen($p_remove_path);
3612
+
3613
+ // ----- Open the zip file
3614
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
3615
+ if (($v_result = $this->privOpenFd('rb')) != 1)
3616
+ {
3617
+ $this->privSwapBackMagicQuotes();
3618
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3619
+ return $v_result;
3620
+ }
3621
+
3622
+ // ----- Read the central directory informations
3623
+ $v_central_dir = array();
3624
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3625
+ {
3626
+ // ----- Close the zip file
3627
+ $this->privCloseFd();
3628
+ $this->privSwapBackMagicQuotes();
3629
+
3630
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3631
+ return $v_result;
3632
+ }
3633
+
3634
+ // ----- Start at beginning of Central Dir
3635
+ $v_pos_entry = $v_central_dir['offset'];
3636
+
3637
+ // ----- Read each entry
3638
+ $j_start = 0;
3639
+ for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
3640
+ {
3641
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : '$i'");
3642
+
3643
+ // ----- Read next Central dir entry
3644
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Position before rewind : ".ftell($this->zip_fd)."'");
3645
+ @rewind($this->zip_fd);
3646
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Position after rewind : ".ftell($this->zip_fd)."'");
3647
+ if (@fseek($this->zip_fd, $v_pos_entry))
3648
+ {
3649
+ // ----- Close the zip file
3650
+ $this->privCloseFd();
3651
+ $this->privSwapBackMagicQuotes();
3652
+
3653
+ // ----- Error log
3654
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3655
+
3656
+ // ----- Return
3657
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3658
+ return PclZip::errorCode();
3659
+ }
3660
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");
3661
+
3662
+ // ----- Read the file header
3663
+ $v_header = array();
3664
+ if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3665
+ {
3666
+ // ----- Close the zip file
3667
+ $this->privCloseFd();
3668
+ $this->privSwapBackMagicQuotes();
3669
+
3670
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3671
+ return $v_result;
3672
+ }
3673
+
3674
+ // ----- Store the index
3675
+ $v_header['index'] = $i;
3676
+
3677
+ // ----- Store the file position
3678
+ $v_pos_entry = ftell($this->zip_fd);
3679
+
3680
+ // ----- Look for the specific extract rules
3681
+ $v_extract = false;
3682
+
3683
+ // ----- Look for extract by name rule
3684
+ if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
3685
+ && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
3686
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
3687
+
3688
+ // ----- Look if the filename is in the list
3689
+ for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
3690
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
3691
+
3692
+ // ----- Look for a directory
3693
+ if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
3694
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
3695
+
3696
+ // ----- Look if the directory is in the filename path
3697
+ if ( (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
3698
+ && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
3699
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
3700
+ $v_extract = true;
3701
+ }
3702
+ }
3703
+ // ----- Look for a filename
3704
+ elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
3705
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
3706
+ $v_extract = true;
3707
+ }
3708
+ }
3709
+ }
3710
+
3711
+ // ----- Look for extract by ereg rule
3712
+ // ereg() is deprecated with PHP 5.3
3713
+ /*
3714
+ else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
3715
+ && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
3716
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
3717
+
3718
+ if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
3719
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
3720
+ $v_extract = true;
3721
+ }
3722
+ }
3723
+ */
3724
+
3725
+ // ----- Look for extract by preg rule
3726
+ else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
3727
+ && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
3728
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
3729
+
3730
+ if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
3731
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
3732
+ $v_extract = true;
3733
+ }
3734
+ }
3735
+
3736
+ // ----- Look for extract by index rule
3737
+ else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
3738
+ && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
3739
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
3740
+
3741
+ // ----- Look if the index is in the list
3742
+ for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
3743
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
3744
+
3745
+ if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
3746
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
3747
+ $v_extract = true;
3748
+ }
3749
+ if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
3750
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
3751
+ $j_start = $j+1;
3752
+ }
3753
+
3754
+ if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
3755
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
3756
+ break;
3757
+ }
3758
+ }
3759
+ }
3760
+
3761
+ // ----- Look for no rule, which means extract all the archive
3762
+ else {
3763
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with no rule (extract all)");
3764
+ $v_extract = true;
3765
+ }
3766
+
3767
+ // ----- Check compression method
3768
+ if ( ($v_extract)
3769
+ && ( ($v_header['compression'] != 8)
3770
+ && ($v_header['compression'] != 0))) {
3771
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported compression method (".$v_header['compression'].")");
3772
+ $v_header['status'] = 'unsupported_compression';
3773
+
3774
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3775
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3776
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3777
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
3778
+
3779
+ $this->privSwapBackMagicQuotes();
3780
+
3781
+ PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
3782
+ "Filename '".$v_header['stored_filename']."' is "
3783
+ ."compressed by an unsupported compression "
3784
+ ."method (".$v_header['compression'].") ");
3785
+
3786
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3787
+ return PclZip::errorCode();
3788
+ }
3789
+ }
3790
+
3791
+ // ----- Check encrypted files
3792
+ if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
3793
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported file encryption");
3794
+ $v_header['status'] = 'unsupported_encryption';
3795
+
3796
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3797
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3798
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3799
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
3800
+
3801
+ $this->privSwapBackMagicQuotes();
3802
+
3803
+ PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
3804
+ "Unsupported encryption for "
3805
+ ." filename '".$v_header['stored_filename']
3806
+ ."'");
3807
+
3808
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3809
+ return PclZip::errorCode();
3810
+ }
3811
+ }
3812
+
3813
+ // ----- Look for real extraction
3814
+ if (($v_extract) && ($v_header['status'] != 'ok')) {
3815
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "No need for extract");
3816
+ $v_result = $this->privConvertHeader2FileInfo($v_header,
3817
+ $p_file_list[$v_nb_extracted++]);
3818
+ if ($v_result != 1) {
3819
+ $this->privCloseFd();
3820
+ $this->privSwapBackMagicQuotes();
3821
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3822
+ return $v_result;
3823
+ }
3824
+
3825
+ $v_extract = false;
3826
+ }
3827
+
3828
+ // ----- Look for real extraction
3829
+ if ($v_extract)
3830
+ {
3831
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file '".$v_header['filename']."', index '$i'");
3832
+
3833
+ // ----- Go to the file position
3834
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
3835
+ @rewind($this->zip_fd);
3836
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
3837
+ if (@fseek($this->zip_fd, $v_header['offset']))
3838
+ {
3839
+ // ----- Close the zip file
3840
+ $this->privCloseFd();
3841
+
3842
+ $this->privSwapBackMagicQuotes();
3843
+
3844
+ // ----- Error log
3845
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3846
+
3847
+ // ----- Return
3848
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3849
+ return PclZip::errorCode();
3850
+ }
3851
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
3852
+
3853
+ // ----- Look for extraction as string
3854
+ if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
3855
+
3856
+ $v_string = '';
3857
+
3858
+ // ----- Extracting the file
3859
+ $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options);
3860
+ if ($v_result1 < 1) {
3861
+ $this->privCloseFd();
3862
+ $this->privSwapBackMagicQuotes();
3863
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
3864
+ return $v_result1;
3865
+ }
3866
+
3867
+ // ----- Get the only interesting attributes
3868
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
3869
+ {
3870
+ // ----- Close the zip file
3871
+ $this->privCloseFd();
3872
+ $this->privSwapBackMagicQuotes();
3873
+
3874
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3875
+ return $v_result;
3876
+ }
3877
+
3878
+ // ----- Set the file content
3879
+ $p_file_list[$v_nb_extracted]['content'] = $v_string;
3880
+
3881
+ // ----- Next extracted file
3882
+ $v_nb_extracted++;
3883
+
3884
+ // ----- Look for user callback abort
3885
+ if ($v_result1 == 2) {
3886
+ break;
3887
+ }
3888
+ }
3889
+ // ----- Look for extraction in standard output
3890
+ elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
3891
+ && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
3892
+ // ----- Extracting the file in standard output
3893
+ $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
3894
+ if ($v_result1 < 1) {
3895
+ $this->privCloseFd();
3896
+ $this->privSwapBackMagicQuotes();
3897
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
3898
+ return $v_result1;
3899
+ }
3900
+
3901
+ // ----- Get the only interesting attributes
3902
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
3903
+ $this->privCloseFd();
3904
+ $this->privSwapBackMagicQuotes();
3905
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3906
+ return $v_result;
3907
+ }
3908
+
3909
+ // ----- Look for user callback abort
3910
+ if ($v_result1 == 2) {
3911
+ break;
3912
+ }
3913
+ }
3914
+ // ----- Look for normal extraction
3915
+ else {
3916
+ // ----- Extracting the file
3917
+ $v_result1 = $this->privExtractFile($v_header,
3918
+ $p_path, $p_remove_path,
3919
+ $p_remove_all_path,
3920
+ $p_options);
3921
+ if ($v_result1 < 1) {
3922
+ $this->privCloseFd();
3923
+ $this->privSwapBackMagicQuotes();
3924
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
3925
+ return $v_result1;
3926
+ }
3927
+
3928
+ // ----- Get the only interesting attributes
3929
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
3930
+ {
3931
+ // ----- Close the zip file
3932
+ $this->privCloseFd();
3933
+ $this->privSwapBackMagicQuotes();
3934
+
3935
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3936
+ return $v_result;
3937
+ }
3938
+
3939
+ // ----- Look for user callback abort
3940
+ if ($v_result1 == 2) {
3941
+ break;
3942
+ }
3943
+ }
3944
+ }
3945
+ }
3946
+
3947
+ // ----- Close the zip file
3948
+ $this->privCloseFd();
3949
+ $this->privSwapBackMagicQuotes();
3950
+
3951
+ // ----- Return
3952
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3953
+ return $v_result;
3954
+ }
3955
+ // --------------------------------------------------------------------------------
3956
+
3957
+ // --------------------------------------------------------------------------------
3958
+ // Function : privExtractFile()
3959
+ // Description :
3960
+ // Parameters :
3961
+ // Return Values :
3962
+ //
3963
+ // 1 : ... ?
3964
+ // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
3965
+ // --------------------------------------------------------------------------------
3966
+ function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3967
+ {
3968
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFile', "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
3969
+ $v_result=1;
3970
+
3971
+ // ----- Read the file header
3972
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1)
3973
+ {
3974
+ // ----- Return
3975
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3976
+ return $v_result;
3977
+ }
3978
+
3979
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
3980
+
3981
+ // ----- Check that the file header is coherent with $p_entry info
3982
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
3983
+ // TBC
3984
+ }
3985
+
3986
+ // ----- Look for all path to remove
3987
+ if ($p_remove_all_path == true) {
3988
+ // ----- Look for folder entry that not need to be extracted
3989
+ if (($p_entry['external']&0x00000010)==0x00000010) {
3990
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "The entry is a folder : need to be filtered");
3991
+
3992
+ $p_entry['status'] = "filtered";
3993
+
3994
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3995
+ return $v_result;
3996
+ }
3997
+
3998
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "All path is removed");
3999
+ // ----- Get the basename of the path
4000
+ $p_entry['filename'] = basename($p_entry['filename']);
4001
+ }
4002
+
4003
+ // ----- Look for path to remove
4004
+ else if ($p_remove_path != "")
4005
+ {
4006
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Look for some path to remove");
4007
+ if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
4008
+ {
4009
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "The folder is the same as the removed path '".$p_entry['filename']."'");
4010
+
4011
+ // ----- Change the file status
4012
+ $p_entry['status'] = "filtered";
4013
+
4014
+ // ----- Return
4015
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4016
+ return $v_result;
4017
+ }
4018
+
4019
+ $p_remove_path_size = strlen($p_remove_path);
4020
+ if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
4021
+ {
4022
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '".$p_entry['filename']."'");
4023
+
4024
+ // ----- Remove the path
4025
+ $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
4026
+
4027
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Resulting file is '".$p_entry['filename']."'");
4028
+ }
4029
+ }
4030
+
4031
+ // ----- Add the path
4032
+ if ($p_path != '') {
4033
+ $p_entry['filename'] = $p_path."/".$p_entry['filename'];
4034
+ }
4035
+
4036
+ // ----- Check a base_dir_restriction
4037
+ if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
4038
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Check the extract directory restriction");
4039
+ $v_inclusion
4040
+ = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
4041
+ $p_entry['filename']);
4042
+ if ($v_inclusion == 0) {
4043
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_EXTRACT_DIR_RESTRICTION is selected, file is outside restriction");
4044
+
4045
+ PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
4046
+ "Filename '".$p_entry['filename']."' is "
4047
+ ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
4048
+
4049
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4050
+ return PclZip::errorCode();
4051
+ }
4052
+ }
4053
+
4054
+ // ----- Look for pre-extract callback
4055
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4056
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
4057
+
4058
+ // ----- Generate a local information
4059
+ $v_local_header = array();
4060
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4061
+
4062
+ // ----- Call the callback
4063
+ // Here I do not use call_user_func() because I need to send a reference to the
4064
+ // header.
4065
+ // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4066
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4067
+ if ($v_result == 0) {
4068
+ // ----- Change the file status
4069
+ $p_entry['status'] = "skipped";
4070
+ $v_result = 1;
4071
+ }
4072
+
4073
+ // ----- Look for abort result
4074
+ if ($v_result == 2) {
4075
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
4076
+ // ----- This status is internal and will be changed in 'skipped'
4077
+ $p_entry['status'] = "aborted";
4078
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4079
+ }
4080
+
4081
+ // ----- Update the informations
4082
+ // Only some fields can be modified
4083
+ $p_entry['filename'] = $v_local_header['filename'];
4084
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
4085
+ }
4086
+
4087
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
4088
+
4089
+ // ----- Look if extraction should be done
4090
+ if ($p_entry['status'] == 'ok') {
4091
+
4092
+ // ----- Look for specific actions while the file exist
4093
+ if (file_exists($p_entry['filename']))
4094
+ {
4095
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_entry['filename']."' already exists");
4096
+
4097
+ // ----- Look if file is a directory
4098
+ if (is_dir($p_entry['filename']))
4099
+ {
4100
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is a directory");
4101
+
4102
+ // ----- Change the file status
4103
+ $p_entry['status'] = "already_a_directory";
4104
+
4105
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
4106
+ // For historical reason first PclZip implementation does not stop
4107
+ // when this kind of error occurs.
4108
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
4109
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
4110
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
4111
+
4112
+ PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
4113
+ "Filename '".$p_entry['filename']."' is "
4114
+ ."already used by an existing directory");
4115
+
4116
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4117
+ return PclZip::errorCode();
4118
+ }
4119
+ }
4120
+ // ----- Look if file is write protected
4121
+ else if (!is_writeable($p_entry['filename']))
4122
+ {
4123
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is write protected");
4124
+
4125
+ // ----- Change the file status
4126
+ $p_entry['status'] = "write_protected";
4127
+
4128
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
4129
+ // For historical reason first PclZip implementation does not stop
4130
+ // when this kind of error occurs.
4131
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
4132
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
4133
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
4134
+
4135
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
4136
+ "Filename '".$p_entry['filename']."' exists "
4137
+ ."and is write protected");
4138
+
4139
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4140
+ return PclZip::errorCode();
4141
+ }
4142
+ }
4143
+
4144
+ // ----- Look if the extracted file is older
4145
+ else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
4146
+ {
4147
+ 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']).")");
4148
+ // ----- Change the file status
4149
+ if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
4150
+ && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
4151
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_REPLACE_NEWER is selected, file will be replaced");
4152
+ }
4153
+ else {
4154
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be replaced");
4155
+ $p_entry['status'] = "newer_exist";
4156
+
4157
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
4158
+ // For historical reason first PclZip implementation does not stop
4159
+ // when this kind of error occurs.
4160
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
4161
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
4162
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
4163
+
4164
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
4165
+ "Newer version of '".$p_entry['filename']."' exists "
4166
+ ."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
4167
+
4168
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4169
+ return PclZip::errorCode();
4170
+ }
4171
+ }
4172
+ }
4173
+ else {
4174
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is older than the extrated one - will be replaced by the extracted one (".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']).")");
4175
+ }
4176
+ }
4177
+
4178
+ // ----- Check the directory availability and create it if necessary
4179
+ else {
4180
+ if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
4181
+ $v_dir_to_check = $p_entry['filename'];
4182
+ else if (!strstr($p_entry['filename'], "/"))
4183
+ $v_dir_to_check = "";
4184
+ else
4185
+ $v_dir_to_check = dirname($p_entry['filename']);
4186
+
4187
+ if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
4188
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '".$p_entry['filename']."'");
4189
+
4190
+ // ----- Change the file status
4191
+ $p_entry['status'] = "path_creation_fail";
4192
+
4193
+ // ----- Return
4194
+ //PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4195
+ //return $v_result;
4196
+ $v_result = 1;
4197
+ }
4198
+ }
4199
+ }
4200
+
4201
+ // ----- Look if extraction should be done
4202
+ if ($p_entry['status'] == 'ok') {
4203
+
4204
+ // ----- Do the extraction (if not a folder)
4205
+ if (!(($p_entry['external']&0x00000010)==0x00000010))
4206
+ {
4207
+ // ----- Look for not compressed file
4208
+ if ($p_entry['compression'] == 0) {
4209
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
4210
+
4211
+ // ----- Opening destination file
4212
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
4213
+ {
4214
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
4215
+
4216
+ // ----- Change the file status
4217
+ $p_entry['status'] = "write_error";
4218
+
4219
+ // ----- Return
4220
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4221
+ return $v_result;
4222
+ }
4223
+
4224
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Read '".$p_entry['size']."' bytes");
4225
+
4226
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
4227
+ $v_size = $p_entry['compressed_size'];
4228
+ while ($v_size != 0)
4229
+ {
4230
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4231
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
4232
+ $v_buffer = @fread($this->zip_fd, $v_read_size);
4233
+ /* Try to speed up the code
4234
+ $v_binary_data = pack('a'.$v_read_size, $v_buffer);
4235
+ @fwrite($v_dest_file, $v_binary_data, $v_read_size);
4236
+ */
4237
+ @fwrite($v_dest_file, $v_buffer, $v_read_size);
4238
+ $v_size -= $v_read_size;
4239
+ }
4240
+
4241
+ // ----- Closing the destination file
4242
+ fclose($v_dest_file);
4243
+
4244
+ // ----- Change the file mtime
4245
+ touch($p_entry['filename'], $p_entry['mtime']);
4246
+
4247
+
4248
+ }
4249
+ else {
4250
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (Compression method ".$p_entry['compression'].")");
4251
+ // ----- TBC
4252
+ // Need to be finished
4253
+ if (($p_entry['flag'] & 1) == 1) {
4254
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File is encrypted");
4255
+ PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
4256
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4257
+ return PclZip::errorCode();
4258
+ }
4259
+
4260
+
4261
+ // ----- Look for using temporary file to unzip
4262
+ if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
4263
+ && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
4264
+ || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
4265
+ && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) {
4266
+ $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options);
4267
+ if ($v_result < PCLZIP_ERR_NO_ERROR) {
4268
+ return $v_result;
4269
+ }
4270
+ }
4271
+
4272
+ // ----- Look for extract in memory
4273
+ else {
4274
+
4275
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".$p_entry['compressed_size']."' compressed bytes");
4276
+
4277
+ // ----- Read the compressed file in a buffer (one shot)
4278
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4279
+
4280
+ // ----- Decompress the file
4281
+ $v_file_content = @gzinflate($v_buffer);
4282
+ unset($v_buffer);
4283
+ if ($v_file_content === FALSE) {
4284
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to inflate compressed file");
4285
+
4286
+ // ----- Change the file status
4287
+ // TBC
4288
+ $p_entry['status'] = "error";
4289
+
4290
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4291
+ return $v_result;
4292
+ }
4293
+
4294
+ // ----- Opening destination file
4295
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
4296
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
4297
+
4298
+ // ----- Change the file status
4299
+ $p_entry['status'] = "write_error";
4300
+
4301
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4302
+ return $v_result;
4303
+ }
4304
+
4305
+ // ----- Write the uncompressed data
4306
+ @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
4307
+ unset($v_file_content);
4308
+
4309
+ // ----- Closing the destination file
4310
+ @fclose($v_dest_file);
4311
+
4312
+ }
4313
+
4314
+ // ----- Change the file mtime
4315
+ @touch($p_entry['filename'], $p_entry['mtime']);
4316
+ }
4317
+
4318
+ // ----- Look for chmod option
4319
+ if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
4320
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "chmod option activated '".$p_options[PCLZIP_OPT_SET_CHMOD]."'");
4321
+
4322
+ // ----- Change the mode of the file
4323
+ @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
4324
+ }
4325
+
4326
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
4327
+ }
4328
+ }
4329
+
4330
+ // ----- Change abort status
4331
+ if ($p_entry['status'] == "aborted") {
4332
+ $p_entry['status'] = "skipped";
4333
+ }
4334
+
4335
+ // ----- Look for post-extract callback
4336
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4337
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
4338
+
4339
+ // ----- Generate a local information
4340
+ $v_local_header = array();
4341
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4342
+
4343
+ // ----- Call the callback
4344
+ // Here I do not use call_user_func() because I need to send a reference to the
4345
+ // header.
4346
+ // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
4347
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4348
+
4349
+ // ----- Look for abort result
4350
+ if ($v_result == 2) {
4351
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
4352
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4353
+ }
4354
+ }
4355
+
4356
+ // ----- Return
4357
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4358
+ return $v_result;
4359
+ }
4360
+ // --------------------------------------------------------------------------------
4361
+
4362
+ // --------------------------------------------------------------------------------
4363
+ // Function : privExtractFileUsingTempFile()
4364
+ // Description :
4365
+ // Parameters :
4366
+ // Return Values :
4367
+ // --------------------------------------------------------------------------------
4368
+ function privExtractFileUsingTempFile(&$p_entry, &$p_options)
4369
+ {
4370
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileUsingTempFile', "filename='".$p_entry['filename']."'");
4371
+ $v_result=1;
4372
+
4373
+ // ----- Creates a temporary file
4374
+ $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
4375
+ if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
4376
+ fclose($v_file);
4377
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
4378
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4379
+ return PclZip::errorCode();
4380
+ }
4381
+
4382
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Start extraction of '".$p_entry['filename']."'");
4383
+
4384
+ // ----- Write gz file format header
4385
+ $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
4386
+ @fwrite($v_dest_file, $v_binary_data, 10);
4387
+
4388
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
4389
+ $v_size = $p_entry['compressed_size'];
4390
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Compressed Size :".$v_size."");
4391
+ while ($v_size != 0)
4392
+ {
4393
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4394
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Read ".$v_read_size." bytes");
4395
+ $v_buffer = @fread($this->zip_fd, $v_read_size);
4396
+ //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
4397
+ @fwrite($v_dest_file, $v_buffer, $v_read_size);
4398
+ $v_size -= $v_read_size;
4399
+ }
4400
+
4401
+ // ----- Write gz file format footer
4402
+ $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']);
4403
+ @fwrite($v_dest_file, $v_binary_data, 8);
4404
+
4405
+ // ----- Close the temporary file
4406
+ @fclose($v_dest_file);
4407
+
4408
+ // ----- Opening destination file
4409
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
4410
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
4411
+ $p_entry['status'] = "write_error";
4412
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4413
+ return $v_result;
4414
+ }
4415
+
4416
+ // ----- Open the temporary gz file
4417
+ if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) {
4418
+ @fclose($v_dest_file);
4419
+ $p_entry['status'] = "read_error";
4420
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
4421
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4422
+ return PclZip::errorCode();
4423
+ }
4424
+
4425
+ PclTraceFctMessage(__FILE__, __LINE__, 2, 'File size is '.filesize($v_gzip_temp_name));
4426
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
4427
+
4428
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
4429
+ $v_size = $p_entry['size'];
4430
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Size :".$v_size."");
4431
+ while ($v_size != 0) {
4432
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4433
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Read ".$v_read_size." bytes");
4434
+ $v_buffer = @gzread($v_src_file, $v_read_size);
4435
+ //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
4436
+ @fwrite($v_dest_file, $v_buffer, $v_read_size);
4437
+ $v_size -= $v_read_size;
4438
+ }
4439
+ @fclose($v_dest_file);
4440
+ @gzclose($v_src_file);
4441
+
4442
+ // ----- Delete the temporary file
4443
+ @unlink($v_gzip_temp_name);
4444
+
4445
+ // ----- Return
4446
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4447
+ return $v_result;
4448
+ }
4449
+ // --------------------------------------------------------------------------------
4450
+
4451
+ // --------------------------------------------------------------------------------
4452
+ // Function : privExtractFileInOutput()
4453
+ // Description :
4454
+ // Parameters :
4455
+ // Return Values :
4456
+ // --------------------------------------------------------------------------------
4457
+ function privExtractFileInOutput(&$p_entry, &$p_options)
4458
+ {
4459
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileInOutput', "");
4460
+ $v_result=1;
4461
+
4462
+ // ----- Read the file header
4463
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
4464
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4465
+ return $v_result;
4466
+ }
4467
+
4468
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
4469
+
4470
+ // ----- Check that the file header is coherent with $p_entry info
4471
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4472
+ // TBC
4473
+ }
4474
+
4475
+ // ----- Look for pre-extract callback
4476
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4477
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
4478
+
4479
+ // ----- Generate a local information
4480
+ $v_local_header = array();
4481
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4482
+
4483
+ // ----- Call the callback
4484
+ // Here I do not use call_user_func() because I need to send a reference to the
4485
+ // header.
4486
+ // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4487
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4488
+ if ($v_result == 0) {
4489
+ // ----- Change the file status
4490
+ $p_entry['status'] = "skipped";
4491
+ $v_result = 1;
4492
+ }
4493
+
4494
+ // ----- Look for abort result
4495
+ if ($v_result == 2) {
4496
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
4497
+ // ----- This status is internal and will be changed in 'skipped'
4498
+ $p_entry['status'] = "aborted";
4499
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4500
+ }
4501
+
4502
+ // ----- Update the informations
4503
+ // Only some fields can be modified
4504
+ $p_entry['filename'] = $v_local_header['filename'];
4505
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
4506
+ }
4507
+
4508
+ // ----- Trace
4509
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
4510
+
4511
+ // ----- Look if extraction should be done
4512
+ if ($p_entry['status'] == 'ok') {
4513
+
4514
+ // ----- Do the extraction (if not a folder)
4515
+ if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4516
+ // ----- Look for not compressed file
4517
+ if ($p_entry['compressed_size'] == $p_entry['size']) {
4518
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
4519
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
4520
+
4521
+ // ----- Read the file in a buffer (one shot)
4522
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4523
+
4524
+ // ----- Send the file to the output
4525
+ echo $v_buffer;
4526
+ unset($v_buffer);
4527
+ }
4528
+ else {
4529
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
4530
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Reading '".$p_entry['size']."' bytes");
4531
+
4532
+ // ----- Read the compressed file in a buffer (one shot)
4533
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4534
+
4535
+ // ----- Decompress the file
4536
+ $v_file_content = gzinflate($v_buffer);
4537
+ unset($v_buffer);
4538
+
4539
+ // ----- Send the file to the output
4540
+ echo $v_file_content;
4541
+ unset($v_file_content);
4542
+ }
4543
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
4544
+ }
4545
+ }
4546
+
4547
+ // ----- Change abort status
4548
+ if ($p_entry['status'] == "aborted") {
4549
+ $p_entry['status'] = "skipped";
4550
+ }
4551
+
4552
+ // ----- Look for post-extract callback
4553
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4554
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
4555
+
4556
+ // ----- Generate a local information
4557
+ $v_local_header = array();
4558
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4559
+
4560
+ // ----- Call the callback
4561
+ // Here I do not use call_user_func() because I need to send a reference to the
4562
+ // header.
4563
+ // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
4564
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4565
+
4566
+ // ----- Look for abort result
4567
+ if ($v_result == 2) {
4568
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
4569
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4570
+ }
4571
+ }
4572
+
4573
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4574
+ return $v_result;
4575
+ }
4576
+ // --------------------------------------------------------------------------------
4577
+
4578
+ // --------------------------------------------------------------------------------
4579
+ // Function : privExtractFileAsString()
4580
+ // Description :
4581
+ // Parameters :
4582
+ // Return Values :
4583
+ // --------------------------------------------------------------------------------
4584
+ function privExtractFileAsString(&$p_entry, &$p_string, &$p_options)
4585
+ {
4586
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileAsString', "p_entry['filename']='".$p_entry['filename']."'");
4587
+ $v_result=1;
4588
+
4589
+ // ----- Read the file header
4590
+ $v_header = array();
4591
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1)
4592
+ {
4593
+ // ----- Return
4594
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4595
+ return $v_result;
4596
+ }
4597
+
4598
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
4599
+
4600
+ // ----- Check that the file header is coherent with $p_entry info
4601
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4602
+ // TBC
4603
+ }
4604
+
4605
+ // ----- Look for pre-extract callback
4606
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4607
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
4608
+
4609
+ // ----- Generate a local information
4610
+ $v_local_header = array();
4611
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4612
+
4613
+ // ----- Call the callback
4614
+ // Here I do not use call_user_func() because I need to send a reference to the
4615
+ // header.
4616
+ // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4617
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4618
+ if ($v_result == 0) {
4619
+ // ----- Change the file status
4620
+ $p_entry['status'] = "skipped";
4621
+ $v_result = 1;
4622
+ }
4623
+
4624
+ // ----- Look for abort result
4625
+ if ($v_result == 2) {
4626
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
4627
+ // ----- This status is internal and will be changed in 'skipped'
4628
+ $p_entry['status'] = "aborted";
4629
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4630
+ }
4631
+
4632
+ // ----- Update the informations
4633
+ // Only some fields can be modified
4634
+ $p_entry['filename'] = $v_local_header['filename'];
4635
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
4636
+ }
4637
+
4638
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file in string (with path) '".$p_entry['filename']."', size '$v_header[size]'");
4639
+
4640
+ // ----- Look if extraction should be done
4641
+ if ($p_entry['status'] == 'ok') {
4642
+
4643
+ // ----- Do the extraction (if not a folder)
4644
+ if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4645
+ // ----- Look for not compressed file
4646
+ // if ($p_entry['compressed_size'] == $p_entry['size'])
4647
+ if ($p_entry['compression'] == 0) {
4648
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
4649
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
4650
+
4651
+ // ----- Reading the file
4652
+ $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
4653
+ }
4654
+ else {
4655
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (compression method '".$p_entry['compression']."')");
4656
+
4657
+ // ----- Reading the file
4658
+ $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
4659
+
4660
+ // ----- Decompress the file
4661
+ if (($p_string = @gzinflate($v_data)) === FALSE) {
4662
+ // TBC
4663
+ }
4664
+ }
4665
+
4666
+ // ----- Trace
4667
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
4668
+ }
4669
+ else {
4670
+ // TBC : error : can not extract a folder in a string
4671
+ }
4672
+
4673
+ }
4674
+
4675
+ // ----- Change abort status
4676
+ if ($p_entry['status'] == "aborted") {
4677
+ $p_entry['status'] = "skipped";
4678
+ }
4679
+
4680
+ // ----- Look for post-extract callback
4681
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4682
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
4683
+
4684
+ // ----- Generate a local information
4685
+ $v_local_header = array();
4686
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4687
+
4688
+ // ----- Swap the content to header
4689
+ $v_local_header['content'] = $p_string;
4690
+ $p_string = '';
4691
+
4692
+ // ----- Call the callback
4693
+ // Here I do not use call_user_func() because I need to send a reference to the
4694
+ // header.
4695
+ // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
4696
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4697
+
4698
+ // ----- Swap back the content to header
4699
+ $p_string = $v_local_header['content'];
4700
+ unset($v_local_header['content']);
4701
+
4702
+ // ----- Look for abort result
4703
+ if ($v_result == 2) {
4704
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
4705
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4706
+ }
4707
+ }
4708
+
4709
+ // ----- Return
4710
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4711
+ return $v_result;
4712
+ }
4713
+ // --------------------------------------------------------------------------------
4714
+
4715
+ // --------------------------------------------------------------------------------
4716
+ // Function : privReadFileHeader()
4717
+ // Description :
4718
+ // Parameters :
4719
+ // Return Values :
4720
+ // --------------------------------------------------------------------------------
4721
+ function privReadFileHeader(&$p_header)
4722
+ {
4723
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadFileHeader", "");
4724
+ $v_result=1;
4725
+
4726
+ // ----- Read the 4 bytes signature
4727
+ $v_binary_data = @fread($this->zip_fd, 4);
4728
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
4729
+ $v_data = unpack('Vid', $v_binary_data);
4730
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
4731
+
4732
+ // ----- Check signature
4733
+ if ($v_data['id'] != 0x04034b50)
4734
+ {
4735
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid File header");
4736
+
4737
+ // ----- Error log
4738
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4739
+
4740
+ // ----- Return
4741
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4742
+ return PclZip::errorCode();
4743
+ }
4744
+
4745
+ // ----- Read the first 42 bytes of the header
4746
+ $v_binary_data = fread($this->zip_fd, 26);
4747
+
4748
+ // ----- Look for invalid block size
4749
+ if (strlen($v_binary_data) != 26)
4750
+ {
4751
+ $p_header['filename'] = "";
4752
+ $p_header['status'] = "invalid_header";
4753
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
4754
+
4755
+ // ----- Error log
4756
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4757
+
4758
+ // ----- Return
4759
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4760
+ return PclZip::errorCode();
4761
+ }
4762
+
4763
+ // ----- Extract the values
4764
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'");
4765
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'");
4766
+ $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
4767
+
4768
+ // ----- Get filename
4769
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$v_data['filename_len']);
4770
+ $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
4771
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\'');
4772
+
4773
+ // ----- Get extra_fields
4774
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra field length : ".$v_data['extra_len']);
4775
+ if ($v_data['extra_len'] != 0) {
4776
+ $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
4777
+ }
4778
+ else {
4779
+ $p_header['extra'] = '';
4780
+ }
4781
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra field : \''.bin2hex($p_header['extra']).'\'');
4782
+
4783
+ // ----- Extract properties
4784
+ $p_header['version_extracted'] = $v_data['version'];
4785
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : ('.$p_header['version_extracted'].') \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
4786
+ $p_header['compression'] = $v_data['compression'];
4787
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compression method : \''.$p_header['compression'].'\'');
4788
+ $p_header['size'] = $v_data['size'];
4789
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\'');
4790
+ $p_header['compressed_size'] = $v_data['compressed_size'];
4791
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
4792
+ $p_header['crc'] = $v_data['crc'];
4793
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
4794
+ $p_header['flag'] = $v_data['flag'];
4795
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\'');
4796
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag bit 11 (from right) : \''.($p_header['flag']&0x0400).'\'');
4797
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag bit 11 (from left) : \''.($p_header['flag']&0x0020).'\'');
4798
+ $p_header['filename_len'] = $v_data['filename_len'];
4799
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename_len : \''.$p_header['filename_len'].'\'');
4800
+
4801
+ // ----- Recuperate date in UNIX format
4802
+ $p_header['mdate'] = $v_data['mdate'];
4803
+ $p_header['mtime'] = $v_data['mtime'];
4804
+ if ($p_header['mdate'] && $p_header['mtime'])
4805
+ {
4806
+ // ----- Extract time
4807
+ $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4808
+ $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4809
+ $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4810
+
4811
+ // ----- Extract date
4812
+ $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4813
+ $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4814
+ $v_day = $p_header['mdate'] & 0x001F;
4815
+
4816
+ // ----- Get UNIX date format
4817
+ $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4818
+
4819
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
4820
+ }
4821
+ else
4822
+ {
4823
+ $p_header['mtime'] = time();
4824
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
4825
+ }
4826
+
4827
+ // TBC
4828
+ //for(reset($v_data); $key = key($v_data); next($v_data)) {
4829
+ // PclTraceFctMessage(__FILE__, __LINE__, 3, "Attribut[$key] = ".$v_data[$key]);
4830
+ //}
4831
+
4832
+ // ----- Set the stored filename
4833
+ $p_header['stored_filename'] = $p_header['filename'];
4834
+
4835
+ // ----- Set the status field
4836
+ $p_header['status'] = "ok";
4837
+
4838
+ // ----- Return
4839
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4840
+ return $v_result;
4841
+ }
4842
+ // --------------------------------------------------------------------------------
4843
+
4844
+ // --------------------------------------------------------------------------------
4845
+ // Function : privReadCentralFileHeader()
4846
+ // Description :
4847
+ // Parameters :
4848
+ // Return Values :
4849
+ // --------------------------------------------------------------------------------
4850
+ function privReadCentralFileHeader(&$p_header)
4851
+ {
4852
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadCentralFileHeader", "");
4853
+ $v_result=1;
4854
+
4855
+ // ----- Read the 4 bytes signature
4856
+ $v_binary_data = @fread($this->zip_fd, 4);
4857
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
4858
+ $v_data = unpack('Vid', $v_binary_data);
4859
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
4860
+
4861
+ // ----- Check signature
4862
+ if ($v_data['id'] != 0x02014b50)
4863
+ {
4864
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid Central Dir File signature");
4865
+
4866
+ // ----- Error log
4867
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4868
+
4869
+ // ----- Return
4870
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4871
+ return PclZip::errorCode();
4872
+ }
4873
+
4874
+ // ----- Read the first 42 bytes of the header
4875
+ $v_binary_data = fread($this->zip_fd, 42);
4876
+
4877
+ // ----- Look for invalid block size
4878
+ if (strlen($v_binary_data) != 42)
4879
+ {
4880
+ $p_header['filename'] = "";
4881
+ $p_header['status'] = "invalid_header";
4882
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
4883
+
4884
+ // ----- Error log
4885
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4886
+
4887
+ // ----- Return
4888
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4889
+ return PclZip::errorCode();
4890
+ }
4891
+
4892
+ // ----- Extract the values
4893
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Header : '".$v_binary_data."'");
4894
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Header (Hex) : '".bin2hex($v_binary_data)."'");
4895
+ $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);
4896
+
4897
+ // ----- Get filename
4898
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "File name length : ".$p_header['filename_len']);
4899
+ if ($p_header['filename_len'] != 0)
4900
+ $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
4901
+ else
4902
+ $p_header['filename'] = '';
4903
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Filename : \''.$p_header['filename'].'\'');
4904
+
4905
+ // ----- Get extra
4906
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Extra length : ".$p_header['extra_len']);
4907
+ if ($p_header['extra_len'] != 0)
4908
+ $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
4909
+ else
4910
+ $p_header['extra'] = '';
4911
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Extra : \''.$p_header['extra'].'\'');
4912
+
4913
+ // ----- Get comment
4914
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Comment length : ".$p_header['comment_len']);
4915
+ if ($p_header['comment_len'] != 0)
4916
+ $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
4917
+ else
4918
+ $p_header['comment'] = '';
4919
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Comment : \''.$p_header['comment'].'\'');
4920
+
4921
+ // ----- Extract properties
4922
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version : \''.($p_header['version']/10).'.'.($p_header['version']%10).'\'');
4923
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
4924
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Size : \''.$p_header['size'].'\'');
4925
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
4926
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
4927
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Flag : \''.$p_header['flag'].'\'');
4928
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Offset : \''.$p_header['offset'].'\'');
4929
+
4930
+ // ----- Recuperate date in UNIX format
4931
+ //if ($p_header['mdate'] && $p_header['mtime'])
4932
+ // TBC : bug : this was ignoring time with 0/0/0
4933
+ if (1)
4934
+ {
4935
+ // ----- Extract time
4936
+ $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4937
+ $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4938
+ $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4939
+
4940
+ // ----- Extract date
4941
+ $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4942
+ $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4943
+ $v_day = $p_header['mdate'] & 0x001F;
4944
+
4945
+ // ----- Get UNIX date format
4946
+ $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4947
+
4948
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
4949
+ }
4950
+ else
4951
+ {
4952
+ $p_header['mtime'] = time();
4953
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
4954
+ }
4955
+
4956
+ // ----- Set the stored filename
4957
+ $p_header['stored_filename'] = $p_header['filename'];
4958
+
4959
+ // ----- Set default status to ok
4960
+ $p_header['status'] = 'ok';
4961
+
4962
+ // ----- Look if it is a directory
4963
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Internal (Hex) : '".sprintf("Ox%04X", $p_header['internal'])."'");
4964
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "External (Hex) : '".sprintf("Ox%04X", $p_header['external'])."' (".(($p_header['external']&0x00000010)==0x00000010?'is a folder':'is a file').')');
4965
+ if (substr($p_header['filename'], -1) == '/') {
4966
+ //$p_header['external'] = 0x41FF0010;
4967
+ $p_header['external'] = 0x00000010;
4968
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Force folder external : \''.sprintf("Ox%04X", $p_header['external']).'\'');
4969
+ }
4970
+
4971
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Header of filename : \''.$p_header['filename'].'\'');
4972
+
4973
+ // ----- Return
4974
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4975
+ return $v_result;
4976
+ }
4977
+ // --------------------------------------------------------------------------------
4978
+
4979
+ // --------------------------------------------------------------------------------
4980
+ // Function : privCheckFileHeaders()
4981
+ // Description :
4982
+ // Parameters :
4983
+ // Return Values :
4984
+ // 1 on success,
4985
+ // 0 on error;
4986
+ // --------------------------------------------------------------------------------
4987
+ function privCheckFileHeaders(&$p_local_header, &$p_central_header)
4988
+ {
4989
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFileHeaders", "");
4990
+ $v_result=1;
4991
+
4992
+ // ----- Check the static values
4993
+ // TBC
4994
+ if ($p_local_header['filename'] != $p_central_header['filename']) {
4995
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename" : TBC To Be Completed');
4996
+ }
4997
+ if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
4998
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "version_extracted" : TBC To Be Completed');
4999
+ }
5000
+ if ($p_local_header['flag'] != $p_central_header['flag']) {
5001
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "flag" : TBC To Be Completed');
5002
+ }
5003
+ if ($p_local_header['compression'] != $p_central_header['compression']) {
5004
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "compression" : TBC To Be Completed');
5005
+ }
5006
+ if ($p_local_header['mtime'] != $p_central_header['mtime']) {
5007
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "mtime" : TBC To Be Completed');
5008
+ }
5009
+ if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
5010
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename_len" : TBC To Be Completed');
5011
+ }
5012
+
5013
+ // ----- Look for flag bit 3
5014
+ if (($p_local_header['flag'] & 8) == 8) {
5015
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Purpose bit flag bit 3 set !');
5016
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'File size, compression size and crc found in central header');
5017
+ $p_local_header['size'] = $p_central_header['size'];
5018
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_local_header['size'].'\'');
5019
+ $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
5020
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_local_header['compressed_size'].'\'');
5021
+ $p_local_header['crc'] = $p_central_header['crc'];
5022
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_local_header['crc']).'\'');
5023
+ }
5024
+
5025
+ // ----- Return
5026
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5027
+ return $v_result;
5028
+ }
5029
+ // --------------------------------------------------------------------------------
5030
+
5031
+ // --------------------------------------------------------------------------------
5032
+ // Function : privReadEndCentralDir()
5033
+ // Description :
5034
+ // Parameters :
5035
+ // Return Values :
5036
+ // --------------------------------------------------------------------------------
5037
+ function privReadEndCentralDir(&$p_central_dir)
5038
+ {
5039
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadEndCentralDir", "");
5040
+ $v_result=1;
5041
+
5042
+ // ----- Go to the end of the zip file
5043
+ $v_size = filesize($this->zipname);
5044
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Size of the file :$v_size");
5045
+ @fseek($this->zip_fd, $v_size);
5046
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position at end of zip file : \''.ftell($this->zip_fd).'\'');
5047
+ if (@ftell($this->zip_fd) != $v_size)
5048
+ {
5049
+ // ----- Error log
5050
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
5051
+
5052
+ // ----- Return
5053
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5054
+ return PclZip::errorCode();
5055
+ }
5056
+
5057
+ // ----- First try : look if this is an archive with no commentaries (most of the time)
5058
+ // in this case the end of central dir is at 22 bytes of the file end
5059
+ $v_found = 0;
5060
+ if ($v_size > 26) {
5061
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Look for central dir with no comment');
5062
+ @fseek($this->zip_fd, $v_size-22);
5063
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after min central position : \''.ftell($this->zip_fd).'\'');
5064
+ if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
5065
+ {
5066
+ // ----- Error log
5067
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
5068
+
5069
+ // ----- Return
5070
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5071
+ return PclZip::errorCode();
5072
+ }
5073
+
5074
+ // ----- Read for bytes
5075
+ $v_binary_data = @fread($this->zip_fd, 4);
5076
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
5077
+ $v_data = @unpack('Vid', $v_binary_data);
5078
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
5079
+
5080
+ // ----- Check signature
5081
+ if ($v_data['id'] == 0x06054b50) {
5082
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Found central dir at the default position.");
5083
+ $v_found = 1;
5084
+ }
5085
+
5086
+ $v_pos = ftell($this->zip_fd);
5087
+ }
5088
+
5089
+ // ----- Go back to the maximum possible size of the Central Dir End Record
5090
+ if (!$v_found) {
5091
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Start extended search of end central dir');
5092
+ $v_maximum_size = 65557; // 0xFFFF + 22;
5093
+ if ($v_maximum_size > $v_size)
5094
+ $v_maximum_size = $v_size;
5095
+ @fseek($this->zip_fd, $v_size-$v_maximum_size);
5096
+ if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
5097
+ {
5098
+ // ----- Error log
5099
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
5100
+
5101
+ // ----- Return
5102
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5103
+ return PclZip::errorCode();
5104
+ }
5105
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');
5106
+
5107
+ // ----- Read byte per byte in order to find the signature
5108
+ $v_pos = ftell($this->zip_fd);
5109
+ $v_bytes = 0x00000000;
5110
+ while ($v_pos < $v_size)
5111
+ {
5112
+ // ----- Read a byte
5113
+ $v_byte = @fread($this->zip_fd, 1);
5114
+
5115
+ // ----- Add the byte
5116
+ //$v_bytes = ($v_bytes << 8) | Ord($v_byte);
5117
+ // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
5118
+ // Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
5119
+ $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
5120
+
5121
+ // ----- Compare the bytes
5122
+ if ($v_bytes == 0x504b0506)
5123
+ {
5124
+ PclTraceFctMessage(__FILE__, __LINE__, 4, 'Found End Central Dir signature at position : \''.ftell($this->zip_fd).'\'');
5125
+ $v_pos++;
5126
+ break;
5127
+ }
5128
+
5129
+ $v_pos++;
5130
+ }
5131
+
5132
+ // ----- Look if not found end of central dir
5133
+ if ($v_pos == $v_size)
5134
+ {
5135
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to find End of Central Dir Record signature");
5136
+
5137
+ // ----- Error log
5138
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
5139
+
5140
+ // ----- Return
5141
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5142
+ return PclZip::errorCode();
5143
+ }
5144
+ }
5145
+
5146
+ // ----- Read the first 18 bytes of the header
5147
+ $v_binary_data = fread($this->zip_fd, 18);
5148
+
5149
+ // ----- Look for invalid block size
5150
+ if (strlen($v_binary_data) != 18)
5151
+ {
5152
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
5153
+
5154
+ // ----- Error log
5155
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
5156
+
5157
+ // ----- Return
5158
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5159
+ return PclZip::errorCode();
5160
+ }
5161
+
5162
+ // ----- Extract the values
5163
+ //PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record : '".$v_binary_data."'");
5164
+ //PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record (Hex) : '".bin2hex($v_binary_data)."'");
5165
+ $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
5166
+
5167
+ // ----- Check the global size
5168
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$v_data['comment_size']);
5169
+ if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
5170
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "The central dir is not at the end of the archive. Some trailing bytes exists after the archive.");
5171
+
5172
+ // ----- Removed in release 2.2 see readme file
5173
+ // The check of the file size is a little too strict.
5174
+ // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
5175
+ // While decrypted, zip has training 0 bytes
5176
+ if (0) {
5177
+ // ----- Error log
5178
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
5179
+ 'The central dir is not at the end of the archive.'
5180
+ .' Some trailing bytes exists after the archive.');
5181
+
5182
+ // ----- Return
5183
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5184
+ return PclZip::errorCode();
5185
+ }
5186
+ }
5187
+
5188
+ // ----- Get comment
5189
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment size : \''.$v_data['comment_size'].'\'');
5190
+ if ($v_data['comment_size'] != 0) {
5191
+ $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
5192
+ }
5193
+ else
5194
+ $p_central_dir['comment'] = '';
5195
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_central_dir['comment'].'\'');
5196
+
5197
+ $p_central_dir['entries'] = $v_data['entries'];
5198
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries : \''.$p_central_dir['entries'].'\'');
5199
+ $p_central_dir['disk_entries'] = $v_data['disk_entries'];
5200
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries for this disk : \''.$p_central_dir['disk_entries'].'\'');
5201
+ $p_central_dir['offset'] = $v_data['offset'];
5202
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset of Central Dir : \''.$p_central_dir['offset'].'\'');
5203
+ $p_central_dir['size'] = $v_data['size'];
5204
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size of Central Dir : \''.$p_central_dir['size'].'\'');
5205
+ $p_central_dir['disk'] = $v_data['disk'];
5206
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Disk number : \''.$p_central_dir['disk'].'\'');
5207
+ $p_central_dir['disk_start'] = $v_data['disk_start'];
5208
+ PclTraceFctMessage(__FILE__, __LINE__, 3, 'Start disk number : \''.$p_central_dir['disk_start'].'\'');
5209
+
5210
+ // TBC
5211
+ //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
5212
+ // PclTraceFctMessage(__FILE__, __LINE__, 3, "central_dir[$key] = ".$p_central_dir[$key]);
5213
+ //}
5214
+
5215
+ // ----- Return
5216
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5217
+ return $v_result;
5218
+ }
5219
+ // --------------------------------------------------------------------------------
5220
+
5221
+ // --------------------------------------------------------------------------------
5222
+ // Function : privDeleteByRule()
5223
+ // Description :
5224
+ // Parameters :
5225
+ // Return Values :
5226
+ // --------------------------------------------------------------------------------
5227
+ function privDeleteByRule(&$p_result_list, &$p_options)
5228
+ {
5229
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDeleteByRule", "");
5230
+ $v_result=1;
5231
+ $v_list_detail = array();
5232
+
5233
+ // ----- Open the zip file
5234
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5235
+ if (($v_result=$this->privOpenFd('rb')) != 1)
5236
+ {
5237
+ // ----- Return
5238
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5239
+ return $v_result;
5240
+ }
5241
+
5242
+ // ----- Read the central directory informations
5243
+ $v_central_dir = array();
5244
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
5245
+ {
5246
+ $this->privCloseFd();
5247
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5248
+ return $v_result;
5249
+ }
5250
+
5251
+ // ----- Go to beginning of File
5252
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
5253
+ @rewind($this->zip_fd);
5254
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
5255
+
5256
+ // ----- Scan all the files
5257
+ // ----- Start at beginning of Central Dir
5258
+ $v_pos_entry = $v_central_dir['offset'];
5259
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
5260
+ @rewind($this->zip_fd);
5261
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
5262
+ if (@fseek($this->zip_fd, $v_pos_entry))
5263
+ {
5264
+ // ----- Close the zip file
5265
+ $this->privCloseFd();
5266
+
5267
+ // ----- Error log
5268
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
5269
+
5270
+ // ----- Return
5271
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5272
+ return PclZip::errorCode();
5273
+ }
5274
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
5275
+
5276
+ // ----- Read each entry
5277
+ $v_header_list = array();
5278
+ $j_start = 0;
5279
+ for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
5280
+ {
5281
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry (index '$i')");
5282
+
5283
+ // ----- Read the file header
5284
+ $v_header_list[$v_nb_extracted] = array();
5285
+ if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
5286
+ {
5287
+ // ----- Close the zip file
5288
+ $this->privCloseFd();
5289
+
5290
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5291
+ return $v_result;
5292
+ }
5293
+
5294
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename (index '$i') : '".$v_header_list[$v_nb_extracted]['stored_filename']."'");
5295
+
5296
+ // ----- Store the index
5297
+ $v_header_list[$v_nb_extracted]['index'] = $i;
5298
+
5299
+ // ----- Look for the specific extract rules
5300
+ $v_found = false;
5301
+
5302
+ // ----- Look for extract by name rule
5303
+ if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
5304
+ && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
5305
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
5306
+
5307
+ // ----- Look if the filename is in the list
5308
+ for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
5309
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
5310
+
5311
+ // ----- Look for a directory
5312
+ if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
5313
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
5314
+
5315
+ // ----- Look if the directory is in the filename path
5316
+ if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
5317
+ && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
5318
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
5319
+ $v_found = true;
5320
+ }
5321
+ elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
5322
+ && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
5323
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The entry is the searched directory");
5324
+ $v_found = true;
5325
+ }
5326
+ }
5327
+ // ----- Look for a filename
5328
+ elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
5329
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
5330
+ $v_found = true;
5331
+ }
5332
+ }
5333
+ }
5334
+
5335
+ // ----- Look for extract by ereg rule
5336
+ // ereg() is deprecated with PHP 5.3
5337
+ /*
5338
+ else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
5339
+ && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
5340
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
5341
+
5342
+ if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
5343
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
5344
+ $v_found = true;
5345
+ }
5346
+ }
5347
+ */
5348
+
5349
+ // ----- Look for extract by preg rule
5350
+ else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
5351
+ && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
5352
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
5353
+
5354
+ if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
5355
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
5356
+ $v_found = true;
5357
+ }
5358
+ }
5359
+
5360
+ // ----- Look for extract by index rule
5361
+ else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
5362
+ && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
5363
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
5364
+
5365
+ // ----- Look if the index is in the list
5366
+ for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
5367
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
5368
+
5369
+ if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
5370
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
5371
+ $v_found = true;
5372
+ }
5373
+ if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
5374
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
5375
+ $j_start = $j+1;
5376
+ }
5377
+
5378
+ if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
5379
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
5380
+ break;
5381
+ }
5382
+ }
5383
+ }
5384
+ else {
5385
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "No argument mean remove all file");
5386
+ $v_found = true;
5387
+ }
5388
+
5389
+ // ----- Look for deletion
5390
+ if ($v_found)
5391
+ {
5392
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' need to be deleted");
5393
+ unset($v_header_list[$v_nb_extracted]);
5394
+ }
5395
+ else
5396
+ {
5397
+ PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' will not be deleted");
5398
+ $v_nb_extracted++;
5399
+ }
5400
+ }
5401
+
5402
+ // ----- Look if something need to be deleted
5403
+ if ($v_nb_extracted > 0) {
5404
+
5405
+ // ----- Creates a temporay file
5406
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
5407
+
5408
+ // ----- Creates a temporary zip archive
5409
+ $v_temp_zip = new PclZip($v_zip_temp_name);
5410
+
5411
+ // ----- Open the temporary zip file in write mode
5412
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary write mode");
5413
+ if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
5414
+ $this->privCloseFd();
5415
+
5416
+ // ----- Return
5417
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5418
+ return $v_result;
5419
+ }
5420
+
5421
+ // ----- Look which file need to be kept
5422
+ for ($i=0; $i<sizeof($v_header_list); $i++) {
5423
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Keep entry index '$i' : '".$v_header_list[$i]['filename']."'");
5424
+
5425
+ // ----- Calculate the position of the header
5426
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset='". $v_header_list[$i]['offset']."'");
5427
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
5428
+ @rewind($this->zip_fd);
5429
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
5430
+ if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
5431
+ // ----- Close the zip file
5432
+ $this->privCloseFd();
5433
+ $v_temp_zip->privCloseFd();
5434
+ @unlink($v_zip_temp_name);
5435
+
5436
+ // ----- Error log
5437
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
5438
+
5439
+ // ----- Return
5440
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5441
+ return PclZip::errorCode();
5442
+ }
5443
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
5444
+
5445
+ // ----- Read the file header
5446
+ $v_local_header = array();
5447
+ if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
5448
+ // ----- Close the zip file
5449
+ $this->privCloseFd();
5450
+ $v_temp_zip->privCloseFd();
5451
+ @unlink($v_zip_temp_name);
5452
+
5453
+ // ----- Return
5454
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5455
+ return $v_result;
5456
+ }
5457
+
5458
+ // ----- Check that local file header is same as central file header
5459
+ if ($this->privCheckFileHeaders($v_local_header,
5460
+ $v_header_list[$i]) != 1) {
5461
+ // TBC
5462
+ }
5463
+ unset($v_local_header);
5464
+
5465
+ // ----- Write the file header
5466
+ if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
5467
+ // ----- Close the zip file
5468
+ $this->privCloseFd();
5469
+ $v_temp_zip->privCloseFd();
5470
+ @unlink($v_zip_temp_name);
5471
+
5472
+ // ----- Return
5473
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5474
+ return $v_result;
5475
+ }
5476
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset for this file is '".$v_header_list[$i]['offset']."'");
5477
+
5478
+ // ----- Read/write the data block
5479
+ if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
5480
+ // ----- Close the zip file
5481
+ $this->privCloseFd();
5482
+ $v_temp_zip->privCloseFd();
5483
+ @unlink($v_zip_temp_name);
5484
+
5485
+ // ----- Return
5486
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5487
+ return $v_result;
5488
+ }
5489
+ }
5490
+
5491
+ // ----- Store the offset of the central dir
5492
+ $v_offset = @ftell($v_temp_zip->zip_fd);
5493
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "New offset of central dir : $v_offset");
5494
+
5495
+ // ----- Re-Create the Central Dir files header
5496
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the new central directory");
5497
+ for ($i=0; $i<sizeof($v_header_list); $i++) {
5498
+ // ----- Create the file header
5499
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset of file : ".$v_header_list[$i]['offset']);
5500
+ if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
5501
+ $v_temp_zip->privCloseFd();
5502
+ $this->privCloseFd();
5503
+ @unlink($v_zip_temp_name);
5504
+
5505
+ // ----- Return
5506
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5507
+ return $v_result;
5508
+ }
5509
+
5510
+ // ----- Transform the header to a 'usable' info
5511
+ $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
5512
+ }
5513
+
5514
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the central directory footer");
5515
+
5516
+ // ----- Zip file comment
5517
+ $v_comment = '';
5518
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
5519
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
5520
+ }
5521
+
5522
+ // ----- Calculate the size of the central header
5523
+ $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
5524
+
5525
+ // ----- Create the central dir footer
5526
+ if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
5527
+ // ----- Reset the file list
5528
+ unset($v_header_list);
5529
+ $v_temp_zip->privCloseFd();
5530
+ $this->privCloseFd();
5531
+ @unlink($v_zip_temp_name);
5532
+
5533
+ // ----- Return
5534
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5535
+ return $v_result;
5536
+ }
5537
+
5538
+ // ----- Close
5539
+ $v_temp_zip->privCloseFd();
5540
+ $this->privCloseFd();
5541
+
5542
+ // ----- Delete the zip file
5543
+ // TBC : I should test the result ...
5544
+ @unlink($this->zipname);
5545
+
5546
+ // ----- Rename the temporary file
5547
+ // TBC : I should test the result ...
5548
+ //@rename($v_zip_temp_name, $this->zipname);
5549
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
5550
+
5551
+ // ----- Destroy the temporary archive
5552
+ unset($v_temp_zip);
5553
+ }
5554
+
5555
+ // ----- Remove every files : reset the file
5556
+ else if ($v_central_dir['entries'] != 0) {
5557
+ $this->privCloseFd();
5558
+
5559
+ if (($v_result = $this->privOpenFd('wb')) != 1) {
5560
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5561
+ return $v_result;
5562
+ }
5563
+
5564
+ if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
5565
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5566
+ return $v_result;
5567
+ }
5568
+
5569
+ $this->privCloseFd();
5570
+ }
5571
+
5572
+ // ----- Return
5573
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5574
+ return $v_result;
5575
+ }
5576
+ // --------------------------------------------------------------------------------
5577
+
5578
+ // --------------------------------------------------------------------------------
5579
+ // Function : privDirCheck()
5580
+ // Description :
5581
+ // Check if a directory exists, if not it creates it and all the parents directory
5582
+ // which may be useful.
5583
+ // Parameters :
5584
+ // $p_dir : Directory path to check.
5585
+ // Return Values :
5586
+ // 1 : OK
5587
+ // -1 : Unable to create directory
5588
+ // --------------------------------------------------------------------------------
5589
+ function privDirCheck($p_dir, $p_is_dir=false)
5590
+ {
5591
+ $v_result = 1;
5592
+
5593
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDirCheck", "entry='$p_dir', is_dir='".($p_is_dir?"true":"false")."'");
5594
+
5595
+ // ----- Remove the final '/'
5596
+ if (($p_is_dir) && (substr($p_dir, -1)=='/'))
5597
+ {
5598
+ $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
5599
+ }
5600
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for entry '$p_dir'");
5601
+
5602
+ // ----- Check the directory availability
5603
+ if ((is_dir($p_dir)) || ($p_dir == ""))
5604
+ {
5605
+ PclTraceFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
5606
+ return 1;
5607
+ }
5608
+
5609
+ // ----- Extract parent directory
5610
+ $p_parent_dir = dirname($p_dir);
5611
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
5612
+
5613
+ // ----- Just a check
5614
+ if ($p_parent_dir != $p_dir)
5615
+ {
5616
+ // ----- Look for parent directory
5617
+ if ($p_parent_dir != "")
5618
+ {
5619
+ if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
5620
+ {
5621
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5622
+ return $v_result;
5623
+ }
5624
+ }
5625
+ }
5626
+
5627
+ // ----- Create the directory
5628
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
5629
+ if (!@mkdir($p_dir, 0777))
5630
+ {
5631
+ // ----- Error log
5632
+ PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
5633
+
5634
+ // ----- Return
5635
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5636
+ return PclZip::errorCode();
5637
+ }
5638
+
5639
+ // ----- Return
5640
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
5641
+ return $v_result;
5642
+ }
5643
+ // --------------------------------------------------------------------------------
5644
+
5645
+ // --------------------------------------------------------------------------------
5646
+ // Function : privMerge()
5647
+ // Description :
5648
+ // If $p_archive_to_add does not exist, the function exit with a success result.
5649
+ // Parameters :
5650
+ // Return Values :
5651
+ // --------------------------------------------------------------------------------
5652
+ function privMerge(&$p_archive_to_add)
5653
+ {
5654
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privMerge", "archive='".$p_archive_to_add->zipname."'");
5655
+ $v_result=1;
5656
+
5657
+ // ----- Look if the archive_to_add exists
5658
+ if (!is_file($p_archive_to_add->zipname))
5659
+ {
5660
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to add does not exist. End of merge.");
5661
+
5662
+ // ----- Nothing to merge, so merge is a success
5663
+ $v_result = 1;
5664
+
5665
+ // ----- Return
5666
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5667
+ return $v_result;
5668
+ }
5669
+
5670
+ // ----- Look if the archive exists
5671
+ if (!is_file($this->zipname))
5672
+ {
5673
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, duplicate the archive_to_add.");
5674
+
5675
+ // ----- Do a duplicate
5676
+ $v_result = $this->privDuplicate($p_archive_to_add->zipname);
5677
+
5678
+ // ----- Return
5679
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5680
+ return $v_result;
5681
+ }
5682
+
5683
+ // ----- Open the zip file
5684
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5685
+ if (($v_result=$this->privOpenFd('rb')) != 1)
5686
+ {
5687
+ // ----- Return
5688
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5689
+ return $v_result;
5690
+ }
5691
+
5692
+ // ----- Read the central directory informations
5693
+ $v_central_dir = array();
5694
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
5695
+ {
5696
+ $this->privCloseFd();
5697
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5698
+ return $v_result;
5699
+ }
5700
+
5701
+ // ----- Go to beginning of File
5702
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
5703
+ @rewind($this->zip_fd);
5704
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
5705
+
5706
+ // ----- Open the archive_to_add file
5707
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open archive_to_add in binary read mode");
5708
+ if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
5709
+ {
5710
+ $this->privCloseFd();
5711
+
5712
+ // ----- Return
5713
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5714
+ return $v_result;
5715
+ }
5716
+
5717
+ // ----- Read the central directory informations
5718
+ $v_central_dir_to_add = array();
5719
+ if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
5720
+ {
5721
+ $this->privCloseFd();
5722
+ $p_archive_to_add->privCloseFd();
5723
+
5724
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5725
+ return $v_result;
5726
+ }
5727
+
5728
+ // ----- Go to beginning of File
5729
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
5730
+ @rewind($p_archive_to_add->zip_fd);
5731
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
5732
+
5733
+ // ----- Creates a temporay file
5734
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
5735
+
5736
+ // ----- Open the temporary file in write mode
5737
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5738
+ if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
5739
+ {
5740
+ $this->privCloseFd();
5741
+ $p_archive_to_add->privCloseFd();
5742
+
5743
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
5744
+
5745
+ // ----- Return
5746
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5747
+ return PclZip::errorCode();
5748
+ }
5749
+
5750
+ // ----- Copy the files from the archive to the temporary file
5751
+ // TBC : Here I should better append the file and go back to erase the central dir
5752
+ $v_size = $v_central_dir['offset'];
5753
+ while ($v_size != 0)
5754
+ {
5755
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5756
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5757
+ $v_buffer = fread($this->zip_fd, $v_read_size);
5758
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5759
+ $v_size -= $v_read_size;
5760
+ }
5761
+
5762
+ // ----- Copy the files from the archive_to_add into the temporary file
5763
+ $v_size = $v_central_dir_to_add['offset'];
5764
+ while ($v_size != 0)
5765
+ {
5766
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5767
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5768
+ $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
5769
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5770
+ $v_size -= $v_read_size;
5771
+ }
5772
+
5773
+ // ----- Store the offset of the central dir
5774
+ $v_offset = @ftell($v_zip_temp_fd);
5775
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
5776
+
5777
+ // ----- Copy the block of file headers from the old archive
5778
+ $v_size = $v_central_dir['size'];
5779
+ while ($v_size != 0)
5780
+ {
5781
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5782
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5783
+ $v_buffer = @fread($this->zip_fd, $v_read_size);
5784
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5785
+ $v_size -= $v_read_size;
5786
+ }
5787
+
5788
+ // ----- Copy the block of file headers from the archive_to_add
5789
+ $v_size = $v_central_dir_to_add['size'];
5790
+ while ($v_size != 0)
5791
+ {
5792
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5793
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5794
+ $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
5795
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5796
+ $v_size -= $v_read_size;
5797
+ }
5798
+
5799
+ // ----- Merge the file comments
5800
+ $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
5801
+
5802
+ // ----- Calculate the size of the (new) central header
5803
+ $v_size = @ftell($v_zip_temp_fd)-$v_offset;
5804
+
5805
+ // ----- Swap the file descriptor
5806
+ // Here is a trick : I swap the temporary fd with the zip fd, in order to use
5807
+ // the following methods on the temporary fil and not the real archive fd
5808
+ $v_swap = $this->zip_fd;
5809
+ $this->zip_fd = $v_zip_temp_fd;
5810
+ $v_zip_temp_fd = $v_swap;
5811
+
5812
+ // ----- Create the central dir footer
5813
+ if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
5814
+ {
5815
+ $this->privCloseFd();
5816
+ $p_archive_to_add->privCloseFd();
5817
+ @fclose($v_zip_temp_fd);
5818
+ $this->zip_fd = null;
5819
+
5820
+ // ----- Reset the file list
5821
+ unset($v_header_list);
5822
+
5823
+ // ----- Return
5824
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5825
+ return $v_result;
5826
+ }
5827
+
5828
+ // ----- Swap back the file descriptor
5829
+ $v_swap = $this->zip_fd;
5830
+ $this->zip_fd = $v_zip_temp_fd;
5831
+ $v_zip_temp_fd = $v_swap;
5832
+
5833
+ // ----- Close
5834
+ $this->privCloseFd();
5835
+ $p_archive_to_add->privCloseFd();
5836
+
5837
+ // ----- Close the temporary file
5838
+ @fclose($v_zip_temp_fd);
5839
+
5840
+ // ----- Delete the zip file
5841
+ // TBC : I should test the result ...
5842
+ @unlink($this->zipname);
5843
+
5844
+ // ----- Rename the temporary file
5845
+ // TBC : I should test the result ...
5846
+ //@rename($v_zip_temp_name, $this->zipname);
5847
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
5848
+
5849
+ // ----- Return
5850
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5851
+ return $v_result;
5852
+ }
5853
+ // --------------------------------------------------------------------------------
5854
+
5855
+ // --------------------------------------------------------------------------------
5856
+ // Function : privDuplicate()
5857
+ // Description :
5858
+ // Parameters :
5859
+ // Return Values :
5860
+ // --------------------------------------------------------------------------------
5861
+ function privDuplicate($p_archive_filename)
5862
+ {
5863
+ PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDuplicate", "archive_filename='$p_archive_filename'");
5864
+ $v_result=1;
5865
+
5866
+ // ----- Look if the $p_archive_filename exists
5867
+ if (!is_file($p_archive_filename))
5868
+ {
5869
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to duplicate does not exist. End of duplicate.");
5870
+
5871
+ // ----- Nothing to duplicate, so duplicate is a success.
5872
+ $v_result = 1;
5873
+
5874
+ // ----- Return
5875
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5876
+ return $v_result;
5877
+ }
5878
+
5879
+ // ----- Open the zip file
5880
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5881
+ if (($v_result=$this->privOpenFd('wb')) != 1)
5882
+ {
5883
+ // ----- Return
5884
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5885
+ return $v_result;
5886
+ }
5887
+
5888
+ // ----- Open the temporary file in write mode
5889
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5890
+ if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
5891
+ {
5892
+ $this->privCloseFd();
5893
+
5894
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
5895
+
5896
+ // ----- Return
5897
+ PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5898
+ return PclZip::errorCode();
5899
+ }
5900
+
5901
+ // ----- Copy the files from the archive to the temporary file
5902
+ // TBC : Here I should better append the file and go back to erase the central dir
5903
+ $v_size = filesize($p_archive_filename);
5904
+ while ($v_size != 0)
5905
+ {
5906
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5907
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Read $v_read_size bytes");
5908
+ $v_buffer = fread($v_zip_temp_fd, $v_read_size);
5909
+ @fwrite($this->zip_fd, $v_buffer, $v_read_size);
5910
+ $v_size -= $v_read_size;
5911
+ }
5912
+
5913
+ // ----- Close
5914
+ $this->privCloseFd();
5915
+
5916
+ // ----- Close the temporary file
5917
+ @fclose($v_zip_temp_fd);
5918
+
5919
+ // ----- Return
5920
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5921
+ return $v_result;
5922
+ }
5923
+ // --------------------------------------------------------------------------------
5924
+
5925
+ // --------------------------------------------------------------------------------
5926
+ // Function : privErrorLog()
5927
+ // Description :
5928
+ // Parameters :
5929
+ // --------------------------------------------------------------------------------
5930
+ function privErrorLog($p_error_code=0, $p_error_string='')
5931
+ {
5932
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
5933
+ PclError($p_error_code, $p_error_string);
5934
+ }
5935
+ else {
5936
+ $this->error_code = $p_error_code;
5937
+ $this->error_string = $p_error_string;
5938
+ }
5939
+ }
5940
+ // --------------------------------------------------------------------------------
5941
+
5942
+ // --------------------------------------------------------------------------------
5943
+ // Function : privErrorReset()
5944
+ // Description :
5945
+ // Parameters :
5946
+ // --------------------------------------------------------------------------------
5947
+ function privErrorReset()
5948
+ {
5949
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
5950
+ PclErrorReset();
5951
+ }
5952
+ else {
5953
+ $this->error_code = 0;
5954
+ $this->error_string = '';
5955
+ }
5956
+ }
5957
+ // --------------------------------------------------------------------------------
5958
+
5959
+ // --------------------------------------------------------------------------------
5960
+ // Function : privDisableMagicQuotes()
5961
+ // Description :
5962
+ // Parameters :
5963
+ // Return Values :
5964
+ // --------------------------------------------------------------------------------
5965
+ function privDisableMagicQuotes()
5966
+ {
5967
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDisableMagicQuotes', "");
5968
+ $v_result=1;
5969
+
5970
+ // ----- Look if function exists
5971
+ if ( (!function_exists("get_magic_quotes_runtime"))
5972
+ || (!function_exists("set_magic_quotes_runtime"))) {
5973
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported");
5974
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5975
+ return $v_result;
5976
+ }
5977
+
5978
+ // ----- Look if already done
5979
+ if ($this->magic_quotes_status != -1) {
5980
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote already disabled");
5981
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5982
+ return $v_result;
5983
+ }
5984
+
5985
+ // ----- Get and memorize the magic_quote value
5986
+ $this->magic_quotes_status = @get_magic_quotes_runtime();
5987
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Current magic_quotes_runtime status is '".($this->magic_quotes_status==0?'disable':'enable')."'");
5988
+
5989
+ // ----- Disable magic_quotes
5990
+ if ($this->magic_quotes_status == 1) {
5991
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Disable magic_quotes");
5992
+ @set_magic_quotes_runtime(0);
5993
+ }
5994
+
5995
+ // ----- Return
5996
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5997
+ return $v_result;
5998
+ }
5999
+ // --------------------------------------------------------------------------------
6000
+
6001
+ // --------------------------------------------------------------------------------
6002
+ // Function : privSwapBackMagicQuotes()
6003
+ // Description :
6004
+ // Parameters :
6005
+ // Return Values :
6006
+ // --------------------------------------------------------------------------------
6007
+ function privSwapBackMagicQuotes()
6008
+ {
6009
+ PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privSwapBackMagicQuotes', "");
6010
+ $v_result=1;
6011
+
6012
+ // ----- Look if function exists
6013
+ if ( (!function_exists("get_magic_quotes_runtime"))
6014
+ || (!function_exists("set_magic_quotes_runtime"))) {
6015
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported");
6016
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
6017
+ return $v_result;
6018
+ }
6019
+
6020
+ // ----- Look if something to do
6021
+ if ($this->magic_quotes_status != -1) {
6022
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote not modified");
6023
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
6024
+ return $v_result;
6025
+ }
6026
+
6027
+ // ----- Swap back magic_quotes
6028
+ if ($this->magic_quotes_status == 1) {
6029
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Enable back magic_quotes");
6030
+ @set_magic_quotes_runtime($this->magic_quotes_status);
6031
+ }
6032
+
6033
+ // ----- Return
6034
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
6035
+ return $v_result;
6036
+ }
6037
+ // --------------------------------------------------------------------------------
6038
+
6039
+ }
6040
+ // End of class
6041
+ // --------------------------------------------------------------------------------
6042
+
6043
+ // --------------------------------------------------------------------------------
6044
+ // Function : PclZipUtilPathReduction()
6045
+ // Description :
6046
+ // Parameters :
6047
+ // Return Values :
6048
+ // --------------------------------------------------------------------------------
6049
+ function PclZipUtilPathReduction($p_dir)
6050
+ {
6051
+ PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathReduction", "dir='$p_dir'");
6052
+ $v_result = "";
6053
+
6054
+ // ----- Look for not empty path
6055
+ if ($p_dir != "") {
6056
+ // ----- Explode path by directory names
6057
+ $v_list = explode("/", $p_dir);
6058
+
6059
+ // ----- Study directories from last to first
6060
+ $v_skip = 0;
6061
+ for ($i=sizeof($v_list)-1; $i>=0; $i--) {
6062
+ // ----- Look for current path
6063
+ if ($v_list[$i] == ".") {
6064
+ // ----- Ignore this directory
6065
+ // Should be the first $i=0, but no check is done
6066
+ }
6067
+ else if ($v_list[$i] == "..") {
6068
+ $v_skip++;
6069
+ }
6070
+ else if ($v_list[$i] == "") {
6071
+ // ----- First '/' i.e. root slash
6072
+ if ($i == 0) {
6073
+ $v_result = "/".$v_result;
6074
+ if ($v_skip > 0) {
6075
+ // ----- It is an invalid path, so the path is not modified
6076
+ // TBC
6077
+ $v_result = $p_dir;
6078
+ PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid path is unchanged");
6079
+ $v_skip = 0;
6080
+ }
6081
+ }
6082
+ // ----- Last '/' i.e. indicates a directory
6083
+ else if ($i == (sizeof($v_list)-1)) {
6084
+ $v_result = $v_list[$i];
6085
+ }
6086
+ // ----- Double '/' inside the path
6087
+ else {
6088
+ // ----- Ignore only the double '//' in path,
6089
+ // but not the first and last '/'
6090
+ }
6091
+ }
6092
+ else {
6093
+ // ----- Look for item to skip
6094
+ if ($v_skip > 0) {
6095
+ $v_skip--;
6096
+ }
6097
+ else {
6098
+ $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
6099
+ }
6100
+ }
6101
+ }
6102
+
6103
+ // ----- Look for skip
6104
+ if ($v_skip > 0) {
6105
+ while ($v_skip > 0) {
6106
+ $v_result = '../'.$v_result;
6107
+ $v_skip--;
6108
+ }
6109
+ }
6110
+ }
6111
+
6112
+ // ----- Return
6113
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
6114
+ return $v_result;
6115
+ }
6116
+ // --------------------------------------------------------------------------------
6117
+
6118
+ // --------------------------------------------------------------------------------
6119
+ // Function : PclZipUtilPathInclusion()
6120
+ // Description :
6121
+ // This function indicates if the path $p_path is under the $p_dir tree. Or,
6122
+ // said in an other way, if the file or sub-dir $p_path is inside the dir
6123
+ // $p_dir.
6124
+ // The function indicates also if the path is exactly the same as the dir.
6125
+ // This function supports path with duplicated '/' like '//', but does not
6126
+ // support '.' or '..' statements.
6127
+ // Parameters :
6128
+ // Return Values :
6129
+ // 0 if $p_path is not inside directory $p_dir
6130
+ // 1 if $p_path is inside directory $p_dir
6131
+ // 2 if $p_path is exactly the same as $p_dir
6132
+ // --------------------------------------------------------------------------------
6133
+ function PclZipUtilPathInclusion($p_dir, $p_path)
6134
+ {
6135
+ PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathInclusion", "dir='$p_dir', path='$p_path'");
6136
+ $v_result = 1;
6137
+
6138
+ // ----- Look for path beginning by ./
6139
+ if ( ($p_dir == '.')
6140
+ || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
6141
+ $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
6142
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_dir '".$p_dir."'");
6143
+ }
6144
+ if ( ($p_path == '.')
6145
+ || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
6146
+ $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
6147
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_path '".$p_path."'");
6148
+ }
6149
+
6150
+ // ----- Explode dir and path by directory separator
6151
+ $v_list_dir = explode("/", $p_dir);
6152
+ $v_list_dir_size = sizeof($v_list_dir);
6153
+ $v_list_path = explode("/", $p_path);
6154
+ $v_list_path_size = sizeof($v_list_path);
6155
+
6156
+ // ----- Study directories paths
6157
+ $i = 0;
6158
+ $j = 0;
6159
+ while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
6160
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Working on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'");
6161
+
6162
+ // ----- Look for empty dir (path reduction)
6163
+ if ($v_list_dir[$i] == '') {
6164
+ $i++;
6165
+ continue;
6166
+ }
6167
+ if ($v_list_path[$j] == '') {
6168
+ $j++;
6169
+ continue;
6170
+ }
6171
+
6172
+ // ----- Compare the items
6173
+ if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
6174
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Items ($i,$j) are different");
6175
+ $v_result = 0;
6176
+ }
6177
+
6178
+ // ----- Next items
6179
+ $i++;
6180
+ $j++;
6181
+ }
6182
+
6183
+ // ----- Look if everything seems to be the same
6184
+ if ($v_result) {
6185
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Look for tie break");
6186
+ // ----- Skip all the empty items
6187
+ while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
6188
+ while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
6189
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Looking on dir($i)='".($i < $v_list_dir_size?$v_list_dir[$i]:'')."' and path($j)='".($j < $v_list_path_size?$v_list_path[$j]:'')."'");
6190
+
6191
+ if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
6192
+ // ----- There are exactly the same
6193
+ $v_result = 2;
6194
+ }
6195
+ else if ($i < $v_list_dir_size) {
6196
+ // ----- The path is shorter than the dir
6197
+ $v_result = 0;
6198
+ }
6199
+ }
6200
+
6201
+ // ----- Return
6202
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
6203
+ return $v_result;
6204
+ }
6205
+ // --------------------------------------------------------------------------------
6206
+
6207
+ // --------------------------------------------------------------------------------
6208
+ // Function : PclZipUtilCopyBlock()
6209
+ // Description :
6210
+ // Parameters :
6211
+ // $p_mode : read/write compression mode
6212
+ // 0 : src & dest normal
6213
+ // 1 : src gzip, dest normal
6214
+ // 2 : src normal, dest gzip
6215
+ // 3 : src & dest gzip
6216
+ // Return Values :
6217
+ // --------------------------------------------------------------------------------
6218
+ function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
6219
+ {
6220
+ PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilCopyBlock", "size=$p_size, mode=$p_mode");
6221
+ $v_result = 1;
6222
+
6223
+ if ($p_mode==0)
6224
+ {
6225
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset before read :".(@ftell($p_src)));
6226
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset before write :".(@ftell($p_dest)));
6227
+ while ($p_size != 0)
6228
+ {
6229
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
6230
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
6231
+ $v_buffer = @fread($p_src, $v_read_size);
6232
+ @fwrite($p_dest, $v_buffer, $v_read_size);
6233
+ $p_size -= $v_read_size;
6234
+ }
6235
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset after read :".(@ftell($p_src)));
6236
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset after write :".(@ftell($p_dest)));
6237
+ }
6238
+ else if ($p_mode==1)
6239
+ {
6240
+ while ($p_size != 0)
6241
+ {
6242
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
6243
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
6244
+ $v_buffer = @gzread($p_src, $v_read_size);
6245
+ @fwrite($p_dest, $v_buffer, $v_read_size);
6246
+ $p_size -= $v_read_size;
6247
+ }
6248
+ }
6249
+ else if ($p_mode==2)
6250
+ {
6251
+ while ($p_size != 0)
6252
+ {
6253
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
6254
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
6255
+ $v_buffer = @fread($p_src, $v_read_size);
6256
+ @gzwrite($p_dest, $v_buffer, $v_read_size);
6257
+ $p_size -= $v_read_size;
6258
+ }
6259
+ }
6260
+ else if ($p_mode==3)
6261
+ {
6262
+ while ($p_size != 0)
6263
+ {
6264
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
6265
+ PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
6266
+ $v_buffer = @gzread($p_src, $v_read_size);
6267
+ @gzwrite($p_dest, $v_buffer, $v_read_size);
6268
+ $p_size -= $v_read_size;
6269
+ }
6270
+ }
6271
+
6272
+ // ----- Return
6273
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
6274
+ return $v_result;
6275
+ }
6276
+ // --------------------------------------------------------------------------------
6277
+
6278
+ // --------------------------------------------------------------------------------
6279
+ // Function : PclZipUtilRename()
6280
+ // Description :
6281
+ // This function tries to do a simple rename() function. If it fails, it
6282
+ // tries to copy the $p_src file in a new $p_dest file and then unlink the
6283
+ // first one.
6284
+ // Parameters :
6285
+ // $p_src : Old filename
6286
+ // $p_dest : New filename
6287
+ // Return Values :
6288
+ // 1 on success, 0 on failure.
6289
+ // --------------------------------------------------------------------------------
6290
+ function PclZipUtilRename($p_src, $p_dest)
6291
+ {
6292
+ PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilRename", "source=$p_src, destination=$p_dest");
6293
+ $v_result = 1;
6294
+
6295
+ // ----- Try to rename the files
6296
+ if (!@rename($p_src, $p_dest)) {
6297
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to rename file, try copy+unlink");
6298
+
6299
+ // ----- Try to copy & unlink the src
6300
+ if (!@copy($p_src, $p_dest)) {
6301
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to copy file");
6302
+ $v_result = 0;
6303
+ }
6304
+ else if (!@unlink($p_src)) {
6305
+ PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to unlink old filename");
6306
+ $v_result = 0;
6307
+ }
6308
+ }
6309
+
6310
+ // ----- Return
6311
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
6312
+ return $v_result;
6313
+ }
6314
+ // --------------------------------------------------------------------------------
6315
+
6316
+ // --------------------------------------------------------------------------------
6317
+ // Function : PclZipUtilOptionText()
6318
+ // Description :
6319
+ // Translate option value in text. Mainly for debug purpose.
6320
+ // Parameters :
6321
+ // $p_option : the option value.
6322
+ // Return Values :
6323
+ // The option text value.
6324
+ // --------------------------------------------------------------------------------
6325
+ function PclZipUtilOptionText($p_option)
6326
+ {
6327
+ PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilOptionText", "option='".$p_option."'");
6328
+
6329
+ $v_list = get_defined_constants();
6330
+ for (reset($v_list); $v_key = key($v_list); next($v_list)) {
6331
+ $v_prefix = substr($v_key, 0, 10);
6332
+ if (( ($v_prefix == 'PCLZIP_OPT')
6333
+ || ($v_prefix == 'PCLZIP_CB_')
6334
+ || ($v_prefix == 'PCLZIP_ATT'))
6335
+ && ($v_list[$v_key] == $p_option)) {
6336
+ PclTraceFctEnd(__FILE__, __LINE__, $v_key);
6337
+ return $v_key;
6338
+ }
6339
+ }
6340
+
6341
+ $v_result = 'Unknown';
6342
+
6343
+ PclTraceFctEnd(__FILE__, __LINE__, $v_result);
6344
+ return $v_result;
6345
+ }
6346
+ // --------------------------------------------------------------------------------
6347
+
6348
+ // --------------------------------------------------------------------------------
6349
+ // Function : PclZipUtilTranslateWinPath()
6350
+ // Description :
6351
+ // Translate windows path by replacing '\' by '/' and optionally removing
6352
+ // drive letter.
6353
+ // Parameters :
6354
+ // $p_path : path to translate.
6355
+ // $p_remove_disk_letter : true | false
6356
+ // Return Values :
6357
+ // The path translated.
6358
+ // --------------------------------------------------------------------------------
6359
+ function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
6360
+ {
6361
+ if (stristr(php_uname(), 'windows')) {
6362
+ // ----- Look for potential disk letter
6363
+ if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
6364
+ $p_path = substr($p_path, $v_position+1);
6365
+ }
6366
+ // ----- Change potential windows directory separator
6367
+ if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
6368
+ $p_path = strtr($p_path, '\\', '/');
6369
+ }
6370
+ }
6371
+ return $p_path;
6372
+ }
6373
+ // --------------------------------------------------------------------------------
6374
+
6375
+
6376
+ ?>
app/options-save.php CHANGED
@@ -65,6 +65,7 @@ case 'savecfg': //Save config form Setings page
65
  $cfg['maxlogs']=abs((int)$_POST['maxlogs']);
66
  $cfg['dirlogs']=untrailingslashit(str_replace('\\','/',stripslashes($_POST['dirlogs'])));
67
  $cfg['dirtemp']=untrailingslashit(str_replace('\\','/',stripslashes($_POST['dirtemp'])));
 
68
  if (update_option('backwpup',$cfg))
69
  $backwpup_message=__('Settings saved', 'backwpup');
70
  $_REQUEST['action']='settings';
65
  $cfg['maxlogs']=abs((int)$_POST['maxlogs']);
66
  $cfg['dirlogs']=untrailingslashit(str_replace('\\','/',stripslashes($_POST['dirlogs'])));
67
  $cfg['dirtemp']=untrailingslashit(str_replace('\\','/',stripslashes($_POST['dirtemp'])));
68
+ $cfg['pcl_log_level']=$_POST['pcl_log_level'];
69
  if (update_option('backwpup',$cfg))
70
  $backwpup_message=__('Settings saved', 'backwpup');
71
  $_REQUEST['action']='settings';
app/options-settings.php CHANGED
@@ -98,6 +98,20 @@ echo '</select>';
98
  </td>
99
  </tr>
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
  </table>
103
 
98
  </td>
99
  </tr>
100
 
101
+ <tr valign="top">
102
+ <th scope="row"><label for="pcl_log_level"><?PHP _e('Log Level for PCL ZIP:','backwpup'); ?></label></th>
103
+ <td>
104
+ <?PHP
105
+ echo '<select name="pcl_log_level">';
106
+ echo '<option value="1"'.selected(1,$cfg['pcl_log_level'],false).'>'.__('Level 1 (Errors)','backwpup').'</option>';
107
+ echo '<option value="2"'.selected(2,$cfg['pcl_log_level'],false).'>'.__('Level 2 (Min.)','backwpup').'</option>';
108
+ echo '<option value="3"'.selected(3,$cfg['pcl_log_level'],false).'>'.__('Level 3','backwpup').'</option>';
109
+ echo '<option value="4"'.selected(4,$cfg['pcl_log_level'],false).'>'.__('Level 4','backwpup').'</option>';
110
+ echo '<option value="5"'.selected(5,$cfg['pcl_log_level'],false).'>'.__('Level 5 (Max.)','backwpup').'</option>';
111
+ echo '</select>';
112
+ ?><br />
113
+ </td>
114
+ </tr>
115
 
116
  </table>
117
 
backwpup.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: BackWPup
4
  Plugin URI: http://danielhuesken.de/portfolio/backwpup/
5
  Description: Backup and more of your WordPress Blog Database and Files.
6
  Author: Daniel H&uuml;sken
7
- Version: 0.8.0
8
  Author URI: http://danielhuesken.de
9
  Text Domain: backwpup
10
  Domain Path: /lang/
@@ -35,7 +35,7 @@ if ( !defined('ABSPATH') )
35
  //Set plugin dirname
36
  define('BACKWPUP_PLUGIN_DIR', dirname(plugin_basename(__FILE__)));
37
  //Set Plugin Version
38
- define('BACKWPUP_VERSION', '0.8.0');
39
 
40
  //load Text Domain
41
  load_plugin_textdomain('backwpup', false, BACKWPUP_PLUGIN_DIR.'/lang');
4
  Plugin URI: http://danielhuesken.de/portfolio/backwpup/
5
  Description: Backup and more of your WordPress Blog Database and Files.
6
  Author: Daniel H&uuml;sken
7
+ Version: 0.8.1
8
  Author URI: http://danielhuesken.de
9
  Text Domain: backwpup
10
  Domain Path: /lang/
35
  //Set plugin dirname
36
  define('BACKWPUP_PLUGIN_DIR', dirname(plugin_basename(__FILE__)));
37
  //Set Plugin Version
38
+ define('BACKWPUP_VERSION', '0.8.1');
39
 
40
  //load Text Domain
41
  load_plugin_textdomain('backwpup', false, BACKWPUP_PLUGIN_DIR.'/lang');
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: danielhuesken
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=daniel%40huesken-net%2ede&item_name=Daniel%20Huesken%20Plugin%20Donation&item_number=BackWPup&no_shipping=0&no_note=1&tax=0&currency_code=EUR&lc=DE&bn=PP%2dDonationsBF&charset=UTF%2d8
4
  Tags: backup, admin, file, Database, mysql, cron, ftp, S3
5
  Requires at least: 2.8
6
- Tested up to: 2.9.3
7
- Stable tag: 0.8.0
8
 
9
  Backup and more of your WordPress Blog Database and Files
10
 
@@ -46,18 +46,22 @@ in the root folder of the zip Archive. <i>DBName</i>.sql
46
  1. Job Page
47
 
48
  == Changelog ==
 
 
 
 
49
  = 0.8.0 =
50
  * Fiexed not working default setttings on settingspage
51
  * crate .htaccsses on Apache and index.html on other webserver
52
  * fixed global for $wp_version
53
- * set max execution time to 0 for unlimeted job time
54
- * use WP function to display job tables
55
  * Backup file list and zip creation changes
56
  * Added support for Amazon S3
57
  * Only works with PHP 5 now
58
  * Cmplete rewrite of job doing as PHP5 class
59
  * PHP errors now in Backup log
60
- * Log stred in files now again
61
 
62
  = 0.7.2 =
63
  * make FTP any more robust
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=daniel%40huesken-net%2ede&item_name=Daniel%20Huesken%20Plugin%20Donation&item_number=BackWPup&no_shipping=0&no_note=1&tax=0&currency_code=EUR&lc=DE&bn=PP%2dDonationsBF&charset=UTF%2d8
4
  Tags: backup, admin, file, Database, mysql, cron, ftp, S3
5
  Requires at least: 2.8
6
+ Tested up to: 3.0.0
7
+ Stable tag: 0.8.1
8
 
9
  Backup and more of your WordPress Blog Database and Files
10
 
46
  1. Job Page
47
 
48
  == Changelog ==
49
+ = 0.8.1 =
50
+ * use global var instat of constant for log file
51
+ * PCL Zip Trace included with setting for log Level
52
+
53
  = 0.8.0 =
54
  * Fiexed not working default setttings on settingspage
55
  * crate .htaccsses on Apache and index.html on other webserver
56
  * fixed global for $wp_version
57
+ * set max execution time to 0 for unlimeted
58
+ * use WP function to generate options tables
59
  * Backup file list and zip creation changes
60
  * Added support for Amazon S3
61
  * Only works with PHP 5 now
62
  * Cmplete rewrite of job doing as PHP5 class
63
  * PHP errors now in Backup log
64
+ * Log now in files
65
 
66
  = 0.7.2 =
67
  * make FTP any more robust