source: spip-zone/_core_/plugins/archiviste/inc/pcltar.php

Last change on this file was 95127, checked in by marcimat@…, 3 years ago

Mauvais nom d'une variable par endroit (undefined) sur pcltar encore : uniformisation.

File size: 115.3 KB
Line 
1<?php
2// --------------------------------------------------------------------------------
3// PhpConcept Library - Tar Module 1.3.1
4// --------------------------------------------------------------------------------
5// License GNU/GPL - Vincent Blavet - January 2003
6// http://www.phpconcept.net
7// --------------------------------------------------------------------------------
8//
9// Presentation :
10//   PclTar is a library that allow you to create a GNU TAR + GNU ZIP archive,
11//   to add files or directories, to extract all the archive or a part of it.
12//   So far tests show that the files generated by PclTar are readable by
13//   gzip tools and WinZip application.
14//
15// Description :
16//   See readme.txt (English & Fran�ais) and http://www.phpconcept.net
17//
18// Warning :
19//   This library and the associated files are non commercial, non professional
20//   work.
21//   It should not have unexpected results. However if any damage is caused by
22//   this software the author can not be responsible.
23//   The use of this software is at the risk of the user.
24//
25// --------------------------------------------------------------------------------
26
27// ----- Look for double include
28if (!defined("PCL_TAR")) {
29        define("PCL_TAR", 1);
30
31        // ----- Configuration variable
32        // Theses values may be changed by the user of PclTar library
33        if (!isset($g_pcltar_lib_dir)) {
34                $g_pcltar_lib_dir = find_in_path("lib/pcltar");
35        }
36
37        // ----- Error codes
38        //   -1 : Unable to open file in binary write mode
39        //   -2 : Unable to open file in binary read mode
40        //   -3 : Invalid parameters
41        //   -4 : File does not exist
42        //   -5 : Filename is too long (max. 99)
43        //   -6 : Not a valid tar file
44        //   -7 : Invalid extracted file size
45        //   -8 : Unable to create directory
46        //   -9 : Invalid archive extension
47        //  -10 : Invalid archive format
48        //  -11 : Unable to delete file (unlink)
49        //  -12 : Unable to rename file (rename)
50        //  -13 : Invalid header checksum
51
52
53// --------------------------------------------------------------------------------
54// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
55// --------------------------------------------------------------------------------
56
57        // ----- Global variables
58        $g_pcltar_version = "1.3.1";
59
60        // ----- Extract extension type (.php3/.php/...)
61        $g_pcltar_extension = "php";
62
63        // ----- Include other libraries
64        // This library should be called by each script before the include of PhpZip
65        // Library in order to limit the potential 'lib' directory path problem.
66        if (!defined("PCLERROR_LIB")) {
67                include($g_pcltar_lib_dir . "/pclerror.lib." . $g_pcltar_extension);
68        }
69        if (!defined("PCLTRACE_LIB")) {
70                include($g_pcltar_lib_dir . "/pcltrace.lib." . $g_pcltar_extension);
71        }
72
73        // --------------------------------------------------------------------------------
74        // Function : PclTarCreate()
75        // Description :
76        //   Creates a new archive with name $p_tarname containing the files and/or
77        //   directories indicated in $p_list. If the tar filename extension is
78        //   ".tar", the file will not be compressed. If it is ".tar.gz" or ".tgz"
79        //   it will be a gzip compressed tar archive.
80        //   If you want to use an other extension, you must indicate the mode in
81        //   $p_mode ("tar" or "tgz").
82        //   $p_add_dir and $p_remove_dir give you the ability to store a path
83        //   which is not the real path of the files.
84        // Parameters :
85        //   $p_tarname : Name of an existing tar file
86        //   $p_filelist : An array containing file or directory names, or
87        //                 a string containing one filename or directory name, or
88        //                 a string containing a list of filenames and/or directory
89        //                 names separated by spaces.
90        //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive,
91        //             if $p_mode is not specified, it will be determined by the extension.
92        //   $p_add_dir : Path to add in the filename path archived
93        //   $p_remove_dir : Path to remove in the filename path archived
94        // Return Values :
95        //   1 on success, or an error code (see table at the beginning).
96        // --------------------------------------------------------------------------------
97        function PclTarCreate($p_tarname, $p_filelist = "", $p_mode = "", $p_add_dir = "", $p_remove_dir = "") {
98                TrFctStart(__FILE__, __LINE__, "PclTarCreate",
99                        "tar=$p_tarname, file='$p_filelist', mode=$p_mode, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
100                $v_result = 1;
101
102                // ----- Look for default mode
103                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
104                        // ----- Extract the tar format from the extension
105                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
106                                // ----- Return
107                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
108
109                                return PclErrorCode();
110                        }
111
112                        // ----- Trace
113                        TrFctMessage(__FILE__, __LINE__, 1, "Auto mode selected : found $p_mode");
114                }
115
116                // ----- Look if the $p_filelist is really an array
117                if (is_array($p_filelist)) {
118                        // ----- Call the create fct
119                        $v_result = PclTarHandleCreate($p_tarname, $p_filelist, $p_mode, $p_add_dir, $p_remove_dir);
120                } // ----- Look if the $p_filelist is a string
121                else {
122                        if (is_string($p_filelist)) {
123                                // ----- Create a list with the elements from the string
124                                $v_list = explode(" ", $p_filelist);
125
126                                // ----- Call the create fct
127                                $v_result = PclTarHandleCreate($p_tarname, $v_list, $p_mode, $p_add_dir, $p_remove_dir);
128                        } // ----- Invalid variable
129                        else {
130                                // ----- Error log
131                                PclErrorLog(-3, "Invalid variable type p_filelist");
132                                $v_result = -3;
133                        }
134                }
135
136                // ----- Return
137                TrFctEnd(__FILE__, __LINE__, $v_result);
138
139                return $v_result;
140        }
141
142        // --------------------------------------------------------------------------------
143
144        // --------------------------------------------------------------------------------
145        // Function : PclTarAdd()
146        // Description :
147        //   PLEASE DO NOT USE ANY MORE THIS FUNCTION. Use PclTarAddList().
148        //
149        //   This function is maintained only for compatibility reason
150        //
151        // Parameters :
152        //   $p_tarname : Name of an existing tar file
153        //   $p_filelist : An array containing file or directory names, or
154        //                 a string containing one filename or directory name, or
155        //                 a string containing a list of filenames and/or directory
156        //                 names separated by spaces.
157        // Return Values :
158        //   1 on success,
159        //   Or an error code (see list on top).
160        // --------------------------------------------------------------------------------
161        function PclTarAdd($p_tarname, $p_filelist) {
162                TrFctStart(__FILE__, __LINE__, "PclTarAdd", "tar=$p_tarname, file=$p_filelist");
163                $v_result = 1;
164                $v_list_detail = array();
165
166                // ----- Extract the tar format from the extension
167                if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
168                        // ----- Return
169                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
170
171                        return PclErrorCode();
172                }
173
174                // ----- Look if the $p_filelist is really an array
175                if (is_array($p_filelist)) {
176                        // ----- Call the add fct
177                        $v_result = PclTarHandleAppend($p_tarname, $p_filelist, $p_mode, $v_list_detail, "", "");
178                } // ----- Look if the $p_filelist is a string
179                else {
180                        if (is_string($p_filelist)) {
181                                // ----- Create a list with the elements from the string
182                                $v_list = explode(" ", $p_filelist);
183
184                                // ----- Call the add fct
185                                $v_result = PclTarHandleAppend($p_tarname, $v_list, $p_mode, $v_list_detail, "", "");
186                        } // ----- Invalid variable
187                        else {
188                                // ----- Error log
189                                PclErrorLog(-3, "Invalid variable type p_filelist");
190                                $v_result = -3;
191                        }
192                }
193
194                // ----- Cleaning
195                unset($v_list_detail);
196
197                // ----- Return
198                TrFctEnd(__FILE__, __LINE__, $v_result);
199
200                return $v_result;
201        }
202
203        // --------------------------------------------------------------------------------
204
205        // --------------------------------------------------------------------------------
206        // Function : PclTarAddList()
207        // Description :
208        //   Add a list of files or directories ($p_filelist) in the tar archive $p_tarname.
209        //   The list can be an array of file/directory names or a string with names
210        //   separated by one space.
211        //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
212        //   different from the real path of the file. This is usefull if you want to have PclTar
213        //   running in any directory, and memorize relative path from an other directory.
214        //   If $p_mode is not set it will be automatically computed from the $p_tarname
215        //   extension (.tar, .tar.gz or .tgz).
216        // Parameters :
217        //   $p_tarname : Name of an existing tar file
218        //   $p_filelist : An array containing file or directory names, or
219        //                 a string containing one filename or directory name, or
220        //                 a string containing a list of filenames and/or directory
221        //                 names separated by spaces.
222        //   $p_add_dir : Path to add in the filename path archived
223        //   $p_remove_dir : Path to remove in the filename path archived
224        //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
225        // Return Values :
226        //   1 on success,
227        //   Or an error code (see list on top).
228        // --------------------------------------------------------------------------------
229        function PclTarAddList($p_tarname, $p_filelist, $p_add_dir = "", $p_remove_dir = "", $p_mode = "") {
230                TrFctStart(__FILE__, __LINE__, "PclTarAddList",
231                        "tar=$p_tarname, file=$p_filelist, p_add_dir='$p_add_dir', p_remove_dir='$p_remove_dir', mode=$p_mode");
232                $v_result = 1;
233                $p_list_detail = array();
234
235                // ----- Extract the tar format from the extension
236                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
237                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
238                                // ----- Return
239                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
240
241                                return PclErrorCode();
242                        }
243                }
244
245                // ----- Look if the $p_filelist is really an array
246                if (is_array($p_filelist)) {
247                        // ----- Call the add fct
248                        $v_result = PclTarHandleAppend($p_tarname, $p_filelist, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
249                } // ----- Look if the $p_filelist is a string
250                else {
251                        if (is_string($p_filelist)) {
252                                // ----- Create a list with the elements from the string
253                                $v_list = explode(" ", $p_filelist);
254
255                                // ----- Call the add fct
256                                $v_result = PclTarHandleAppend($p_tarname, $v_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
257                        } // ----- Invalid variable
258                        else {
259                                // ----- Error log
260                                PclErrorLog(-3, "Invalid variable type p_filelist");
261                                $v_result = -3;
262                        }
263                }
264
265                // ----- Return
266                if ($v_result != 1) {
267                        TrFctEnd(__FILE__, __LINE__, 0);
268
269                        return 0;
270                }
271                TrFctEnd(__FILE__, __LINE__, $p_list_detail);
272
273                return $p_list_detail;
274        }
275
276        // --------------------------------------------------------------------------------
277
278        // --------------------------------------------------------------------------------
279        // Function : PclTarList()
280        // Description :
281        //   Gives the list of all the files present in the tar archive $p_tarname.
282        //   The list is the function result, it will be 0 on error.
283        //   Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
284        //   function will determine the type of the archive.
285        // Parameters :
286        //   $p_tarname : Name of an existing tar file
287        //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
288        // Return Values :
289        //  0 on error (Use PclErrorCode() and PclErrorString() for more info)
290        //  or
291        //  An array containing file properties. Each file properties is an array of
292        //  properties.
293        //  The properties (array field names) are :
294        //    filename, size, mode, uid, gid, mtime, typeflag, status
295        //  Exemple : $v_list = PclTarList("my.tar");
296        //            for ($i=0; $i<sizeof($v_list); $i++)
297        //              echo "Filename :'".$v_list[$i]['filename']."'<br>";
298        // --------------------------------------------------------------------------------
299        function PclTarList($p_tarname, $p_mode = "") {
300                TrFctStart(__FILE__, __LINE__, "PclTarList", "tar=$p_tarname, mode='$p_mode'");
301                $v_result = 1;
302
303                // ----- Extract the tar format from the extension
304                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
305                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
306                                // ----- Return
307                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
308
309                                return 0;
310                        }
311                }
312
313                // ----- Call the extracting fct
314                $p_list = array();
315                if (($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, "list", "", $p_mode, "")) != 1) {
316                        unset($p_list);
317                        TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
318
319                        return (0);
320                }
321
322                // ----- Return
323                TrFctEnd(__FILE__, __LINE__, $p_list);
324
325                return $p_list;
326        }
327
328        // --------------------------------------------------------------------------------
329
330        // --------------------------------------------------------------------------------
331        // Function : PclTarExtract()
332        // Description :
333        //   Extract all the files present in the archive $p_tarname, in the directory
334        //   $p_path. The relative path of the archived files are keep and become
335        //   relative to $p_path.
336        //   If a file with the same name already exists it will be replaced.
337        //   If the path to the file does not exist, it will be created.
338        //   Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
339        //   function will determine the type of the archive.
340        // Parameters :
341        //   $p_tarname : Name of an existing tar file.
342        //   $p_path : Path where the files will be extracted. The files will use
343        //             their memorized path from $p_path.
344        //             If $p_path is "", files will be extracted in "./".
345        //   $p_remove_path : Path to remove (from the file memorized path) while writing the
346        //                    extracted files. If the path does not match the file path,
347        //                    the file is extracted with its memorized path.
348        //                    $p_path and $p_remove_path are commulative.
349        //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
350        // Return Values :
351        //   Same as PclTarList()
352        // --------------------------------------------------------------------------------
353        function PclTarExtract($p_tarname, $p_path = "./", $p_remove_path = "", $p_mode = "") {
354                TrFctStart(__FILE__, __LINE__, "PclTarExtract",
355                        "tar='$p_tarname', path='$p_path', remove_path='$p_remove_path', mode='$p_mode'");
356                $v_result = 1;
357
358                // ----- Extract the tar format from the extension
359                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
360                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
361                                // ----- Return
362                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
363
364                                return 0;
365                        }
366                }
367
368                // ----- Call the extracting fct
369                if (($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, "complete", $p_path, $p_mode,
370                                $p_remove_path)) != 1
371                ) {
372                        TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
373
374                        return (0);
375                }
376
377                // ----- Return
378                TrFctEnd(__FILE__, __LINE__, $p_list);
379
380                return $p_list;
381        }
382
383        // --------------------------------------------------------------------------------
384
385        // --------------------------------------------------------------------------------
386        // Function : PclTarExtractList()
387        // Description :
388        //   Extract the files present in the archive $p_tarname and specified in
389        //   $p_filelist, in the directory
390        //   $p_path. The relative path of the archived files are keep and become
391        //   relative to $p_path.
392        //   If a directory is sp�cified in the list, all the files from this directory
393        //   will be extracted.
394        //   If a file with the same name already exists it will be replaced.
395        //   If the path to the file does not exist, it will be created.
396        //   Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
397        //   function will determine the type of the archive.
398        // Parameters :
399        //   $p_tarname : Name of an existing tar file
400        //   $p_filelist : An array containing file or directory names, or
401        //                 a string containing one filename or directory name, or
402        //                 a string containing a list of filenames and/or directory
403        //                 names separated by spaces.
404        //   $p_path : Path where the files will be extracted. The files will use
405        //             their memorized path from $p_path.
406        //             If $p_path is "", files will be extracted in "./".
407        //   $p_remove_path : Path to remove (from the file memorized path) while writing the
408        //                    extracted files. If the path does not match the file path,
409        //                    the file is extracted with its memorized path.
410        //                    $p_path and $p_remove_path are commulative.
411        //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
412        // Return Values :
413        //   Same as PclTarList()
414        // --------------------------------------------------------------------------------
415        function PclTarExtractList($p_tarname, $p_filelist, $p_path = "./", $p_remove_path = "", $p_mode = "") {
416                TrFctStart(__FILE__, __LINE__, "PclTarExtractList",
417                        "tar=$p_tarname, list, path=$p_path, remove_path='$p_remove_path', mode='$p_mode'");
418                $v_result = 1;
419
420                // ----- Extract the tar format from the extension
421                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
422                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
423                                // ----- Return
424                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
425
426                                return 0;
427                        }
428                }
429
430                // ----- Look if the $p_filelist is really an array
431                if (is_array($p_filelist)) {
432                        // ----- Call the extracting fct
433                        if (($v_result = PclTarHandleExtract($p_tarname, $p_filelist, $p_list, "partial", $p_path, $p_mode,
434                                        $p_remove_path)) != 1
435                        ) {
436                                TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
437
438                                return (0);
439                        }
440                } // ----- Look if the $p_filelist is a string
441                else {
442                        if (is_string($p_filelist)) {
443                                // ----- Create a list with the elements from the string
444                                $v_list = explode(" ", $p_filelist);
445
446                                // ----- Call the extracting fct
447                                if (($v_result = PclTarHandleExtract($p_tarname, $v_list, $p_list, "partial", $p_path, $p_mode,
448                                                $p_remove_path)) != 1
449                                ) {
450                                        TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
451
452                                        return (0);
453                                }
454                        } // ----- Invalid variable
455                        else {
456                                // ----- Error log
457                                PclErrorLog(-3, "Invalid variable type p_filelist");
458
459                                // ----- Return
460                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
461
462                                return 0;
463                        }
464                }
465
466                // ----- Return
467                TrFctEnd(__FILE__, __LINE__, $p_list);
468
469                return $p_list;
470        }
471
472        // --------------------------------------------------------------------------------
473
474        // --------------------------------------------------------------------------------
475        // Function : PclTarExtractIndex()
476        // Description :
477        //   Extract the files present in the archive $p_tarname and specified at
478        //   the indexes in $p_index, in the directory
479        //   $p_path. The relative path of the archived files are keep and become
480        //   relative to $p_path.
481        //   If a directory is specified in the list, the directory only is created. All
482        //   the file stored in this archive for this directory
483        //   are not extracted.
484        //   If a file with the same name already exists it will be replaced.
485        //   If the path to the file does not exist, it will be created.
486        //   Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
487        //   function will determine the type of the archive.
488        // Parameters :
489        //   $p_tarname : Name of an existing tar file
490        //   $p_index : A single index (integer) or a string of indexes of files to
491        //              extract. The form of the string is "0,4-6,8-12" with only numbers
492        //              and '-' for range or ',' to separate ranges. No spaces or ';'
493        //              are allowed.
494        //   $p_path : Path where the files will be extracted. The files will use
495        //             their memorized path from $p_path.
496        //             If $p_path is "", files will be extracted in "./".
497        //   $p_remove_path : Path to remove (from the file memorized path) while writing the
498        //                    extracted files. If the path does not match the file path,
499        //                    the file is extracted with its memorized path.
500        //                    $p_path and $p_remove_path are commulative.
501        //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
502        // Return Values :
503        //   Same as PclTarList()
504        // --------------------------------------------------------------------------------
505        function PclTarExtractIndex($p_tarname, $p_index, $p_path = "./", $p_remove_path = "", $p_mode = "") {
506                TrFctStart(__FILE__, __LINE__, "PclTarExtractIndex",
507                        "tar=$p_tarname, index='$p_index', path=$p_path, remove_path='$p_remove_path', mode='$p_mode'");
508                $v_result = 1;
509
510                // ----- Extract the tar format from the extension
511                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
512                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
513                                // ----- Return
514                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
515
516                                return 0;
517                        }
518                }
519
520                // ----- Look if the $p_index is really an integer
521                if (is_integer($p_index)) {
522                        // ----- Call the extracting fct
523                        if (($v_result = PclTarHandleExtractByIndexList($p_tarname, "$p_index", $p_list, $p_path, $p_remove_path,
524                                        $p_mode)) != 1
525                        ) {
526                                TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
527
528                                return (0);
529                        }
530                } // ----- Look if the $p_filelist is a string
531                else {
532                        if (is_string($p_index)) {
533                                // ----- Call the extracting fct
534                                if (($v_result = PclTarHandleExtractByIndexList($p_tarname, $p_index, $p_list, $p_path, $p_remove_path,
535                                                $p_mode)) != 1
536                                ) {
537                                        TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
538
539                                        return (0);
540                                }
541                        } // ----- Invalid variable
542                        else {
543                                // ----- Error log
544                                PclErrorLog(-3, "Invalid variable type $p_index");
545
546                                // ----- Return
547                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
548
549                                return 0;
550                        }
551                }
552
553                // ----- Return
554                TrFctEnd(__FILE__, __LINE__, $p_list);
555
556                return $p_list;
557        }
558
559        // --------------------------------------------------------------------------------
560
561        // --------------------------------------------------------------------------------
562        // Function : PclTarDelete()
563        // Description :
564        //   This function deletes from the archive $p_tarname the files which are listed
565        //   in $p_filelist. $p_filelist can be a string with file names separated by
566        //   spaces, or an array containing the file names.
567        // Parameters :
568        //   $p_tarname : Name of an existing tar file
569        //   $p_filelist : An array or a string containing file names to remove from the
570        //                 archive.
571        //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
572        // Return Values :
573        //   List of the files which are kept in the archive (same format as PclTarList())
574        // --------------------------------------------------------------------------------
575        function PclTarDelete($p_tarname, $p_filelist, $p_mode = "") {
576                TrFctStart(__FILE__, __LINE__, "PclTarDelete", "tar='$p_tarname', list='$p_filelist', mode='$p_mode'");
577                $v_result = 1;
578
579                // ----- Extract the tar format from the extension
580                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
581                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
582                                // ----- Return
583                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
584
585                                return 0;
586                        }
587                }
588
589                // ----- Look if the $p_filelist is really an array
590                if (is_array($p_filelist)) {
591                        // ----- Call the extracting fct
592                        if (($v_result = PclTarHandleDelete($p_tarname, $p_filelist, $p_list, $p_mode)) != 1) {
593                                TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
594
595                                return (0);
596                        }
597                } // ----- Look if the $p_filelist is a string
598                else {
599                        if (is_string($p_filelist)) {
600                                // ----- Create a list with the elements from the string
601                                $v_list = explode(" ", $p_filelist);
602
603                                // ----- Call the extracting fct
604                                if (($v_result = PclTarHandleDelete($p_tarname, $v_list, $p_list, $p_mode)) != 1) {
605                                        TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
606
607                                        return (0);
608                                }
609                        } // ----- Invalid variable
610                        else {
611                                // ----- Error log
612                                PclErrorLog(-3, "Invalid variable type p_filelist");
613
614                                // ----- Return
615                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
616
617                                return 0;
618                        }
619                }
620
621                // ----- Return
622                TrFctEnd(__FILE__, __LINE__, $p_list);
623
624                return $p_list;
625        }
626
627        // --------------------------------------------------------------------------------
628
629        // --------------------------------------------------------------------------------
630        // Function : PclTarUpdate()
631        // Description :
632        //   This function updates the files in $p_filelist which are already in the
633        //   $p_tarname archive with an older last modified date. If the file does not
634        //   exist, it is added at the end of the archive.
635        // Parameters :
636        //   $p_tarname : Name of an existing tar file
637        //   $p_filelist : An array or a string containing file names to update from the
638        //                 archive.
639        //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
640        // Return Values :
641        //   List of the files contained in the archive. The field status contains
642        //   "updated", "not_updated", "added" or "ok" for the files not concerned.
643        // --------------------------------------------------------------------------------
644        function PclTarUpdate($p_tarname, $p_filelist, $p_mode = "", $p_add_dir = "", $p_remove_dir = "") {
645                TrFctStart(__FILE__, __LINE__, "PclTarUpdate", "tar='$p_tarname', list='$p_filelist', mode='$p_mode'");
646                $v_result = 1;
647
648                // ----- Extract the tar format from the extension
649                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
650                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
651                                // ----- Return
652                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
653
654                                return 0;
655                        }
656                }
657
658                // ----- Look if the $p_filelist is really an array
659                if (is_array($p_filelist)) {
660                        // ----- Call the extracting fct
661                        if (($v_result = PclTarHandleUpdate($p_tarname, $p_filelist, $p_list, $p_mode, $p_add_dir, $p_remove_dir)) != 1) {
662                                TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
663
664                                return (0);
665                        }
666                } // ----- Look if the $p_filelist is a string
667                else {
668                        if (is_string($p_filelist)) {
669                                // ----- Create a list with the elements from the string
670                                $v_list = explode(" ", $p_filelist);
671
672                                // ----- Call the extracting fct
673                                if (($v_result = PclTarHandleUpdate($p_tarname, $v_list, $p_list, $p_mode, $p_add_dir, $p_remove_dir)) != 1) {
674                                        TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
675
676                                        return (0);
677                                }
678                        } // ----- Invalid variable
679                        else {
680                                // ----- Error log
681                                PclErrorLog(-3, "Invalid variable type p_filelist");
682
683                                // ----- Return
684                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
685
686                                return 0;
687                        }
688                }
689
690                // ----- Return
691                TrFctEnd(__FILE__, __LINE__, $p_list);
692
693                return $p_list;
694        }
695
696        // --------------------------------------------------------------------------------
697
698
699        // --------------------------------------------------------------------------------
700        // Function : PclTarMerge()
701        // Description :
702        //   This function add the content of $p_tarname_add at the end of $p_tarname.
703        // Parameters :
704        //   $p_tarname : Name of an existing tar file
705        //   $p_tarname_add : Name of an existing tar file taht will be added at the end
706        //                    of $p_tarname.
707        //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
708        //   $p_mode_add : 'tar' or 'tgz', if not set, will be determined by $p_tarname_add
709        //                 extension
710        // Return Values :
711        //   List of the files contained in the archive. The field status contains
712        //   "updated", "not_updated", "added" or "ok" for the files not concerned.
713        // --------------------------------------------------------------------------------
714        function PclTarMerge($p_tarname, $p_tarname_add, $p_mode = "", $p_mode_add = "") {
715                TrFctStart(__FILE__, __LINE__, "PclTarMerge",
716                        "tar='$p_tarname', tar_add='$p_tarname_add', mode='$p_mode', mode_add='$p_mode_add'");
717                $v_result = 1;
718
719                // ----- Check the parameters
720                if (($p_tarname == "") || ($p_tarname_add == "")) {
721                        // ----- Error log
722                        PclErrorLog(-3, "Invalid empty archive name");
723
724                        // ----- Return
725                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
726
727                        return PclErrorCode();
728                }
729
730                // ----- Extract the tar format from the extension
731                if (($p_mode == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
732                        if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
733                                // ----- Return
734                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
735
736                                return 0;
737                        }
738                }
739                if (($p_mode_add == "") || (($p_mode_add != "tar") && ($p_mode_add != "tgz"))) {
740                        if (($p_mode_add = PclTarHandleExtension($p_tarname_add)) == "") {
741                                // ----- Return
742                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
743
744                                return 0;
745                        }
746                }
747
748                // ----- Clear filecache
749                clearstatcache();
750
751                // ----- Check the file size
752                if ((!is_file($p_tarname)) ||
753                        (((($v_size = filesize($p_tarname)) % 512) != 0) && ($p_mode == "tar"))
754                ) {
755                        // ----- Error log
756                        if (!is_file($p_tarname)) {
757                                PclErrorLog(-4, "Archive '$p_tarname' does not exist");
758                        } else {
759                                PclErrorLog(-6, "Archive '$p_tarname' has invalid size " . filesize($p_tarname) . "(not a 512 block multiple)");
760                        }
761
762                        // ----- Return
763                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
764
765                        return PclErrorCode();
766                }
767                if ((!is_file($p_tarname_add)) ||
768                        (((($v_size_add = filesize($p_tarname_add)) % 512) != 0) && ($p_mode_add == "tar"))
769                ) {
770                        // ----- Error log
771                        if (!is_file($p_tarname_add)) {
772                                PclErrorLog(-4, "Archive '$p_tarname_add' does not exist");
773                        } else {
774                                PclErrorLog(-6,
775                                        "Archive '$p_tarname_add' has invalid size " . filesize($p_tarname_add) . "(not a 512 block multiple)");
776                        }
777
778                        // ----- Return
779                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
780
781                        return PclErrorCode();
782                }
783
784                // ----- Look for compressed archive
785                if ($p_mode == "tgz") {
786                        // ----- Open the file in read mode
787                        if (($p_tar = @gzopen($p_tarname, "rb")) == 0) {
788                                // ----- Error log
789                                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
790
791                                // ----- Return
792                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
793
794                                return PclErrorCode();
795                        }
796
797                        // ----- Open a temporary file in write mode
798                        $v_temp_tarname = uniqid("pcltar-") . ".tmp";
799                        TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
800                        if (($v_temp_tar = @gzopen($v_temp_tarname, "wb")) == 0) {
801                                // ----- Close tar file
802                                gzclose($p_tar);
803
804                                // ----- Error log
805                                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
806
807                                // ----- Return
808                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
809
810                                return PclErrorCode();
811                        }
812
813                        // ----- Read the first 512 bytes block
814                        $v_buffer = gzread($p_tar, 512);
815
816                        // ----- Read the following blocks but not the last one
817                        if (!gzeof($p_tar)) {
818                                TrFctMessage(__FILE__, __LINE__, 3, "More than one 512 block file");
819                                $i = 1;
820
821                                // ----- Read new 512 block and write the already read
822                                do {
823                                        // ----- Write the already read block
824                                        $v_binary_data = pack("a512", "$v_buffer");
825                                        gzputs($v_temp_tar, $v_binary_data);
826
827                                        $i++;
828                                        TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
829
830                                        // ----- Read next block
831                                        $v_buffer = gzread($p_tar, 512);
832
833                                } while (!gzeof($p_tar));
834
835                                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
836                        }
837                } // ----- Look for uncompressed tar file
838                else {
839                        if ($p_mode == "tar") {
840                                // ----- Open the tar file
841                                if (($p_tar = fopen($p_tarname, "r+b")) == 0) {
842                                        // ----- Error log
843                                        PclErrorLog(-1, "Unable to open file '$p_tarname' in binary write mode");
844
845                                        // ----- Return
846                                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
847
848                                        return PclErrorCode();
849                                }
850
851                                // ----- Go to the beginning of last block
852                                TrFctMessage(__FILE__, __LINE__, 4, "Position before :" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
853                                fseek($p_tar, $v_size - 512);
854                                TrFctMessage(__FILE__, __LINE__, 4, "Position after :" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
855                        } // ----- Look for unknown type
856                        else {
857                                // ----- Error log
858                                PclErrorLog(-3, "Invalid tar mode $p_mode");
859
860                                // ----- Return
861                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
862
863                                return PclErrorCode();
864                        }
865                }
866
867                // ----- Look for type of archive to add
868                if ($p_mode_add == "tgz") {
869                        TrFctMessage(__FILE__, __LINE__, 4, "Opening file $p_tarname_add");
870
871                        // ----- Open the file in read mode
872                        if (($p_tar_add = @gzopen($p_tarname_add, "rb")) == 0) {
873                                // ----- Error log
874                                PclErrorLog(-2, "Unable to open file '$p_tarname_add' in binary read mode");
875
876                                // ----- Return
877                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
878
879                                return PclErrorCode();
880                        }
881
882                        // ----- Read the first 512 bytes block
883                        $v_buffer = gzread($p_tar_add, 512);
884
885                        // ----- Read the following blocks but not the last one
886                        if (!gzeof($p_tar_add)) {
887                                TrFctMessage(__FILE__, __LINE__, 3, "More than one 512 block file");
888                                $i = 1;
889
890                                // ----- Read new 512 block and write the already read
891                                do {
892                                        // ----- Write the already read block
893                                        $v_binary_data = pack("a512", "$v_buffer");
894                                        if ($p_mode == "tar") {
895                                                fputs($p_tar, $v_binary_data);
896                                        } else {
897                                                gzputs($v_temp_tar, $v_binary_data);
898                                        }
899
900                                        $i++;
901                                        TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
902
903                                        // ----- Read next block
904                                        $v_buffer = gzread($p_tar_add, 512);
905
906                                } while (!gzeof($p_tar_add));
907
908                                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
909                        }
910
911                        // ----- Close the files
912                        gzclose($p_tar_add);
913                } // ----- Look for uncompressed tar file
914                else {
915                        if ($p_mode == "tar") {
916                                // ----- Open the file in read mode
917                                if (($p_tar_add = @fopen($p_tarname_add, "rb")) == 0) {
918                                        // ----- Error log
919                                        PclErrorLog(-2, "Unable to open file '$p_tarname_add' in binary read mode");
920
921                                        // ----- Return
922                                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
923
924                                        return PclErrorCode();
925                                }
926
927                                // ----- Read the first 512 bytes block
928                                $v_buffer = fread($p_tar_add, 512);
929
930                                // ----- Read the following blocks but not the last one
931                                if (!feof($p_tar_add)) {
932                                        TrFctMessage(__FILE__, __LINE__, 3, "More than one 512 block file");
933                                        $i = 1;
934
935                                        // ----- Read new 512 block and write the already read
936                                        do {
937                                                // ----- Write the already read block
938                                                $v_binary_data = pack("a512", "$v_buffer");
939                                                if ($p_mode == "tar") {
940                                                        fputs($p_tar, $v_binary_data);
941                                                } else {
942                                                        gzputs($v_temp_tar, $v_binary_data);
943                                                }
944
945                                                $i++;
946                                                TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
947
948                                                // ----- Read next block
949                                                $v_buffer = fread($p_tar_add, 512);
950
951                                        } while (!feof($p_tar_add));
952
953                                        TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
954                                }
955
956                                // ----- Close the files
957                                fclose($p_tar_add);
958                        }
959                }
960
961                // ----- Call the footer of the tar archive
962                $v_result = PclTarHandleFooter($p_tar, $p_mode);
963
964                // ----- Look for closing compressed archive
965                if ($p_mode == "tgz") {
966                        // ----- Close the files
967                        gzclose($p_tar);
968                        gzclose($v_temp_tar);
969
970                        // ----- Unlink tar file
971                        if (!@unlink($p_tarname)) {
972                                // ----- Error log
973                                PclErrorLog(-11, "Error while deleting archive name $p_tarname");
974                        }
975
976                        // ----- Rename tar file
977                        if (!@rename($v_temp_tarname, $p_tarname)) {
978                                // ----- Error log
979                                PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
980
981                                // ----- Return
982                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
983
984                                return PclErrorCode();
985                        }
986
987                        // ----- Return
988                        TrFctEnd(__FILE__, __LINE__, $v_result);
989
990                        return $v_result;
991                } // ----- Look for closing uncompressed tar file
992                else {
993                        if ($p_mode == "tar") {
994                                // ----- Close the tarfile
995                                fclose($p_tar);
996                        }
997                }
998
999                // ----- Return
1000                TrFctEnd(__FILE__, __LINE__, $v_result);
1001
1002                return $v_result;
1003        }
1004
1005        // --------------------------------------------------------------------------------
1006
1007
1008// --------------------------------------------------------------------------------
1009// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1010// *****                                                        *****
1011// *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       *****
1012// --------------------------------------------------------------------------------
1013
1014
1015        // --------------------------------------------------------------------------------
1016        // Function : PclTarHandleCreate()
1017        // Description :
1018        // Parameters :
1019        //   $p_tarname : Name of the tar file
1020        //   $p_list : An array containing the file or directory names to add in the tar
1021        //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1022        // Return Values :
1023        // --------------------------------------------------------------------------------
1024        function PclTarHandleCreate($p_tarname, $p_list, $p_mode, $p_add_dir = "", $p_remove_dir = "") {
1025                TrFctStart(__FILE__, __LINE__, "PclTarHandleCreate",
1026                        "tar=$p_tarname, list, mode=$p_mode, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1027                $v_result = 1;
1028                $v_list_detail = array();
1029
1030                // ----- Check the parameters
1031                if (($p_tarname == "") || (($p_mode != "tar") && ($p_mode != "tgz"))) {
1032                        // ----- Error log
1033                        if ($p_tarname == "") {
1034                                PclErrorLog(-3, "Invalid empty archive name");
1035                        } else {
1036                                PclErrorLog(-3, "Unknown mode '$p_mode'");
1037                        }
1038
1039                        // ----- Return
1040                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1041
1042                        return PclErrorCode();
1043                }
1044
1045                // ----- Look for tar file
1046                if ($p_mode == "tar") {
1047                        // ----- Open the tar file
1048                        if (($p_tar = fopen($p_tarname, "wb")) == 0) {
1049                                // ----- Error log
1050                                PclErrorLog(-1, "Unable to open file [$p_tarname] in binary write mode");
1051
1052                                // ----- Return
1053                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1054
1055                                return PclErrorCode();
1056                        }
1057
1058                        // ----- Call the adding fct inside the tar
1059                        if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir)) == 1) {
1060                                // ----- Call the footer of the tar archive
1061                                $v_result = PclTarHandleFooter($p_tar, $p_mode);
1062                        }
1063
1064                        // ----- Close the tarfile
1065                        fclose($p_tar);
1066                } // ----- Look for tgz file
1067                else {
1068                        // ----- Open the tar file
1069                        if (($p_tar = @gzopen($p_tarname, "wb")) == 0) {
1070                                // ----- Error log
1071                                PclErrorLog(-1, "Unable to open file [$p_tarname] in binary write mode");
1072
1073                                // ----- Return
1074                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1075
1076                                return PclErrorCode();
1077                        }
1078
1079                        // ----- Call the adding fct inside the tar
1080                        if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir)) == 1) {
1081                                // ----- Call the footer of the tar archive
1082                                $v_result = PclTarHandleFooter($p_tar, $p_mode);
1083                        }
1084
1085                        // ----- Close the tarfile
1086                        gzclose($p_tar);
1087                }
1088
1089                // ----- Return
1090                TrFctEnd(__FILE__, __LINE__, $v_result);
1091
1092                return $v_result;
1093        }
1094
1095        // --------------------------------------------------------------------------------
1096
1097        // --------------------------------------------------------------------------------
1098        // Function : PclTarHandleAppend()
1099        // Description :
1100        // Parameters :
1101        //   $p_tarname : Name of the tar file
1102        //   $p_list : An array containing the file or directory names to add in the tar
1103        //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1104        // Return Values :
1105        // --------------------------------------------------------------------------------
1106        function PclTarHandleAppend($p_tarname, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir) {
1107                TrFctStart(__FILE__, __LINE__, "PclTarHandleAppend", "tar=$p_tarname, list, mode=$p_mode");
1108                $v_result = 1;
1109
1110                // ----- Check the parameters
1111                if ($p_tarname == "") {
1112                        // ----- Error log
1113                        PclErrorLog(-3, "Invalid empty archive name");
1114
1115                        // ----- Return
1116                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1117
1118                        return PclErrorCode();
1119                }
1120
1121                clearstatcache();
1122
1123                // ----- Check the file size
1124                if ((!is_file($p_tarname)) ||
1125                        (((($v_size = filesize($p_tarname)) % 512) != 0) && ($p_mode == "tar"))
1126                ) {
1127                        // ----- Error log
1128                        if (!is_file($p_tarname)) {
1129                                PclErrorLog(-4, "Archive '$p_tarname' does not exist");
1130                        } else {
1131                                PclErrorLog(-6, "Archive '$p_tarname' has invalid size " . filesize($p_tarname) . "(not a 512 block multiple)");
1132                        }
1133
1134                        // ----- Return
1135                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1136
1137                        return PclErrorCode();
1138                }
1139
1140                // ----- Look for compressed archive
1141                if ($p_mode == "tgz") {
1142                        // ----- Open the file in read mode
1143                        if (($p_tar = @gzopen($p_tarname, "rb")) == 0) {
1144                                // ----- Error log
1145                                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
1146
1147                                // ----- Return
1148                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1149
1150                                return PclErrorCode();
1151                        }
1152
1153                        // ----- Open a temporary file in write mode
1154                        $v_temp_tarname = uniqid("pcltar-") . ".tmp";
1155                        TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
1156                        if (($v_temp_tar = @gzopen($v_temp_tarname, "wb")) == 0) {
1157                                // ----- Close tar file
1158                                gzclose($p_tar);
1159
1160                                // ----- Error log
1161                                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
1162
1163                                // ----- Return
1164                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1165
1166                                return PclErrorCode();
1167                        }
1168
1169                        // ----- Read the first 512 bytes block
1170                        $v_buffer = gzread($p_tar, 512);
1171
1172                        // ----- Read the following blocks but not the last one
1173                        if (!gzeof($p_tar)) {
1174                                TrFctMessage(__FILE__, __LINE__, 3, "More than one 512 block file");
1175                                $i = 1;
1176
1177                                // ----- Read new 512 block and write the already read
1178                                do {
1179                                        // ----- Write the already read block
1180                                        $v_binary_data = pack("a512", "$v_buffer");
1181                                        gzputs($v_temp_tar, $v_binary_data);
1182
1183                                        $i++;
1184                                        TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
1185
1186                                        // ----- Read next block
1187                                        $v_buffer = gzread($p_tar, 512);
1188
1189                                } while (!gzeof($p_tar));
1190
1191                                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
1192                        }
1193
1194                        // ----- Call the adding fct inside the tar
1195                        if (($v_result = PclTarHandleAddList($v_temp_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir,
1196                                        $p_remove_dir)) == 1
1197                        ) {
1198                                // ----- Call the footer of the tar archive
1199                                $v_result = PclTarHandleFooter($v_temp_tar, $p_mode);
1200                        }
1201
1202                        // ----- Close the files
1203                        gzclose($p_tar);
1204                        gzclose($v_temp_tar);
1205
1206                        // ----- Unlink tar file
1207                        if (!@unlink($p_tarname)) {
1208                                // ----- Error log
1209                                PclErrorLog(-11, "Error while deleting archive name $p_tarname");
1210                        }
1211
1212                        // ----- Rename tar file
1213                        if (!@rename($v_temp_tarname, $p_tarname)) {
1214                                // ----- Error log
1215                                PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
1216
1217                                // ----- Return
1218                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1219
1220                                return PclErrorCode();
1221                        }
1222
1223                        // ----- Return
1224                        TrFctEnd(__FILE__, __LINE__, $v_result);
1225
1226                        return $v_result;
1227                } // ----- Look for uncompressed tar file
1228                else {
1229                        if ($p_mode == "tar") {
1230                                // ----- Open the tar file
1231                                if (($p_tar = fopen($p_tarname, "r+b")) == 0) {
1232                                        // ----- Error log
1233                                        PclErrorLog(-1, "Unable to open file '$p_tarname' in binary write mode");
1234
1235                                        // ----- Return
1236                                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1237
1238                                        return PclErrorCode();
1239                                }
1240
1241                                // ----- Go to the beginning of last block
1242                                TrFctMessage(__FILE__, __LINE__, 4, "Position before :" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
1243                                fseek($p_tar, $v_size - 512);
1244                                TrFctMessage(__FILE__, __LINE__, 4, "Position after :" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
1245
1246                                // ----- Call the adding fct inside the tar
1247                                if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir,
1248                                                $p_remove_dir)) == 1
1249                                ) {
1250                                        // ----- Call the footer of the tar archive
1251                                        $v_result = PclTarHandleFooter($p_tar, $p_mode);
1252                                }
1253
1254                                // ----- Close the tarfile
1255                                fclose($p_tar);
1256                        } // ----- Look for unknown type
1257                        else {
1258                                // ----- Error log
1259                                PclErrorLog(-3, "Invalid tar mode $p_mode");
1260
1261                                // ----- Return
1262                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1263
1264                                return PclErrorCode();
1265                        }
1266                }
1267
1268                // ----- Return
1269                TrFctEnd(__FILE__, __LINE__, $v_result);
1270
1271                return $v_result;
1272        }
1273
1274        // --------------------------------------------------------------------------------
1275
1276        // --------------------------------------------------------------------------------
1277        // Function : PclTarHandleAddList()
1278        // Description :
1279        //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
1280        //   different from the real path of the file. This is usefull if you want to have PclTar
1281        //   running in any directory, and memorize relative path from an other directory.
1282        // Parameters :
1283        //   $p_tar : File descriptor of the tar archive
1284        //   $p_list : An array containing the file or directory names to add in the tar
1285        //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1286        //   $p_list_detail : list of added files with their properties (specially the status field)
1287        //   $p_add_dir : Path to add in the filename path archived
1288        //   $p_remove_dir : Path to remove in the filename path archived
1289        // Return Values :
1290        // --------------------------------------------------------------------------------
1291        function PclTarHandleAddList($p_tar, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir) {
1292                TrFctStart(__FILE__, __LINE__, "PclTarHandleAddList",
1293                        "tar='$p_tar', list, mode='$p_mode', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1294                $v_result = 1;
1295                $v_header = array();
1296
1297                // ----- Recuperate the current number of elt in list
1298                $v_nb = sizeof($p_list_detail);
1299
1300                // ----- Check the parameters
1301                if ($p_tar == 0) {
1302                        // ----- Error log
1303                        PclErrorLog(-3, "Invalid file descriptor in file " . __FILE__ . ", line " . __LINE__);
1304
1305                        // ----- Return
1306                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1307
1308                        return PclErrorCode();
1309                }
1310
1311                // ----- Check the arguments
1312                if (sizeof($p_list) == 0) {
1313                        // ----- Error log
1314                        PclErrorLog(-3, "Invalid file list parameter (invalid or empty list)");
1315
1316                        // ----- Return
1317                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1318
1319                        return PclErrorCode();
1320                }
1321
1322                // ----- Loop on the files
1323                for ($j = 0; ($j < count($p_list)) && ($v_result == 1); $j++) {
1324                        // ----- Recuperate the filename
1325                        $p_filename = $p_list[$j];
1326
1327                        TrFctMessage(__FILE__, __LINE__, 2, "Looking for file [$p_filename]");
1328
1329                        // ----- Skip empty file names
1330                        if ($p_filename == "") {
1331                                TrFctMessage(__FILE__, __LINE__, 2, "Skip empty filename");
1332                                continue;
1333                        }
1334
1335                        // ----- Check the filename
1336                        if (!file_exists($p_filename)) {
1337                                // ----- Error log
1338                                TrFctMessage(__FILE__, __LINE__, 2, "File '$p_filename' does not exists");
1339                                PclErrorLog(-4, "File '$p_filename' does not exists");
1340
1341                                // ----- Return
1342                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1343
1344                                return PclErrorCode();
1345                        }
1346
1347                        // ----- Check the path length
1348                        if (strlen($p_filename) > 99) {
1349                                // ----- Error log
1350                                PclErrorLog(-5, "File name is too long (max. 99) : '$p_filename'");
1351
1352                                // ----- Return
1353                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1354
1355                                return PclErrorCode();
1356                        }
1357
1358                        TrFctMessage(__FILE__, __LINE__, 4,
1359                                "File position before header =" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
1360
1361                        // ----- Add the file
1362                        if (($v_result = PclTarHandleAddFile($p_tar, $p_filename, $p_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1) {
1363                                // ----- Return status
1364                                TrFctEnd(__FILE__, __LINE__, $v_result);
1365
1366                                return $v_result;
1367                        }
1368
1369                        // ----- Store the file infos
1370                        $p_list_detail[$v_nb++] = $v_header;
1371
1372                        // ----- Look for directory
1373                        if (is_dir($p_filename)) {
1374                                TrFctMessage(__FILE__, __LINE__, 2, "$p_filename is a directory");
1375
1376                                // ----- Look for path
1377                                if ($p_filename != ".") {
1378                                        $v_path = $p_filename . "/";
1379                                } else {
1380                                        $v_path = "";
1381                                }
1382
1383                                // ----- Read the directory for files and sub-directories
1384                                $p_hdir = opendir($p_filename);
1385                                $p_hitem = readdir($p_hdir); // '.' directory
1386                                $p_hitem = readdir($p_hdir); // '..' directory
1387                                while ($p_hitem = readdir($p_hdir)) {
1388                                        // ----- Look for a file
1389                                        if (is_file($v_path . $p_hitem)) {
1390                                                TrFctMessage(__FILE__, __LINE__, 4, "Add the file '" . $v_path . $p_hitem . "'");
1391
1392                                                // ----- Add the file
1393                                                if (($v_result = PclTarHandleAddFile($p_tar, $v_path . $p_hitem, $p_mode, $v_header, $p_add_dir,
1394                                                                $p_remove_dir)) != 1
1395                                                ) {
1396                                                        // ----- Return status
1397                                                        TrFctEnd(__FILE__, __LINE__, $v_result);
1398
1399                                                        return $v_result;
1400                                                }
1401
1402                                                // ----- Store the file infos
1403                                                $p_list_detail[$v_nb++] = $v_header;
1404                                        } // ----- Recursive call to PclTarHandleAddFile()
1405                                        else {
1406                                                TrFctMessage(__FILE__, __LINE__, 4, "'" . $v_path . $p_hitem . "' is a directory");
1407
1408                                                // ----- Need an array as parameter
1409                                                $p_temp_list[0] = $v_path . $p_hitem;
1410                                                $v_result = PclTarHandleAddList($p_tar, $p_temp_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
1411                                        }
1412                                }
1413
1414                                // ----- Free memory for the recursive loop
1415                                unset($p_temp_list);
1416                                unset($p_hdir);
1417                                unset($p_hitem);
1418                        } else {
1419                                TrFctMessage(__FILE__, __LINE__, 4,
1420                                        "File position after blocks =" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
1421                        }
1422                }
1423
1424                // ----- Return
1425                TrFctEnd(__FILE__, __LINE__, $v_result);
1426
1427                return $v_result;
1428        }
1429
1430        // --------------------------------------------------------------------------------
1431
1432        // --------------------------------------------------------------------------------
1433        // Function : PclTarHandleAddFile()
1434        // Description :
1435        // Parameters :
1436        // Return Values :
1437        // --------------------------------------------------------------------------------
1438        function PclTarHandleAddFile($p_tar, $p_filename, $p_mode, &$p_header, $p_add_dir, $p_remove_dir) {
1439                TrFctStart(__FILE__, __LINE__, "PclTarHandleAddFile",
1440                        "tar='$p_tar', filename='$p_filename', p_mode='$p_mode', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1441                $v_result = 1;
1442
1443                // ----- Check the parameters
1444                if ($p_tar == 0) {
1445                        // ----- Error log
1446                        PclErrorLog(-3, "Invalid file descriptor in file " . __FILE__ . ", line " . __LINE__);
1447
1448                        // ----- Return
1449                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1450
1451                        return PclErrorCode();
1452                }
1453
1454                // ----- Skip empty file names
1455                if ($p_filename == "") {
1456                        // ----- Error log
1457                        PclErrorLog(-3, "Invalid file list parameter (invalid or empty list)");
1458
1459                        // ----- Return
1460                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1461
1462                        return PclErrorCode();
1463                }
1464
1465                // ----- Calculate the stored filename
1466                $v_stored_filename = $p_filename;
1467                if ($p_remove_dir != "") {
1468                        if (substr($p_remove_dir, -1) != '/') {
1469                                $p_remove_dir .= "/";
1470                        }
1471
1472                        if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./")) {
1473                                if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./")) {
1474                                        $p_remove_dir = "./" . $p_remove_dir;
1475                                }
1476                                if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./")) {
1477                                        $p_remove_dir = substr($p_remove_dir, 2);
1478                                }
1479                        }
1480
1481                        if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) {
1482                                $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
1483                                TrFctMessage(__FILE__, __LINE__, 3, "Remove path '$p_remove_dir' in file '$p_filename' = '$v_stored_filename'");
1484                        }
1485                }
1486                if ($p_add_dir != "") {
1487                        if (substr($p_add_dir, -1) == "/") {
1488                                $v_stored_filename = $p_add_dir . $v_stored_filename;
1489                        } else {
1490                                $v_stored_filename = $p_add_dir . "/" . $v_stored_filename;
1491                        }
1492                        TrFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
1493                }
1494
1495                // ----- Check the path length
1496                if (strlen($v_stored_filename) > 99) {
1497                        // ----- Error log
1498                        PclErrorLog(-5, "Stored file name is too long (max. 99) : '$v_stored_filename'");
1499
1500                        // ----- Return
1501                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1502
1503                        return PclErrorCode();
1504                }
1505
1506                // ----- Look for a file
1507                if (is_file($p_filename)) {
1508                        // ----- Open the source file
1509                        if (($v_file = fopen($p_filename, "rb")) == 0) {
1510                                // ----- Error log
1511                                PclErrorLog(-2, "Unable to open file '$p_filename' in binary read mode");
1512
1513                                // ----- Return
1514                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1515
1516                                return PclErrorCode();
1517                        }
1518
1519                        // ----- Call the header generation
1520                        if (($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename)) != 1) {
1521                                // ----- Return status
1522                                TrFctEnd(__FILE__, __LINE__, $v_result);
1523
1524                                return $v_result;
1525                        }
1526
1527                        TrFctMessage(__FILE__, __LINE__, 4,
1528                                "File position after header =" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
1529
1530                        // ----- Read the file by 512 octets blocks
1531                        $i = 0;
1532                        while (($v_buffer = fread($v_file, 512)) != "") {
1533                                $v_binary_data = pack("a512", "$v_buffer");
1534                                if ($p_mode == "tar") {
1535                                        fputs($p_tar, $v_binary_data);
1536                                } else {
1537                                        gzputs($p_tar, $v_binary_data);
1538                                }
1539                                $i++;
1540                        }
1541                        TrFctMessage(__FILE__, __LINE__, 2, "$i 512 bytes blocks");
1542
1543                        // ----- Close the file
1544                        fclose($v_file);
1545
1546                        TrFctMessage(__FILE__, __LINE__, 4,
1547                                "File position after blocks =" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
1548                } // ----- Look for a directory
1549                else {
1550                        // ----- Call the header generation
1551                        if (($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename)) != 1) {
1552                                // ----- Return status
1553                                TrFctEnd(__FILE__, __LINE__, $v_result);
1554
1555                                return $v_result;
1556                        }
1557
1558                        TrFctMessage(__FILE__, __LINE__, 4,
1559                                "File position after header =" . ($p_mode == "tar" ? ftell($p_tar) : gztell($p_tar)));
1560                }
1561
1562                // ----- Return
1563                TrFctEnd(__FILE__, __LINE__, $v_result);
1564
1565                return $v_result;
1566        }
1567
1568        // --------------------------------------------------------------------------------
1569
1570        // --------------------------------------------------------------------------------
1571        // Function : PclTarHandleHeader()
1572        // Description :
1573        //   This function creates in the TAR $p_tar, the TAR header for the file
1574        //   $p_filename.
1575        //
1576        //   1. The informations needed to compose the header are recuperated and formatted
1577        //   2. Two binary strings are composed for the first part of the header, before
1578        //      and after checksum field.
1579        //   3. The checksum is calculated from the two binary strings
1580        //   4. The header is write in the tar file (first binary string, binary string
1581        //      for checksum and last binary string).
1582        // Parameters :
1583        //   $p_tar : a valid file descriptor, opened in write mode,
1584        //   $p_filename : The name of the file the header is for,
1585        //   $p_mode : The mode of the archive ("tar" or "tgz").
1586        //   $p_header : A pointer to a array where will be set the file properties
1587        // Return Values :
1588        // --------------------------------------------------------------------------------
1589        function PclTarHandleHeader($p_tar, $p_filename, $p_mode, &$p_header, $p_stored_filename) {
1590                TrFctStart(__FILE__, __LINE__, "PclTarHandleHeader",
1591                        "tar=$p_tar, file='$p_filename', mode='$p_mode', stored_filename='$p_stored_filename'");
1592                $v_result = 1;
1593
1594                // ----- Check the parameters
1595                if (($p_tar == 0) || ($p_filename == "")) {
1596                        // ----- Error log
1597                        PclErrorLog(-3, "Invalid file descriptor in file " . __FILE__ . ", line " . __LINE__);
1598
1599                        // ----- Return
1600                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1601
1602                        return PclErrorCode();
1603                }
1604
1605                // ----- Filename (reduce the path of stored name)
1606                if ($p_stored_filename == "") {
1607                        $p_stored_filename = $p_filename;
1608                }
1609                $v_reduce_filename = PclTarHandlePathReduction($p_stored_filename);
1610                TrFctMessage(__FILE__, __LINE__, 2,
1611                        "Filename (reduced) '$v_reduce_filename', strlen " . strlen($v_reduce_filename));
1612
1613                // ----- Get file info
1614                $v_info = stat($p_filename);
1615                $v_uid = sprintf("%6s ", DecOct($v_info[4]));
1616                $v_gid = sprintf("%6s ", DecOct($v_info[5]));
1617                TrFctMessage(__FILE__, __LINE__, 3, "uid=$v_uid, gid=$v_gid");
1618                $v_perms = sprintf("%6s ", DecOct(fileperms($p_filename)));
1619                TrFctMessage(__FILE__, __LINE__, 3, "file permissions $v_perms");
1620
1621                // ----- File mtime
1622                $v_mtime_data = filemtime($p_filename);
1623                TrFctMessage(__FILE__, __LINE__, 2, "File mtime : $v_mtime_data");
1624                $v_mtime = sprintf("%11s", DecOct($v_mtime_data));
1625
1626                // ----- File typeflag
1627                // '0' or '\0' is the code for regular file
1628                // '5' is directory
1629                if (is_dir($p_filename)) {
1630                        $v_typeflag = "5";
1631                        $v_size = 0;
1632                } else {
1633                        $v_typeflag = "";
1634
1635                        // ----- Get the file size
1636                        clearstatcache();
1637                        $v_size = filesize($p_filename);
1638                }
1639
1640                TrFctMessage(__FILE__, __LINE__, 2, "File size : $v_size");
1641                $v_size = sprintf("%11s ", DecOct($v_size));
1642
1643                TrFctMessage(__FILE__, __LINE__, 2, "File typeflag : $v_typeflag");
1644
1645                // ----- Linkname
1646                $v_linkname = "";
1647
1648                // ----- Magic
1649                $v_magic = "";
1650
1651                // ----- Version
1652                $v_version = "";
1653
1654                // ----- uname
1655                $v_uname = "";
1656
1657                // ----- gname
1658                $v_gname = "";
1659
1660                // ----- devmajor
1661                $v_devmajor = "";
1662
1663                // ----- devminor
1664                $v_devminor = "";
1665
1666                // ----- prefix
1667                $v_prefix = "";
1668
1669                // ----- Compose the binary string of the header in two parts arround the checksum position
1670                $v_binary_data_first = pack("a100a8a8a8a12A12", $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
1671                $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname,
1672                        $v_gname, $v_devmajor, $v_devminor, $v_prefix, "");
1673
1674                // ----- Calculate the checksum
1675                $v_checksum = 0;
1676                // ..... First part of the header
1677                for ($i = 0; $i < 148; $i++) {
1678                        $v_checksum += ord(substr($v_binary_data_first, $i, 1));
1679                }
1680                // ..... Ignore the checksum value and replace it by ' ' (space)
1681                for ($i = 148; $i < 156; $i++) {
1682                        $v_checksum += ord(' ');
1683                }
1684                // ..... Last part of the header
1685                for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
1686                        $v_checksum += ord(substr($v_binary_data_last, $j, 1));
1687                }
1688                TrFctMessage(__FILE__, __LINE__, 3, "Calculated checksum : $v_checksum");
1689
1690                // ----- Write the first 148 bytes of the header in the archive
1691                if ($p_mode == "tar") {
1692                        fputs($p_tar, $v_binary_data_first, 148);
1693                } else {
1694                        gzputs($p_tar, $v_binary_data_first, 148);
1695                }
1696
1697                // ----- Write the calculated checksum
1698                $v_checksum = sprintf("%6s ", DecOct($v_checksum));
1699                $v_binary_data = pack("a8", $v_checksum);
1700                if ($p_mode == "tar") {
1701                        fputs($p_tar, $v_binary_data, 8);
1702                } else {
1703                        gzputs($p_tar, $v_binary_data, 8);
1704                }
1705
1706                // ----- Write the last 356 bytes of the header in the archive
1707                if ($p_mode == "tar") {
1708                        fputs($p_tar, $v_binary_data_last, 356);
1709                } else {
1710                        gzputs($p_tar, $v_binary_data_last, 356);
1711                }
1712
1713                // ----- Set the properties in the header "structure"
1714                $p_header['filename'] = $v_reduce_filename;
1715                $p_header['mode'] = $v_perms;
1716                $p_header['uid'] = $v_uid;
1717                $p_header['gid'] = $v_gid;
1718                $p_header['size'] = $v_size;
1719                $p_header['mtime'] = $v_mtime;
1720                $p_header['typeflag'] = $v_typeflag;
1721                $p_header['status'] = "added";
1722
1723                // ----- Return
1724                TrFctEnd(__FILE__, __LINE__, $v_result);
1725
1726                return $v_result;
1727        }
1728
1729        // --------------------------------------------------------------------------------
1730
1731        // --------------------------------------------------------------------------------
1732        // Function : PclTarHandleFooter()
1733        // Description :
1734        // Parameters :
1735        // Return Values :
1736        // --------------------------------------------------------------------------------
1737        function PclTarHandleFooter($p_tar, $p_mode) {
1738                TrFctStart(__FILE__, __LINE__, "PclTarHandleFooter", "tar='$p_tar', p_mode=$p_mode");
1739                $v_result = 1;
1740
1741                // ----- Write the last 0 filled block for end of archive
1742                $v_binary_data = pack("a512", "");
1743                if ($p_mode == "tar") {
1744                        fputs($p_tar, $v_binary_data);
1745                } else {
1746                        gzputs($p_tar, $v_binary_data);
1747                }
1748
1749                // ----- Return
1750                TrFctEnd(__FILE__, __LINE__, $v_result);
1751
1752                return $v_result;
1753        }
1754
1755        // --------------------------------------------------------------------------------
1756
1757        // --------------------------------------------------------------------------------
1758        // Function : PclTarHandleExtract()
1759        // Description :
1760        // Parameters :
1761        //   $p_tarname : Filename of the tar (or tgz) archive
1762        //   $p_file_list : An array which contains the list of files to extract, this
1763        //                  array may be empty when $p_mode is 'complete'
1764        //   $p_list_detail : An array where will be placed the properties of  each extracted/listed file
1765        //   $p_mode : 'complete' will extract all files from the archive,
1766        //             'partial' will look for files in $p_file_list
1767        //             'list' will only list the files from the archive without any extract
1768        //   $p_path : Path to add while writing the extracted files
1769        //   $p_tar_mode : 'tar' for GNU TAR archive, 'tgz' for compressed archive
1770        //   $p_remove_path : Path to remove (from the file memorized path) while writing the
1771        //                    extracted files. If the path does not match the file path,
1772        //                    the file is extracted with its memorized path.
1773        //                    $p_remove_path does not apply to 'list' mode.
1774        //                    $p_path and $p_remove_path are commulative.
1775        // Return Values :
1776        // --------------------------------------------------------------------------------
1777        function PclTarHandleExtract(
1778                $p_tarname,
1779                $p_file_list,
1780                &$p_list_detail,
1781                $p_mode,
1782                $p_path,
1783                $p_tar_mode,
1784                $p_remove_path
1785        ) {
1786                TrFctStart(__FILE__, __LINE__, "PclTarHandleExtract",
1787                        "archive='$p_tarname', list, mode=$p_mode, path=$p_path, tar_mode=$p_tar_mode, remove_path='$p_remove_path'");
1788                $v_result = 1;
1789                $v_nb = 0;
1790                $v_extract_all = true;
1791                $v_listing = false;
1792
1793                // ----- Check the path
1794                if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../"))) {
1795                        $p_path = "./" . $p_path;
1796                }
1797
1798                // ----- Look for path to remove format (should end by /)
1799                if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) {
1800                        $p_remove_path .= '/';
1801                }
1802                $p_remove_path_size = strlen($p_remove_path);
1803
1804                // ----- Study the mode
1805                switch ($p_mode) {
1806                        case "complete" :
1807                                // ----- Flag extract of all files
1808                                $v_extract_all = true;
1809                                $v_listing = false;
1810                                break;
1811                        case "partial" :
1812                                // ----- Flag extract of specific files
1813                                $v_extract_all = false;
1814                                $v_listing = false;
1815                                break;
1816                        case "list" :
1817                                // ----- Flag list of all files
1818                                $v_extract_all = false;
1819                                $v_listing = true;
1820                                break;
1821                        default :
1822                                // ----- Error log
1823                                PclErrorLog(-3, "Invalid extract mode ($p_mode)");
1824
1825                                // ----- Return
1826                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1827
1828                                return PclErrorCode();
1829                }
1830
1831                // ----- Open the tar file
1832                if ($p_tar_mode == "tar") {
1833                        TrFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
1834                        $v_tar = fopen($p_tarname, "rb");
1835                } else {
1836                        TrFctMessage(__FILE__, __LINE__, 3, "Open file in gzip binary read mode");
1837                        $v_tar = @gzopen($p_tarname, "rb");
1838                }
1839
1840                // ----- Check that the archive is open
1841                if ($v_tar == 0) {
1842                        // ----- Error log
1843                        PclErrorLog(-2, "Unable to open archive '$p_tarname' in binary read mode");
1844
1845                        // ----- Return
1846                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1847
1848                        return PclErrorCode();
1849                }
1850
1851                // ----- Read the blocks
1852                while (!($v_end_of_file = ($p_tar_mode == "tar" ? feof($v_tar) : gzeof($v_tar)))) {
1853                        TrFctMessage(__FILE__, __LINE__, 3, "Looking for next header ...");
1854
1855                        // ----- Clear cache of file infos
1856                        clearstatcache();
1857
1858                        // ----- Reset extract tag
1859                        $v_extract_file = false;
1860                        $v_extraction_stopped = 0;
1861
1862                        // ----- Read the 512 bytes header
1863                        if ($p_tar_mode == "tar") {
1864                                $v_binary_data = fread($v_tar, 512);
1865                        } else {
1866                                $v_binary_data = gzread($v_tar, 512);
1867                        }
1868
1869                        // ----- Read the header properties
1870                        if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
1871                                // ----- Close the archive file
1872                                if ($p_tar_mode == "tar") {
1873                                        fclose($v_tar);
1874                                } else {
1875                                        gzclose($v_tar);
1876                                }
1877
1878                                // ----- Return
1879                                TrFctEnd(__FILE__, __LINE__, $v_result);
1880
1881                                return $v_result;
1882                        }
1883
1884                        // ----- Look for empty blocks to skip
1885                        if ($v_header['filename'] == "") {
1886                                TrFctMessage(__FILE__, __LINE__, 2, "Empty block found. End of archive ?");
1887                                continue;
1888                        }
1889
1890                        TrFctMessage(__FILE__, __LINE__, 2, "Found file '$v_header[filename]', size '$v_header[size]'");
1891
1892                        // ----- Look for partial extract
1893                        if ((!$v_extract_all) && (is_array($p_file_list))) {
1894                                TrFctMessage(__FILE__, __LINE__, 2, "Look if the file '$v_header[filename]' need to be extracted");
1895
1896                                // ----- By default no unzip if the file is not found
1897                                $v_extract_file = false;
1898
1899                                // ----- Look into the file list
1900                                for ($i = 0; $i < sizeof($p_file_list); $i++) {
1901                                        TrFctMessage(__FILE__, __LINE__, 2,
1902                                                "Compare archived file '$v_header[filename]' from asked list file '" . $p_file_list[$i] . "'");
1903
1904                                        // ----- Look if it is a directory
1905                                        if (substr($p_file_list[$i], -1) == "/") {
1906                                                TrFctMessage(__FILE__, __LINE__, 3, "Compare file '$v_header[filename]' with directory '$p_file_list[$i]'");
1907
1908                                                // ----- Look if the directory is in the filename path
1909                                                if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) && (substr($v_header['filename'], 0,
1910                                                                        strlen($p_file_list[$i])) == $p_file_list[$i])
1911                                                ) {
1912                                                        // ----- The file is in the directory, so extract it
1913                                                        TrFctMessage(__FILE__, __LINE__, 2,
1914                                                                "File '$v_header[filename]' is in directory '$p_file_list[$i]' : extract it");
1915                                                        $v_extract_file = true;
1916
1917                                                        // ----- End of loop
1918                                                        break;
1919                                                }
1920                                        } // ----- It is a file, so compare the file names
1921                                        else {
1922                                                if ($p_file_list[$i] == $v_header['filename']) {
1923                                                        // ----- File found
1924                                                        TrFctMessage(__FILE__, __LINE__, 2, "File '$v_header[filename]' should be extracted");
1925                                                        $v_extract_file = true;
1926
1927                                                        // ----- End of loop
1928                                                        break;
1929                                                }
1930                                        }
1931                                }
1932
1933                                // ----- Trace
1934                                if (!$v_extract_file) {
1935                                        TrFctMessage(__FILE__, __LINE__, 2, "File '$v_header[filename]' should not be extracted");
1936                                }
1937                        } else {
1938                                // ----- All files need to be extracted
1939                                $v_extract_file = true;
1940                        }
1941
1942                        // ----- Look if this file need to be extracted
1943                        if (($v_extract_file) && (!$v_listing)) {
1944                                // ----- Look for path to remove
1945                                if (($p_remove_path != "")
1946                                        && (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path)
1947                                ) {
1948                                        TrFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '$v_header[filename]'");
1949                                        // ----- Remove the path
1950                                        $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
1951                                        TrFctMessage(__FILE__, __LINE__, 3, "Reslting file is '$v_header[filename]'");
1952                                }
1953
1954                                // ----- Add the path to the file
1955                                if (($p_path != "./") && ($p_path != "/")) {
1956                                        // ----- Look for the path end '/'
1957                                        while (substr($p_path, -1) == "/") {
1958                                                TrFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
1959                                                $p_path = substr($p_path, 0, strlen($p_path) - 1);
1960                                                TrFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
1961                                        }
1962
1963                                        // ----- Add the path
1964                                        if (substr($v_header['filename'], 0, 1) == "/") {
1965                                                $v_header['filename'] = $p_path . $v_header['filename'];
1966                                        } else {
1967                                                $v_header['filename'] = $p_path . "/" . $v_header['filename'];
1968                                        }
1969                                }
1970
1971                                // ----- Trace
1972                                TrFctMessage(__FILE__, __LINE__, 2,
1973                                        "Extracting file (with path) '$v_header[filename]', size '$v_header[size]'");
1974
1975                                // ----- Check that the file does not exists
1976                                if (file_exists($v_header['filename'])) {
1977                                        TrFctMessage(__FILE__, __LINE__, 2, "File '$v_header[filename]' already exists");
1978
1979                                        // ----- Look if file is a directory
1980                                        if (is_dir($v_header['filename'])) {
1981                                                TrFctMessage(__FILE__, __LINE__, 2, "Existing file '$v_header[filename]' is a directory");
1982
1983                                                // ----- Change the file status
1984                                                $v_header['status'] = "already_a_directory";
1985
1986                                                // ----- Skip the extract
1987                                                $v_extraction_stopped = 1;
1988                                                $v_extract_file = 0;
1989                                        } // ----- Look if file is write protected
1990                                        else {
1991                                                if (!is_writeable($v_header['filename'])) {
1992                                                        TrFctMessage(__FILE__, __LINE__, 2, "Existing file '$v_header[filename]' is write protected");
1993
1994                                                        // ----- Change the file status
1995                                                        $v_header['status'] = "write_protected";
1996
1997                                                        // ----- Skip the extract
1998                                                        $v_extraction_stopped = 1;
1999                                                        $v_extract_file = 0;
2000                                                } // ----- Look if the extracted file is older
2001                                                else {
2002                                                        if (filemtime($v_header['filename']) > $v_header['mtime']) {
2003                                                                TrFctMessage(__FILE__, __LINE__, 2,
2004                                                                        "Existing file '$v_header[filename]' is newer (" . date("l dS of F Y h:i:s A",
2005                                                                                filemtime($v_header['filename'])) . ") than the extracted file (" . date("l dS of F Y h:i:s A",
2006                                                                                $v_header['mtime']) . ")");
2007
2008                                                                // ----- Change the file status
2009                                                                $v_header['status'] = "newer_exist";
2010
2011                                                                // ----- Skip the extract
2012                                                                $v_extraction_stopped = 1;
2013                                                                $v_extract_file = 0;
2014                                                        }
2015                                                }
2016                                        }
2017                                } // ----- Check the directory availability and create it if necessary
2018                                else {
2019                                        if ($v_header['typeflag'] == "5") {
2020                                                $v_dir_to_check = $v_header['filename'];
2021                                        } else {
2022                                                if (!strstr($v_header['filename'], "/")) {
2023                                                        $v_dir_to_check = "";
2024                                                } else {
2025                                                        $v_dir_to_check = dirname($v_header['filename']);
2026                                                }
2027                                        }
2028
2029                                        if (($v_result = PclTarHandlerDirCheck($v_dir_to_check)) != 1) {
2030                                                TrFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '$v_header[filename]'");
2031
2032                                                // ----- Change the file status
2033                                                $v_header['status'] = "path_creation_fail";
2034
2035                                                // ----- Skip the extract
2036                                                $v_extraction_stopped = 1;
2037                                                $v_extract_file = 0;
2038                                        }
2039                                }
2040
2041                                // ----- Do the extraction
2042                                if (($v_extract_file) && ($v_header['typeflag'] != "5")) {
2043                                        // ----- Open the destination file in write mode
2044                                        if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
2045                                                TrFctMessage(__FILE__, __LINE__, 2, "Error while opening '$v_header[filename]' in write binary mode");
2046
2047                                                // ----- Change the file status
2048                                                $v_header['status'] = "write_error";
2049
2050                                                // ----- Jump to next file
2051                                                TrFctMessage(__FILE__, __LINE__, 2, "Jump to next file");
2052                                                if ($p_tar_mode == "tar") {
2053                                                        fseek($v_tar, ftell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2054                                                } else {
2055                                                        gzseek($v_tar, gztell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2056                                                }
2057                                        } else {
2058                                                TrFctMessage(__FILE__, __LINE__, 2, "Start extraction of '$v_header[filename]'");
2059
2060                                                // ----- Read data
2061                                                $n = floor($v_header['size'] / 512);
2062                                                for ($i = 0; $i < $n; $i++) {
2063                                                        TrFctMessage(__FILE__, __LINE__, 3, "Read complete 512 bytes block number " . ($i + 1));
2064                                                        if ($p_tar_mode == "tar") {
2065                                                                $v_content = fread($v_tar, 512);
2066                                                        } else {
2067                                                                $v_content = gzread($v_tar, 512);
2068                                                        }
2069                                                        fwrite($v_dest_file, $v_content, 512);
2070                                                }
2071                                                if (($v_header['size'] % 512) != 0) {
2072                                                        TrFctMessage(__FILE__, __LINE__, 3, "Read last " . ($v_header['size'] % 512) . " bytes in a 512 block");
2073                                                        if ($p_tar_mode == "tar") {
2074                                                                $v_content = fread($v_tar, 512);
2075                                                        } else {
2076                                                                $v_content = gzread($v_tar, 512);
2077                                                        }
2078                                                        fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
2079                                                }
2080
2081                                                // ----- Close the destination file
2082                                                fclose($v_dest_file);
2083
2084                                                // ----- Change the file mode, mtime
2085                                                touch($v_header['filename'], $v_header['mtime']);
2086                                                //chmod($v_header['filename'], DecOct($v_header['mode']));
2087                                        }
2088
2089                                        // ----- Check the file size
2090                                        clearstatcache();
2091                                        if (filesize($v_header['filename']) != $v_header['size']) {
2092                                                // ----- Close the archive file
2093                                                if ($p_tar_mode == "tar") {
2094                                                        fclose($v_tar);
2095                                                } else {
2096                                                        gzclose($v_tar);
2097                                                }
2098
2099                                                // ----- Error log
2100                                                PclErrorLog(-7,
2101                                                        "Extracted file '$v_header[filename]' does not have the correct file size '" . filesize($v_filename) . "' ('$v_header[size]' expected). Archive may be corrupted.");
2102
2103                                                // ----- Return
2104                                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2105
2106                                                return PclErrorCode();
2107                                        }
2108
2109                                        // ----- Trace
2110                                        TrFctMessage(__FILE__, __LINE__, 2, "Extraction done");
2111                                } else {
2112                                        TrFctMessage(__FILE__, __LINE__, 2, "Extraction of file '$v_header[filename]' skipped.");
2113
2114                                        // ----- Jump to next file
2115                                        TrFctMessage(__FILE__, __LINE__, 2, "Jump to next file");
2116                                        if ($p_tar_mode == "tar") {
2117                                                fseek($v_tar, ftell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2118                                        } else {
2119                                                gzseek($v_tar, gztell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2120                                        }
2121                                }
2122                        } // ----- Look for file that is not to be unzipped
2123                        else {
2124                                // ----- Trace
2125                                TrFctMessage(__FILE__, __LINE__, 2, "Jump file '$v_header[filename]'");
2126                                TrFctMessage(__FILE__, __LINE__, 4,
2127                                        "Position avant jump [" . ($p_tar_mode == "tar" ? ftell($v_tar) : gztell($v_tar)) . "]");
2128
2129                                // ----- Jump to next file
2130                                if ($p_tar_mode == "tar") {
2131                                        fseek($v_tar, ($p_tar_mode == "tar" ? ftell($v_tar) : gztell($v_tar)) + (ceil(($v_header['size'] / 512)) * 512));
2132                                } else {
2133                                        gzseek($v_tar, gztell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2134                                }
2135
2136                                TrFctMessage(__FILE__, __LINE__, 4,
2137                                        "Position apr�s jump [" . ($p_tar_mode == "tar" ? ftell($v_tar) : gztell($v_tar)) . "]");
2138                        }
2139
2140                        if ($p_tar_mode == "tar") {
2141                                $v_end_of_file = feof($v_tar);
2142                        } else {
2143                                $v_end_of_file = gzeof($v_tar);
2144                        }
2145
2146                        // ----- File name and properties are logged if listing mode or file is extracted
2147                        if ($v_listing || $v_extract_file || $v_extraction_stopped) {
2148                                TrFctMessage(__FILE__, __LINE__, 2, "Memorize info about file '$v_header[filename]'");
2149
2150                                // ----- Log extracted files
2151                                if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
2152                                        $v_file_dir = "";
2153                                }
2154                                if ((substr($v_header['filename'], 0, 1) == "/") && ($v_file_dir == "")) {
2155                                        $v_file_dir = "/";
2156                                }
2157
2158                                // ----- Add the array describing the file into the list
2159                                $p_list_detail[$v_nb] = $v_header;
2160
2161                                // ----- Increment
2162                                $v_nb++;
2163                        }
2164                }
2165
2166                // ----- Close the tarfile
2167                if ($p_tar_mode == "tar") {
2168                        fclose($v_tar);
2169                } else {
2170                        gzclose($v_tar);
2171                }
2172
2173                // ----- Return
2174                TrFctEnd(__FILE__, __LINE__, $v_result);
2175
2176                return $v_result;
2177        }
2178
2179        // --------------------------------------------------------------------------------
2180
2181        // --------------------------------------------------------------------------------
2182        // Function : PclTarHandleExtractByIndexList()
2183        // Description :
2184        //   Extract the files which are at the indexes specified. If the 'file' at the
2185        //   index is a directory, the directory only is created, not all the files stored
2186        //   for that directory.
2187        // Parameters :
2188        //   $p_index_string : String of indexes of files to extract. The form of the
2189        //                     string is "0,4-6,8-12" with only numbers and '-' for
2190        //                     for range, and ',' to separate ranges. No spaces or ';'
2191        //                     are allowed.
2192        // Return Values :
2193        // --------------------------------------------------------------------------------
2194        function PclTarHandleExtractByIndexList(
2195                $p_tarname,
2196                $p_index_string,
2197                &$p_list_detail,
2198                $p_path,
2199                $p_remove_path,
2200                $p_tar_mode
2201        ) {
2202                TrFctStart(__FILE__, __LINE__, "PclTarHandleExtractByIndexList",
2203                        "archive='$p_tarname', index_string='$p_index_string', list, path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2204                $v_result = 1;
2205                $v_nb = 0;
2206
2207                // ----- TBC : I should check the string by a regexp
2208
2209                // ----- Check the path
2210                if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../") && (substr($p_path, 0,
2211                                                2) != "./"))
2212                ) {
2213                        $p_path = "./" . $p_path;
2214                }
2215
2216                // ----- Look for path to remove format (should end by /)
2217                if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) {
2218                        $p_remove_path .= '/';
2219                }
2220                $p_remove_path_size = strlen($p_remove_path);
2221
2222                // ----- Open the tar file
2223                if ($p_tar_mode == "tar") {
2224                        TrFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2225                        $v_tar = @fopen($p_tarname, "rb");
2226                } else {
2227                        TrFctMessage(__FILE__, __LINE__, 3, "Open file in gzip binary read mode");
2228                        $v_tar = @gzopen($p_tarname, "rb");
2229                }
2230
2231                // ----- Check that the archive is open
2232                if ($v_tar == 0) {
2233                        // ----- Error log
2234                        PclErrorLog(-2, "Unable to open archive '$p_tarname' in binary read mode");
2235
2236                        // ----- Return
2237                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2238
2239                        return PclErrorCode();
2240                }
2241
2242                // ----- Manipulate the index list
2243                $v_list = explode(",", $p_index_string);
2244                sort($v_list);
2245
2246                // ----- Loop on the index list
2247                $v_index = 0;
2248                for ($i = 0; ($i < sizeof($v_list)) && ($v_result); $i++) {
2249                        TrFctMessage(__FILE__, __LINE__, 3, "Looking for index part '$v_list[$i]'");
2250
2251                        // ----- Extract range
2252                        $v_index_list = explode("-", $v_list[$i]);
2253                        $v_size_index_list = sizeof($v_index_list);
2254                        if ($v_size_index_list == 1) {
2255                                TrFctMessage(__FILE__, __LINE__, 3, "Only one index '$v_index_list[0]'");
2256
2257                                // ----- Do the extraction
2258                                $v_result = PclTarHandleExtractByIndex($v_tar, $v_index, $v_index_list[0], $v_index_list[0], $p_list_detail,
2259                                        $p_path, $p_remove_path, $p_tar_mode);
2260                        } else {
2261                                if ($v_size_index_list == 2) {
2262                                        TrFctMessage(__FILE__, __LINE__, 3, "Two indexes '$v_index_list[0]' and '$v_index_list[1]'");
2263
2264                                        // ----- Do the extraction
2265                                        $v_result = PclTarHandleExtractByIndex($v_tar, $v_index, $v_index_list[0], $v_index_list[1], $p_list_detail,
2266                                                $p_path, $p_remove_path, $p_tar_mode);
2267                                }
2268                        }
2269                }
2270
2271                // ----- Close the tarfile
2272                if ($p_tar_mode == "tar") {
2273                        fclose($v_tar);
2274                } else {
2275                        gzclose($v_tar);
2276                }
2277
2278                // ----- Return
2279                TrFctEnd(__FILE__, __LINE__, $v_result);
2280
2281                return $v_result;
2282        }
2283
2284        // --------------------------------------------------------------------------------
2285
2286        // --------------------------------------------------------------------------------
2287        // Function : PclTarHandleExtractByIndex()
2288        // Description :
2289        // Parameters :
2290        // Return Values :
2291        // --------------------------------------------------------------------------------
2292        function PclTarHandleExtractByIndex(
2293                $p_tar,
2294                &$p_index_current,
2295                $p_index_start,
2296                $p_index_stop,
2297                &$p_list_detail,
2298                $p_path,
2299                $p_remove_path,
2300                $p_tar_mode
2301        ) {
2302                TrFctStart(__FILE__, __LINE__, "PclTarHandleExtractByIndex",
2303                        "archive_descr='$p_tar', index_current=$p_index_current, index_start='$p_index_start', index_stop='$p_index_stop', list, path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2304                $v_result = 1;
2305                $v_nb = 0;
2306
2307                // TBC : I should replace all $v_tar by $p_tar in this function ....
2308                $v_tar = $p_tar;
2309
2310                // ----- Look the number of elements already in $p_list_detail
2311                $v_nb = sizeof($p_list_detail);
2312
2313                // ----- Read the blocks
2314                while (!($v_end_of_file = ($p_tar_mode == "tar" ? feof($v_tar) : gzeof($v_tar)))) {
2315                        TrFctMessage(__FILE__, __LINE__, 3, "Looking for next file ...");
2316                        TrFctMessage(__FILE__, __LINE__, 3, "Index current=$p_index_current, range=[$p_index_start, $p_index_stop])");
2317
2318                        if ($p_index_current > $p_index_stop) {
2319                                TrFctMessage(__FILE__, __LINE__, 2, "Stop extraction, past stop index");
2320                                break;
2321                        }
2322
2323                        // ----- Clear cache of file infos
2324                        clearstatcache();
2325
2326                        // ----- Reset extract tag
2327                        $v_extract_file = false;
2328                        $v_extraction_stopped = 0;
2329
2330                        // ----- Read the 512 bytes header
2331                        if ($p_tar_mode == "tar") {
2332                                $v_binary_data = fread($v_tar, 512);
2333                        } else {
2334                                $v_binary_data = gzread($v_tar, 512);
2335                        }
2336
2337                        // ----- Read the header properties
2338                        if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
2339                                // ----- Return
2340                                TrFctEnd(__FILE__, __LINE__, $v_result);
2341
2342                                return $v_result;
2343                        }
2344
2345                        // ----- Look for empty blocks to skip
2346                        if ($v_header['filename'] == "") {
2347                                TrFctMessage(__FILE__, __LINE__, 2, "Empty block found. End of archive ?");
2348                                continue;
2349                        }
2350
2351                        TrFctMessage(__FILE__, __LINE__, 2, "Found file '$v_header[filename]', size '$v_header[size]'");
2352
2353                        // ----- Look if file is in the range to be extracted
2354                        if (($p_index_current >= $p_index_start) && ($p_index_current <= $p_index_stop)) {
2355                                TrFctMessage(__FILE__, __LINE__, 2, "File '$v_header[filename]' is in the range to be extracted");
2356                                $v_extract_file = true;
2357                        } else {
2358                                TrFctMessage(__FILE__, __LINE__, 2, "File '$v_header[filename]' is out of the range");
2359                                $v_extract_file = false;
2360                        }
2361
2362                        // ----- Look if this file need to be extracted
2363                        if ($v_extract_file) {
2364                                if (($v_result = PclTarHandleExtractFile($v_tar, $v_header, $p_path, $p_remove_path, $p_tar_mode)) != 1) {
2365                                        // ----- Return
2366                                        TrFctEnd(__FILE__, __LINE__, $v_result);
2367
2368                                        return $v_result;
2369                                }
2370                        } // ----- Look for file that is not to be extracted
2371                        else {
2372                                // ----- Trace
2373                                TrFctMessage(__FILE__, __LINE__, 2, "Jump file '$v_header[filename]'");
2374                                TrFctMessage(__FILE__, __LINE__, 4,
2375                                        "Position avant jump [" . ($p_tar_mode == "tar" ? ftell($v_tar) : gztell($v_tar)) . "]");
2376
2377                                // ----- Jump to next file
2378                                if ($p_tar_mode == "tar") {
2379                                        fseek($v_tar, ($p_tar_mode == "tar" ? ftell($v_tar) : gztell($v_tar)) + (ceil(($v_header['size'] / 512)) * 512));
2380                                } else {
2381                                        gzseek($v_tar, gztell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2382                                }
2383
2384                                TrFctMessage(__FILE__, __LINE__, 4,
2385                                        "Position apr�s jump [" . ($p_tar_mode == "tar" ? ftell($v_tar) : gztell($v_tar)) . "]");
2386                        }
2387
2388                        if ($p_tar_mode == "tar") {
2389                                $v_end_of_file = feof($v_tar);
2390                        } else {
2391                                $v_end_of_file = gzeof($v_tar);
2392                        }
2393
2394                        // ----- File name and properties are logged if listing mode or file is extracted
2395                        if ($v_extract_file) {
2396                                TrFctMessage(__FILE__, __LINE__, 2, "Memorize info about file '$v_header[filename]'");
2397
2398                                // ----- Log extracted files
2399                                if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
2400                                        $v_file_dir = "";
2401                                }
2402                                if ((substr($v_header['filename'], 0, 1) == "/") && ($v_file_dir == "")) {
2403                                        $v_file_dir = "/";
2404                                }
2405
2406                                // ----- Add the array describing the file into the list
2407                                $p_list_detail[$v_nb] = $v_header;
2408
2409                                // ----- Increment
2410                                $v_nb++;
2411                        }
2412
2413                        // ----- Increment the current file index
2414                        $p_index_current++;
2415                }
2416
2417                // ----- Return
2418                TrFctEnd(__FILE__, __LINE__, $v_result);
2419
2420                return $v_result;
2421        }
2422
2423        // --------------------------------------------------------------------------------
2424
2425        // --------------------------------------------------------------------------------
2426        // Function : PclTarHandleExtractFile()
2427        // Description :
2428        // Parameters :
2429        // Return Values :
2430        // --------------------------------------------------------------------------------
2431        function PclTarHandleExtractFile($p_tar, &$v_header, $p_path, $p_remove_path, $p_tar_mode) {
2432                TrFctStart(__FILE__, __LINE__, "PclTarHandleExtractFile",
2433                        "archive_descr='$p_tar', path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2434                $v_result = 1;
2435
2436                // TBC : I should replace all $v_tar by $p_tar in this function ....
2437                $v_tar = $p_tar;
2438                $v_extract_file = 1;
2439
2440                $p_remove_path_size = strlen($p_remove_path);
2441
2442                // ----- Look for path to remove
2443                if (($p_remove_path != "")
2444                        && (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path)
2445                ) {
2446                        TrFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '$v_header[filename]'");
2447                        // ----- Remove the path
2448                        $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
2449                        TrFctMessage(__FILE__, __LINE__, 3, "Resulting file is '$v_header[filename]'");
2450                }
2451
2452                // ----- Add the path to the file
2453                if (($p_path != "./") && ($p_path != "/")) {
2454                        // ----- Look for the path end '/'
2455                        while (substr($p_path, -1) == "/") {
2456                                TrFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
2457                                $p_path = substr($p_path, 0, strlen($p_path) - 1);
2458                                TrFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
2459                        }
2460
2461                        // ----- Add the path
2462                        if (substr($v_header['filename'], 0, 1) == "/") {
2463                                $v_header['filename'] = $p_path . $v_header['filename'];
2464                        } else {
2465                                $v_header['filename'] = $p_path . "/" . $v_header['filename'];
2466                        }
2467                }
2468
2469                // ----- Trace
2470                TrFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '$v_header[filename]', size '$v_header[size]'");
2471
2472                // ----- Check that the file does not exists
2473                if (file_exists($v_header['filename'])) {
2474                        TrFctMessage(__FILE__, __LINE__, 2, "File '$v_header[filename]' already exists");
2475
2476                        // ----- Look if file is a directory
2477                        if (is_dir($v_header['filename'])) {
2478                                TrFctMessage(__FILE__, __LINE__, 2, "Existing file '$v_header[filename]' is a directory");
2479
2480                                // ----- Change the file status
2481                                $v_header['status'] = "already_a_directory";
2482
2483                                // ----- Skip the extract
2484                                $v_extraction_stopped = 1;
2485                                $v_extract_file = 0;
2486                        } // ----- Look if file is write protected
2487                        else {
2488                                if (!is_writeable($v_header['filename'])) {
2489                                        TrFctMessage(__FILE__, __LINE__, 2, "Existing file '$v_header[filename]' is write protected");
2490
2491                                        // ----- Change the file status
2492                                        $v_header['status'] = "write_protected";
2493
2494                                        // ----- Skip the extract
2495                                        $v_extraction_stopped = 1;
2496                                        $v_extract_file = 0;
2497                                } // ----- Look if the extracted file is older
2498                                else {
2499                                        if (filemtime($v_header['filename']) > $v_header['mtime']) {
2500                                                TrFctMessage(__FILE__, __LINE__, 2,
2501                                                        "Existing file '$v_header[filename]' is newer (" . date("l dS of F Y h:i:s A",
2502                                                                filemtime($v_header['filename'])) . ") than the extracted file (" . date("l dS of F Y h:i:s A",
2503                                                                $v_header['mtime']) . ")");
2504
2505                                                // ----- Change the file status
2506                                                $v_header['status'] = "newer_exist";
2507
2508                                                // ----- Skip the extract
2509                                                $v_extraction_stopped = 1;
2510                                                $v_extract_file = 0;
2511                                        }
2512                                }
2513                        }
2514                } // ----- Check the directory availability and create it if necessary
2515                else {
2516                        if ($v_header['typeflag'] == "5") {
2517                                $v_dir_to_check = $v_header['filename'];
2518                        } else {
2519                                if (!strstr($v_header['filename'], "/")) {
2520                                        $v_dir_to_check = "";
2521                                } else {
2522                                        $v_dir_to_check = dirname($v_header['filename']);
2523                                }
2524                        }
2525
2526                        if (($v_result = PclTarHandlerDirCheck($v_dir_to_check)) != 1) {
2527                                TrFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '$v_header[filename]'");
2528
2529                                // ----- Change the file status
2530                                $v_header['status'] = "path_creation_fail";
2531
2532                                // ----- Skip the extract
2533                                $v_extraction_stopped = 1;
2534                                $v_extract_file = 0;
2535                        }
2536                }
2537
2538                // ----- Do the real bytes extraction (if not a directory)
2539                if (($v_extract_file) && ($v_header['typeflag'] != "5")) {
2540                        // ----- Open the destination file in write mode
2541                        if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
2542                                TrFctMessage(__FILE__, __LINE__, 2, "Error while opening '$v_header[filename]' in write binary mode");
2543
2544                                // ----- Change the file status
2545                                $v_header['status'] = "write_error";
2546
2547                                // ----- Jump to next file
2548                                TrFctMessage(__FILE__, __LINE__, 2, "Jump to next file");
2549                                if ($p_tar_mode == "tar") {
2550                                        fseek($v_tar, ftell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2551                                } else {
2552                                        gzseek($v_tar, gztell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2553                                }
2554                        } else {
2555                                TrFctMessage(__FILE__, __LINE__, 2, "Start extraction of '$v_header[filename]'");
2556
2557                                // ----- Read data
2558                                $n = floor($v_header['size'] / 512);
2559                                for ($i = 0; $i < $n; $i++) {
2560                                        TrFctMessage(__FILE__, __LINE__, 3, "Read complete 512 bytes block number " . ($i + 1));
2561                                        if ($p_tar_mode == "tar") {
2562                                                $v_content = fread($v_tar, 512);
2563                                        } else {
2564                                                $v_content = gzread($v_tar, 512);
2565                                        }
2566                                        fwrite($v_dest_file, $v_content, 512);
2567                                }
2568                                if (($v_header['size'] % 512) != 0) {
2569                                        TrFctMessage(__FILE__, __LINE__, 3, "Read last " . ($v_header['size'] % 512) . " bytes in a 512 block");
2570                                        if ($p_tar_mode == "tar") {
2571                                                $v_content = fread($v_tar, 512);
2572                                        } else {
2573                                                $v_content = gzread($v_tar, 512);
2574                                        }
2575                                        fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
2576                                }
2577
2578                                // ----- Close the destination file
2579                                fclose($v_dest_file);
2580
2581                                // ----- Change the file mode, mtime
2582                                touch($v_header['filename'], $v_header['mtime']);
2583                                //chmod($v_header['filename'], DecOct($v_header['mode']));
2584                        }
2585
2586                        // ----- Check the file size
2587                        clearstatcache();
2588                        if (filesize($v_header['filename']) != $v_header['size']) {
2589                                // ----- Error log
2590                                PclErrorLog(-7,
2591                                        "Extracted file '$v_header[filename]' does not have the correct file size '" . filesize($v_filename) . "' ('$v_header[size]' expected). Archive may be corrupted.");
2592
2593                                // ----- Return
2594                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2595
2596                                return PclErrorCode();
2597                        }
2598
2599                        // ----- Trace
2600                        TrFctMessage(__FILE__, __LINE__, 2, "Extraction done");
2601                } else {
2602                        TrFctMessage(__FILE__, __LINE__, 2, "Extraction of file '$v_header[filename]' skipped.");
2603
2604                        // ----- Jump to next file
2605                        TrFctMessage(__FILE__, __LINE__, 2, "Jump to next file");
2606                        if ($p_tar_mode == "tar") {
2607                                fseek($v_tar, ftell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2608                        } else {
2609                                gzseek($v_tar, gztell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2610                        }
2611                }
2612
2613                // ----- Return
2614                TrFctEnd(__FILE__, __LINE__, $v_result);
2615
2616                return $v_result;
2617        }
2618
2619        // --------------------------------------------------------------------------------
2620
2621        // --------------------------------------------------------------------------------
2622        // Function : PclTarHandleDelete()
2623        // Description :
2624        // Parameters :
2625        // Return Values :
2626        // --------------------------------------------------------------------------------
2627        function PclTarHandleDelete($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode) {
2628                TrFctStart(__FILE__, __LINE__, "PclTarHandleDelete", "archive='$p_tarname', list, tar_mode=$p_tar_mode");
2629                $v_result = 1;
2630                $v_nb = 0;
2631
2632                // ----- Look for regular tar file
2633                if ($p_tar_mode == "tar") {
2634                        // ----- Open file
2635                        TrFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2636                        if (($v_tar = @fopen($p_tarname, "rb")) == 0) {
2637                                // ----- Error log
2638                                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2639
2640                                // ----- Return
2641                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2642
2643                                return PclErrorCode();
2644                        }
2645
2646                        // ----- Open a temporary file in write mode
2647                        $v_temp_tarname = uniqid("pcltar-") . ".tmp";
2648                        TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
2649                        if (($v_temp_tar = @fopen($v_temp_tarname, "wb")) == 0) {
2650                                // ----- Close tar file
2651                                fclose($v_tar);
2652
2653                                // ----- Error log
2654                                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2655
2656                                // ----- Return
2657                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2658
2659                                return PclErrorCode();
2660                        }
2661                } // ----- Look for compressed tar file
2662                else {
2663                        // ----- Open the file in read mode
2664                        TrFctMessage(__FILE__, __LINE__, 3, "Open file in gzip binary read mode");
2665                        if (($v_tar = @gzopen($p_tarname, "rb")) == 0) {
2666                                // ----- Error log
2667                                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2668
2669                                // ----- Return
2670                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2671
2672                                return PclErrorCode();
2673                        }
2674
2675                        // ----- Open a temporary file in write mode
2676                        $v_temp_tarname = uniqid("pcltar-") . ".tmp";
2677                        TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
2678                        if (($v_temp_tar = @gzopen($v_temp_tarname, "wb")) == 0) {
2679                                // ----- Close tar file
2680                                gzclose($v_tar);
2681
2682                                // ----- Error log
2683                                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2684
2685                                // ----- Return
2686                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2687
2688                                return PclErrorCode();
2689                        }
2690                }
2691
2692                // ----- Read the blocks
2693                while (!($v_end_of_file = ($p_tar_mode == "tar" ? feof($v_tar) : gzeof($v_tar)))) {
2694                        TrFctMessage(__FILE__, __LINE__, 3, "Looking for next header ...");
2695
2696                        // ----- Clear cache of file infos
2697                        clearstatcache();
2698
2699                        // ----- Reset delete tag
2700                        $v_delete_file = false;
2701
2702                        // ----- Read the first 512 block header
2703                        if ($p_tar_mode == "tar") {
2704                                $v_binary_data = fread($v_tar, 512);
2705                        } else {
2706                                $v_binary_data = gzread($v_tar, 512);
2707                        }
2708
2709                        // ----- Read the header properties
2710                        if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
2711                                // ----- Close the archive file
2712                                if ($p_tar_mode == "tar") {
2713                                        fclose($v_tar);
2714                                        fclose($v_temp_tar);
2715                                } else {
2716                                        gzclose($v_tar);
2717                                        gzclose($v_temp_tar);
2718                                }
2719                                @unlink($v_temp_tarname);
2720
2721                                // ----- Return
2722                                TrFctEnd(__FILE__, __LINE__, $v_result);
2723
2724                                return $v_result;
2725                        }
2726
2727                        // ----- Look for empty blocks to skip
2728                        if ($v_header['filename'] == "") {
2729                                TrFctMessage(__FILE__, __LINE__, 2, "Empty block found. End of archive ?");
2730                                continue;
2731                        }
2732
2733                        TrFctMessage(__FILE__, __LINE__, 2, "Found file '$v_header[filename]', size '$v_header[size]'");
2734
2735                        // ----- Look for filenames to delete
2736                        for ($i = 0, $v_delete_file = false; ($i < sizeof($p_file_list)) && (!$v_delete_file); $i++) {
2737                                // ----- Compare the file names
2738//        if ($p_file_list[$i] == $v_header['filename'])
2739                                if (($v_len = strcmp($p_file_list[$i], $v_header['filename'])) <= 0) {
2740                                        if ($v_len == 0) {
2741                                                TrFctMessage(__FILE__, __LINE__, 3, "Found that '$v_header[filename]' need to be deleted");
2742                                                $v_delete_file = true;
2743                                        } else {
2744                                                TrFctMessage(__FILE__, __LINE__, 3, "Look if '$v_header[filename]' is a file in $p_file_list[$i]");
2745                                                if (substr($v_header['filename'], strlen($p_file_list[$i]), 1) == "/") {
2746                                                        TrFctMessage(__FILE__, __LINE__, 3, "'$v_header[filename]' is a file in $p_file_list[$i]");
2747                                                        $v_delete_file = true;
2748                                                }
2749                                        }
2750                                }
2751                        }
2752
2753                        // ----- Copy files that do not need to be deleted
2754                        if (!$v_delete_file) {
2755                                TrFctMessage(__FILE__, __LINE__, 2, "Keep file '$v_header[filename]'");
2756
2757                                // ----- Write the file header
2758                                if ($p_tar_mode == "tar") {
2759                                        fputs($v_temp_tar, $v_binary_data, 512);
2760                                } else {
2761                                        gzputs($v_temp_tar, $v_binary_data, 512);
2762                                }
2763
2764                                // ----- Write the file data
2765                                $n = ceil($v_header['size'] / 512);
2766                                for ($i = 0; $i < $n; $i++) {
2767                                        TrFctMessage(__FILE__, __LINE__, 3, "Read complete 512 bytes block number " . ($i + 1));
2768                                        if ($p_tar_mode == "tar") {
2769                                                $v_content = fread($v_tar, 512);
2770                                                fwrite($v_temp_tar, $v_content, 512);
2771                                        } else {
2772                                                $v_content = gzread($v_tar, 512);
2773                                                gzwrite($v_temp_tar, $v_content, 512);
2774                                        }
2775                                }
2776
2777                                // ----- File name and properties are logged if listing mode or file is extracted
2778                                TrFctMessage(__FILE__, __LINE__, 2, "Memorize info about file '$v_header[filename]'");
2779
2780                                // ----- Add the array describing the file into the list
2781                                $p_list_detail[$v_nb] = $v_header;
2782                                $p_list_detail[$v_nb]['status'] = "ok";
2783
2784                                // ----- Increment
2785                                $v_nb++;
2786                        } // ----- Look for file that is to be deleted
2787                        else {
2788                                // ----- Trace
2789                                TrFctMessage(__FILE__, __LINE__, 2, "Start deletion of '$v_header[filename]'");
2790                                TrFctMessage(__FILE__, __LINE__, 4,
2791                                        "Position avant jump [" . ($p_tar_mode == "tar" ? ftell($v_tar) : gztell($v_tar)) . "]");
2792
2793                                // ----- Jump to next file
2794                                if ($p_tar_mode == "tar") {
2795                                        fseek($v_tar, ftell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2796                                } else {
2797                                        gzseek($v_tar, gztell($v_tar) + (ceil(($v_header['size'] / 512)) * 512));
2798                                }
2799
2800                                TrFctMessage(__FILE__, __LINE__, 4,
2801                                        "Position apr�s jump [" . ($p_tar_mode == "tar" ? ftell($v_tar) : gztell($v_tar)) . "]");
2802                        }
2803
2804                        // ----- Look for end of file
2805                        if ($p_tar_mode == "tar") {
2806                                $v_end_of_file = feof($v_tar);
2807                        } else {
2808                                $v_end_of_file = gzeof($v_tar);
2809                        }
2810                }
2811
2812                // ----- Write the last empty buffer
2813                PclTarHandleFooter($v_temp_tar, $p_tar_mode);
2814
2815                // ----- Close the tarfile
2816                if ($p_tar_mode == "tar") {
2817                        fclose($v_tar);
2818                        fclose($v_temp_tar);
2819                } else {
2820                        gzclose($v_tar);
2821                        gzclose($v_temp_tar);
2822                }
2823
2824                // ----- Unlink tar file
2825                if (!@unlink($p_tarname)) {
2826                        // ----- Error log
2827                        PclErrorLog(-11, "Error while deleting archive name $p_tarname");
2828                }
2829
2830
2831                // ----- Rename tar file
2832                if (!@rename($v_temp_tarname, $p_tarname)) {
2833                        // ----- Error log
2834                        PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
2835
2836                        // ----- Return
2837                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2838
2839                        return PclErrorCode();
2840                }
2841
2842                // ----- Return
2843                TrFctEnd(__FILE__, __LINE__, $v_result);
2844
2845                return $v_result;
2846        }
2847
2848        // --------------------------------------------------------------------------------
2849
2850        // --------------------------------------------------------------------------------
2851        // Function : PclTarHandleUpdate()
2852        // Description :
2853        // Parameters :
2854        // Return Values :
2855        // --------------------------------------------------------------------------------
2856        function PclTarHandleUpdate($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode, $p_add_dir, $p_remove_dir) {
2857                TrFctStart(__FILE__, __LINE__, "PclTarHandleUpdate", "archive='$p_tarname', list, tar_mode=$p_tar_mode");
2858                $v_result = 1;
2859                $v_nb = 0;
2860                $v_found_list = array();
2861
2862                // ----- Look for regular tar file
2863                if ($p_tar_mode == "tar") {
2864                        // ----- Open file
2865                        TrFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2866                        if (($v_tar = @fopen($p_tarname, "rb")) == 0) {
2867                                // ----- Error log
2868                                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2869
2870                                // ----- Return
2871                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2872
2873                                return PclErrorCode();
2874                        }
2875
2876                        // ----- Open a temporary file in write mode
2877                        $v_temp_tarname = uniqid("pcltar-") . ".tmp";
2878                        TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
2879                        if (($v_temp_tar = @fopen($v_temp_tarname, "wb")) == 0) {
2880                                // ----- Close tar file
2881                                fclose($v_tar);
2882
2883                                // ----- Error log
2884                                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2885
2886                                // ----- Return
2887                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2888
2889                                return PclErrorCode();
2890                        }
2891                } // ----- Look for compressed tar file
2892                else {
2893                        // ----- Open the file in read mode
2894                        TrFctMessage(__FILE__, __LINE__, 3, "Open file in gzip binary read mode");
2895                        if (($v_tar = @gzopen($p_tarname, "rb")) == 0) {
2896                                // ----- Error log
2897                                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2898
2899                                // ----- Return
2900                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2901
2902                                return PclErrorCode();
2903                        }
2904
2905                        // ----- Open a temporary file in write mode
2906                        $v_temp_tarname = uniqid("pcltar-") . ".tmp";
2907                        TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
2908                        if (($v_temp_tar = @gzopen($v_temp_tarname, "wb")) == 0) {
2909                                // ----- Close tar file
2910                                gzclose($v_tar);
2911
2912                                // ----- Error log
2913                                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2914
2915                                // ----- Return
2916                                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2917
2918                                return PclErrorCode();
2919                        }
2920                }
2921
2922                // ----- Prepare the list of files
2923                for ($i = 0; $i < sizeof($p_file_list); $i++) {
2924                        // ----- Reset the found list
2925                        $v_found_list[$i] = 0;
2926
2927                        // ----- Calculate the stored filename
2928                        $v_stored_list[$i] = $p_file_list[$i];
2929                        if ($p_remove_dir != "") {
2930                                if (substr($p_file_list[$i], -1) != '/') {
2931                                        $p_remove_dir .= "/";
2932                                }
2933
2934                                if (substr($p_file_list[$i], 0, strlen($p_remove_dir)) == $p_remove_dir) {
2935                                        $v_stored_list[$i] = substr($p_file_list[$i], strlen($p_remove_dir));
2936                                        TrFctMessage(__FILE__, __LINE__, 3,
2937                                                "Remove path '$p_remove_dir' in file '$p_file_list[$i]' = '$v_stored_list[$i]'");
2938                                }
2939                        }
2940                        if ($p_add_dir != "") {
2941                                if (substr($p_add_dir, -1) == "/") {
2942                                        $v_stored_list[$i] = $p_add_dir . $v_stored_list[$i];
2943                                } else {
2944                                        $v_stored_list[$i] = $p_add_dir . "/" . $v_stored_list[$i];
2945                                }
2946                                TrFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_file_list[$i]' = '$v_stored_list[$i]'");
2947                        }
2948                        $v_stored_list[$i] = PclTarHandlePathReduction($v_stored_list[$i]);
2949                        TrFctMessage(__FILE__, __LINE__, 3, "After reduction '$v_stored_list[$i]'");
2950                }
2951
2952
2953                // ----- Update file cache
2954                clearstatcache();
2955
2956                // ----- Read the blocks
2957                while (!($v_end_of_file = ($p_tar_mode == "tar" ? feof($v_tar) : gzeof($v_tar)))) {
2958                        TrFctMessage(__FILE__, __LINE__, 3, "Looking for next header ...");
2959
2960                        // ----- Clear cache of file infos
2961                        clearstatcache();
2962
2963                        // ----- Reset current found filename
2964                        $v_current_filename = "";
2965
2966                        // ----- Reset delete tag
2967                        $v_delete_file = false;
2968
2969                        // ----- Read the first 512 block header
2970                        if ($p_tar_mode == "tar") {
2971                                $v_binary_data = fread($v_tar, 512);
2972                        } else {
2973                                $v_binary_data = gzread($v_tar, 512);
2974                        }
2975
2976                        // ----- Read the header properties
2977                        if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
2978                                // ----- Close the archive file
2979                                if ($p_tar_mode == "tar") {
2980                                        fclose($v_tar);
2981                                        fclose($v_temp_tar);
2982                                } else {
2983                                        gzclose($v_tar);
2984                                        gzclose($v_temp_tar);
2985                                }
2986                                @unlink($v_temp_tarname);
2987
2988                                // ----- Return
2989                                TrFctEnd(__FILE__, __LINE__, $v_result);
2990
2991                                return $v_result;
2992                        }
2993
2994                        // ----- Look for empty blocks to skip
2995                        if ($v_header['filename'] == "") {
2996                                TrFctMessage(__FILE__, __LINE__, 2, "Empty block found. End of archive ?");
2997                                continue;
2998                        }
2999
3000                        TrFctMessage(__FILE__, __LINE__, 2, "Found file '$v_header[filename]', size '$v_header[size]'");
3001
3002                        // ----- Look for filenames to update
3003                        for ($i = 0, $v_update_file = false, $v_found_file = false; ($i < sizeof($v_stored_list)) && (!$v_update_file); $i++) {
3004                                TrFctMessage(__FILE__, __LINE__, 4, "Compare with file '$v_stored_list[$i]'");
3005
3006                                // ----- Compare the file names
3007                                if ($v_stored_list[$i] == $v_header['filename']) {
3008                                        TrFctMessage(__FILE__, __LINE__, 3, "File '$v_stored_list[$i]' is present in archive");
3009                                        TrFctMessage(__FILE__, __LINE__, 3,
3010                                                "File '$v_stored_list[$i]' mtime=" . filemtime($p_file_list[$i]) . " " . date("l dS of F Y h:i:s A",
3011                                                        filemtime($p_file_list[$i])));
3012                                        TrFctMessage(__FILE__, __LINE__, 3,
3013                                                "Archived mtime=" . $v_header['mtime'] . " " . date("l dS of F Y h:i:s A", $v_header['mtime']));
3014
3015                                        // ----- Store found informations
3016                                        $v_found_file = true;
3017                                        $v_current_filename = $p_file_list[$i];
3018
3019                                        // ----- Look if the file need to be updated
3020                                        if (filemtime($p_file_list[$i]) > $v_header['mtime']) {
3021                                                TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' need to be updated");
3022                                                $v_update_file = true;
3023                                        } else {
3024                                                TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' does not need to be updated");
3025                                                $v_update_file = false;
3026                                        }
3027
3028                                        // ----- Flag the name in order not to add the file at the end
3029                                        $v_found_list[$i] = 1;
3030                                } else {
3031                                        TrFctMessage(__FILE__, __LINE__, 4, "File '$p_file_list[$i]' is not '$v_header[filename]'");
3032                                }
3033                        }
3034
3035                        // ----- Copy files that do not need to be updated
3036                        if (!$v_update_file) {
3037                                TrFctMessage(__FILE__, __LINE__, 2, "Keep file '$v_header[filename]'");
3038
3039                                // ----- Write the file header
3040                                if ($p_tar_mode == "tar") {
3041                                        fputs($v_temp_tar, $v_binary_data, 512);
3042                                } else {
3043                                        gzputs($v_temp_tar, $v_binary_data, 512);
3044                                }
3045
3046                                // ----- Write the file data
3047                                $n = ceil($v_header['size'] / 512);
3048                                for ($j = 0; $j < $n; $j++) {
3049                                        TrFctMessage(__FILE__, __LINE__, 3, "Read complete 512 bytes block number " . ($j + 1));
3050                                        if ($p_tar_mode == "tar") {
3051                                                $v_content = fread($v_tar, 512);
3052                                                fwrite($v_temp_tar, $v_content, 512);
3053                                        } else {
3054                                                $v_content = gzread($v_tar, 512);
3055                                                gzwrite($v_temp_tar, $v_content, 512);
3056                                        }
3057                                }
3058
3059                                // ----- File name and properties are logged if listing mode or file is extracted
3060                                TrFctMessage(__FILE__, __LINE__, 2, "Memorize info about file '$v_header[filename]'");
3061
3062                                // ----- Add the array describing the file into the list
3063                                $p_list_detail[$v_nb] = $v_header;
3064                                $p_list_detail[$v_nb]['status'] = ($v_found_file ? "not_updated" : "ok");
3065
3066                                // ----- Increment
3067                                $v_nb++;
3068                        } // ----- Look for file that need to be updated
3069                        else {
3070                                // ----- Trace
3071                                TrFctMessage(__FILE__, __LINE__, 2, "Start update of file '$v_current_filename'");
3072
3073                                // ----- Store the old file size
3074                                $v_old_size = $v_header['size'];
3075
3076                                // ----- Add the file
3077                                if (($v_result = PclTarHandleAddFile($v_temp_tar, $v_current_filename, $p_tar_mode, $v_header, $p_add_dir,
3078                                                $p_remove_dir)) != 1
3079                                ) {
3080                                        // ----- Close the tarfile
3081                                        if ($p_tar_mode == "tar") {
3082                                                fclose($v_tar);
3083                                                fclose($v_temp_tar);
3084                                        } else {
3085                                                gzclose($v_tar);
3086                                                gzclose($v_temp_tar);
3087                                        }
3088                                        @unlink($p_temp_tarname);
3089
3090                                        // ----- Return status
3091                                        TrFctEnd(__FILE__, __LINE__, $v_result);
3092
3093                                        return $v_result;
3094                                }
3095
3096                                // ----- Trace
3097                                TrFctMessage(__FILE__, __LINE__, 2, "Skip old file '$v_header[filename]'");
3098
3099                                // ----- Jump to next file
3100                                if ($p_tar_mode == "tar") {
3101                                        fseek($v_tar, ftell($v_tar) + (ceil(($v_old_size / 512)) * 512));
3102                                } else {
3103                                        gzseek($v_tar, gztell($v_tar) + (ceil(($v_old_size / 512)) * 512));
3104                                }
3105
3106                                // ----- Add the array describing the file into the list
3107                                $p_list_detail[$v_nb] = $v_header;
3108                                $p_list_detail[$v_nb]['status'] = "updated";
3109
3110                                // ----- Increment
3111                                $v_nb++;
3112                        }
3113
3114                        // ----- Look for end of file
3115                        if ($p_tar_mode == "tar") {
3116                                $v_end_of_file = feof($v_tar);
3117                        } else {
3118                                $v_end_of_file = gzeof($v_tar);
3119                        }
3120                }
3121
3122                // ----- Look for files that does not exists in the archive and need to be added
3123                for ($i = 0; $i < sizeof($p_file_list); $i++) {
3124                        // ----- Look if file not found in the archive
3125                        if (!$v_found_list[$i]) {
3126                                TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' need to be added");
3127
3128                                // ----- Add the file
3129                                if (($v_result = PclTarHandleAddFile($v_temp_tar, $p_file_list[$i], $p_tar_mode, $v_header, $p_add_dir,
3130                                                $p_remove_dir)) != 1
3131                                ) {
3132                                        // ----- Close the tarfile
3133                                        if ($p_tar_mode == "tar") {
3134                                                fclose($v_tar);
3135                                                fclose($v_temp_tar);
3136                                        } else {
3137                                                gzclose($v_tar);
3138                                                gzclose($v_temp_tar);
3139                                        }
3140                                        @unlink($p_temp_tarname);
3141
3142                                        // ----- Return status
3143                                        TrFctEnd(__FILE__, __LINE__, $v_result);
3144
3145                                        return $v_result;
3146                                }
3147
3148                                // ----- Add the array describing the file into the list
3149                                $p_list_detail[$v_nb] = $v_header;
3150                                $p_list_detail[$v_nb]['status'] = "added";
3151
3152                                // ----- Increment
3153                                $v_nb++;
3154                        } else {
3155                                TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' was already updated if needed");
3156                        }
3157                }
3158
3159                // ----- Write the last empty buffer
3160                PclTarHandleFooter($v_temp_tar, $p_tar_mode);
3161
3162                // ----- Close the tarfile
3163                if ($p_tar_mode == "tar") {
3164                        fclose($v_tar);
3165                        fclose($v_temp_tar);
3166                } else {
3167                        gzclose($v_tar);
3168                        gzclose($v_temp_tar);
3169                }
3170
3171                // ----- Unlink tar file
3172                if (!@unlink($p_tarname)) {
3173                        // ----- Error log
3174                        PclErrorLog(-11, "Error while deleting archive name $p_tarname");
3175                }
3176
3177
3178                // ----- Rename tar file
3179                if (!@rename($v_temp_tarname, $p_tarname)) {
3180                        // ----- Error log
3181                        PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
3182
3183                        // ----- Return
3184                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3185
3186                        return PclErrorCode();
3187                }
3188
3189                // ----- Return
3190                TrFctEnd(__FILE__, __LINE__, $v_result);
3191
3192                return $v_result;
3193        }
3194
3195        // --------------------------------------------------------------------------------
3196
3197        // --------------------------------------------------------------------------------
3198        // Function : PclTarHandleReadHeader()
3199        // Description :
3200        // Parameters :
3201        // Return Values :
3202        // --------------------------------------------------------------------------------
3203        function PclTarHandleReadHeader($v_binary_data, &$v_header) {
3204                TrFctStart(__FILE__, __LINE__, "PclTarHandleReadHeader", "");
3205                $v_result = 1;
3206
3207                // ----- Read the 512 bytes header
3208                /*
3209    if ($p_tar_mode == "tar")
3210      $v_binary_data = fread($p_tar, 512);
3211    else
3212      $v_binary_data = gzread($p_tar, 512);
3213    */
3214
3215                // ----- Look for no more block
3216                if (strlen($v_binary_data) == 0) {
3217                        $v_header['filename'] = "";
3218                        $v_header['status'] = "empty";
3219
3220                        // ----- Return
3221                        TrFctEnd(__FILE__, __LINE__, $v_result, "End of archive found");
3222
3223                        return $v_result;
3224                }
3225
3226                // ----- Look for invalid block size
3227                if (strlen($v_binary_data) != 512) {
3228                        $v_header['filename'] = "";
3229                        $v_header['status'] = "invalid_header";
3230                        TrFctMessage(__FILE__, __LINE__, 2, "Invalid block size : " . strlen($v_binary_data));
3231
3232                        // ----- Error log
3233                        PclErrorLog(-10, "Invalid block size : " . strlen($v_binary_data));
3234
3235                        // ----- Return
3236                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3237
3238                        return PclErrorCode();
3239                }
3240
3241                // ----- Calculate the checksum
3242                $v_checksum = 0;
3243                // ..... First part of the header
3244                for ($i = 0; $i < 148; $i++) {
3245                        $v_checksum += ord(substr($v_binary_data, $i, 1));
3246                }
3247                // ..... Ignore the checksum value and replace it by ' ' (space)
3248                for ($i = 148; $i < 156; $i++) {
3249                        $v_checksum += ord(' ');
3250                }
3251                // ..... Last part of the header
3252                for ($i = 156; $i < 512; $i++) {
3253                        $v_checksum += ord(substr($v_binary_data, $i, 1));
3254                }
3255                TrFctMessage(__FILE__, __LINE__, 3, "Calculated checksum : $v_checksum");
3256
3257                // ----- Extract the values
3258                TrFctMessage(__FILE__, __LINE__, 2, "Header : '$v_binary_data'");
3259                $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor",
3260                        $v_binary_data);
3261
3262                // ----- Extract the checksum for check
3263                $v_header['checksum'] = OctDec(trim($v_data['checksum']));
3264                TrFctMessage(__FILE__, __LINE__, 3, "File checksum : $v_header[checksum]");
3265                if ($v_header['checksum'] != $v_checksum) {
3266                        TrFctMessage(__FILE__, __LINE__, 2,
3267                                "File checksum is invalid : $v_checksum calculated, $v_header[checksum] expected");
3268
3269                        $v_header['filename'] = "";
3270                        $v_header['status'] = "invalid_header";
3271
3272                        // ----- Look for last block (empty block)
3273                        if (($v_checksum == 256) && ($v_header['checksum'] == 0)) {
3274                                $v_header['status'] = "empty";
3275                                // ----- Return
3276                                TrFctEnd(__FILE__, __LINE__, $v_result, "End of archive found");
3277
3278                                return $v_result;
3279                        }
3280
3281                        // ----- Error log
3282                        PclErrorLog(-13, "Invalid checksum : $v_checksum calculated, $v_header[checksum] expected");
3283
3284                        // ----- Return
3285                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3286
3287                        return PclErrorCode();
3288                }
3289                TrFctMessage(__FILE__, __LINE__, 2, "File checksum is valid ($v_checksum)");
3290
3291                // ----- Extract the properties
3292                $v_header['filename'] = trim($v_data['filename']);
3293                TrFctMessage(__FILE__, __LINE__, 2, "Name : '$v_header[filename]'");
3294                $v_header['mode'] = OctDec(trim($v_data['mode']));
3295                TrFctMessage(__FILE__, __LINE__, 2, "Mode : '" . DecOct($v_header['mode']) . "'");
3296                $v_header['uid'] = OctDec(trim($v_data['uid']));
3297                TrFctMessage(__FILE__, __LINE__, 2, "Uid : '$v_header[uid]'");
3298                $v_header['gid'] = OctDec(trim($v_data['gid']));
3299                TrFctMessage(__FILE__, __LINE__, 2, "Gid : '$v_header[gid]'");
3300                $v_header['size'] = OctDec(trim($v_data['size']));
3301                TrFctMessage(__FILE__, __LINE__, 2, "Size : '$v_header[size]'");
3302                $v_header['mtime'] = OctDec(trim($v_data['mtime']));
3303                TrFctMessage(__FILE__, __LINE__, 2, "Date : " . date("l dS of F Y h:i:s A", $v_header['mtime']));
3304                if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
3305                        $v_header['size'] = 0;
3306                        TrFctMessage(__FILE__, __LINE__, 2, "Size (folder) : '$v_header[size]'");
3307                }
3308                TrFctMessage(__FILE__, __LINE__, 2, "File typeflag : $v_header[typeflag]");
3309                /* ----- All these fields are removed form the header because they do not carry interesting info
3310    $v_header[link] = trim($v_data[link]);
3311    TrFctMessage(__FILE__, __LINE__, 2, "Linkname : $v_header[linkname]");
3312    $v_header[magic] = trim($v_data[magic]);
3313    TrFctMessage(__FILE__, __LINE__, 2, "Magic : $v_header[magic]");
3314    $v_header[version] = trim($v_data[version]);
3315    TrFctMessage(__FILE__, __LINE__, 2, "Version : $v_header[version]");
3316    $v_header[uname] = trim($v_data[uname]);
3317    TrFctMessage(__FILE__, __LINE__, 2, "Uname : $v_header[uname]");
3318    $v_header[gname] = trim($v_data[gname]);
3319    TrFctMessage(__FILE__, __LINE__, 2, "Gname : $v_header[gname]");
3320    $v_header[devmajor] = trim($v_data[devmajor]);
3321    TrFctMessage(__FILE__, __LINE__, 2, "Devmajor : $v_header[devmajor]");
3322    $v_header[devminor] = trim($v_data[devminor]);
3323    TrFctMessage(__FILE__, __LINE__, 2, "Devminor : $v_header[devminor]");
3324    */
3325
3326                // ----- Set the status field
3327                $v_header['status'] = "ok";
3328
3329                // ----- Return
3330                TrFctEnd(__FILE__, __LINE__, $v_result);
3331
3332                return $v_result;
3333        }
3334
3335        // --------------------------------------------------------------------------------
3336
3337        // --------------------------------------------------------------------------------
3338        // Function : PclTarHandlerDirCheck()
3339        // Description :
3340        //   Check if a directory exists, if not it creates it and all the parents directory
3341        //   which may be useful.
3342        // Parameters :
3343        //   $p_dir : Directory path to check (without / at the end).
3344        // Return Values :
3345        //    1 : OK
3346        //   -1 : Unable to create directory
3347        // --------------------------------------------------------------------------------
3348        function PclTarHandlerDirCheck($p_dir) {
3349                $v_result = 1;
3350
3351                TrFctStart(__FILE__, __LINE__, "PclTarHandlerDirCheck", "$p_dir");
3352
3353                // ----- Check the directory availability
3354                if ((is_dir($p_dir)) || ($p_dir == "")) {
3355                        TrFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
3356
3357                        return 1;
3358                }
3359
3360                // ----- Look for file alone
3361                /*
3362    if (!strstr("$p_dir", "/"))
3363    {
3364      TrFctEnd(__FILE__, __LINE__,  "'$p_dir' is a file with no directory");
3365      return 1;
3366    }
3367    */
3368
3369                // ----- Extract parent directory
3370                $p_parent_dir = dirname($p_dir);
3371                TrFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
3372
3373                // ----- Just a check
3374                if ($p_parent_dir != $p_dir) {
3375                        // ----- Look for parent directory
3376                        if ($p_parent_dir != "") {
3377                                if (($v_result = PclTarHandlerDirCheck($p_parent_dir)) != 1) {
3378                                        TrFctEnd(__FILE__, __LINE__, $v_result);
3379
3380                                        return $v_result;
3381                                }
3382                        }
3383                }
3384
3385                // ----- Create the directory
3386                TrFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
3387                if (!@mkdir($p_dir, 0777)) {
3388                        // ----- Error log
3389                        PclErrorLog(-8, "Unable to create directory '$p_dir'");
3390
3391                        // ----- Return
3392                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3393
3394                        return PclErrorCode();
3395                }
3396
3397                // ----- Return
3398                TrFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
3399
3400                return $v_result;
3401        }
3402
3403        // --------------------------------------------------------------------------------
3404
3405        // --------------------------------------------------------------------------------
3406        // Function : PclTarHandleExtension()
3407        // Description :
3408        // Parameters :
3409        // Return Values :
3410        // --------------------------------------------------------------------------------
3411        function PclTarHandleExtension($p_tarname) {
3412                TrFctStart(__FILE__, __LINE__, "PclTarHandleExtension", "tar=$p_tarname");
3413
3414                // ----- Look for file extension
3415                if ((substr($p_tarname, -7) == ".tar.gz") || (substr($p_tarname, -4) == ".tgz")) {
3416                        TrFctMessage(__FILE__, __LINE__, 2, "Archive is a gzip tar");
3417                        $p_mode = "tgz";
3418                } else {
3419                        if (substr($p_tarname, -4) == ".tar") {
3420                                TrFctMessage(__FILE__, __LINE__, 2, "Archive is a tar");
3421                                $p_mode = "tar";
3422                        } else {
3423                                // ----- Error log
3424                                PclErrorLog(-9, "Invalid archive extension");
3425
3426                                TrFctMessage(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3427
3428                                $p_mode = "";
3429                        }
3430                }
3431
3432                // ----- Return
3433                TrFctEnd(__FILE__, __LINE__, $p_mode);
3434
3435                return $p_mode;
3436        }
3437
3438        // --------------------------------------------------------------------------------
3439
3440
3441        // --------------------------------------------------------------------------------
3442        // Function : PclTarHandlePathReduction()
3443        // Description :
3444        // Parameters :
3445        // Return Values :
3446        // --------------------------------------------------------------------------------
3447        function PclTarHandlePathReduction($p_dir) {
3448                TrFctStart(__FILE__, __LINE__, "PclTarHandlePathReduction", "dir='$p_dir'");
3449                $v_result = "";
3450
3451                // ----- Look for not empty path
3452                if ($p_dir != "") {
3453                        // ----- Explode path by directory names
3454                        $v_list = explode("/", $p_dir);
3455
3456                        // ----- Study directories from last to first
3457                        for ($i = sizeof($v_list) - 1; $i >= 0; $i--) {
3458                                // ----- Look for current path
3459                                if ($v_list[$i] == ".") {
3460                                        // ----- Ignore this directory
3461                                        // Should be the first $i=0, but no check is done
3462                                } else {
3463                                        if ($v_list[$i] == "..") {
3464                                                // ----- Ignore it and ignore the $i-1
3465                                                $i--;
3466                                        } else {
3467                                                if (($v_list[$i] == "") && ($i != (sizeof($v_list) - 1)) && ($i != 0)) {
3468                                                        // ----- Ignore only the double '//' in path,
3469                                                        // but not the first and last '/'
3470                                                } else {
3471                                                        $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? "/" . $v_result : "");
3472                                                }
3473                                        }
3474                                }
3475                        }
3476                }
3477
3478                // ----- Return
3479                TrFctEnd(__FILE__, __LINE__, $v_result);
3480
3481                return $v_result;
3482        }
3483
3484        // --------------------------------------------------------------------------------
3485
3486
3487// ----- End of double include look
3488}
Note: See TracBrowser for help on using the repository browser.