Completed
Push — master ( a9decc...a21b67 )
by Michael
02:51
created

class/pcltar.lib.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
28
if (!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($gPcltarLibDir)) {
34
        $gPcltarLibDir = 'lib';
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
    // ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
54
    // --------------------------------------------------------------------------------
55
56
    // ----- Global variables
57
    $g_pcltar_version = '1.3.1';
58
59
    // ----- Include other libraries
60
    // This library should be called by each script before the include of PhpZip
61
    // Library in order to limit the potential 'lib' directory path problem.
62
    if (!defined('PCLERROR_LIB')) {
63
        include $gPcltarLibDir . '/pclerror.lib.php';
64
    }
65
    if (!defined('PCLTRACE_LIB')) {
66
        include $gPcltarLibDir . '/pcltrace.lib.php';
67
    }
68
69
    // --------------------------------------------------------------------------------
70
    // Function : PclTarCreate()
71
    // Description :
72
    //   Creates a new archive with name $p_tarname containing the files and/or
73
    //   directories indicated in $p_list. If the tar filename extension is
74
    //   ".tar", the file will not be compressed. If it is ".tar.gz" or ".tgz"
75
    //   it will be a gzip compressed tar archive.
76
    //   If you want to use an other extension, you must indicate the mode in
77
    //   $p_mode ("tar" or "tgz").
78
    //   $p_add_dir and $p_remove_dir give you the ability to store a path
79
    //   which is not the real path of the files.
80
    // Parameters :
81
    //   $p_tarname : Name of an existing tar file
82
    //   $p_filelist : An array containing file or directory names, or
83
    //                 a string containing one filename or directory name, or
84
    //                 a string containing a list of filenames and/or directory
85
    //                 names separated by spaces.
86
    //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive,
87
    //             if $p_mode is not specified, it will be determined by the extension.
88
    //   $p_add_dir : Path to add in the filename path archived
89
    //   $p_remove_dir : Path to remove in the filename path archived
90
    // Return Values :
91
    //   1 on success, or an error code (see table at the beginning).
92
    // --------------------------------------------------------------------------------
93
    /**
94
     * @param              $p_tarname
95
     * @param string|array $p_filelist
96
     * @param string       $p_mode
97
     * @param string       $p_add_dir
98
     * @param string       $p_remove_dir
99
     *
100
     * @return int
101
     */
102
    function PclTarCreate($p_tarname, $p_filelist = '', $p_mode = '', $p_add_dir = '', $p_remove_dir = '')
103
    {
104
        TrFctStart(__FILE__, __LINE__, 'PclTarCreate', "tar=$p_tarname, file='$p_filelist', mode=$p_mode, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
105
        $v_result = 1;
106
107
        // ----- Look for default mode
108 View Code Duplication
        if (($p_mode == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
109
            // ----- Extract the tar format from the extension
110
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
111
                // ----- Return
112
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
113
114
                return PclErrorCode();
115
            }
116
117
            // ----- Trace
118
            TrFctMessage(__FILE__, __LINE__, 1, "Auto mode selected : found $p_mode");
119
        }
120
121
        // ----- Look if the $p_filelist is really an array
122 View Code Duplication
        if (is_array($p_filelist)) {
123
            // ----- Call the create fct
124
            $v_result = PclTarHandleCreate($p_tarname, $p_filelist, $p_mode, $p_add_dir, $p_remove_dir);
125
        } // ----- Look if the $p_filelist is a string
126
        else {
127
            if (is_string($p_filelist)) {
128
                // ----- Create a list with the elements from the string
129
                $v_list = explode(' ', $p_filelist);
130
131
                // ----- Call the create fct
132
                $v_result = PclTarHandleCreate($p_tarname, $v_list, $p_mode, $p_add_dir, $p_remove_dir);
133
            } // ----- Invalid variable
134
            else {
135
                // ----- Error log
136
                PclErrorLog(-3, 'Invalid variable type p_filelist');
137
                $v_result = -3;
138
            }
139
        }
140
141
        // ----- Return
142
        TrFctEnd(__FILE__, __LINE__, $v_result);
143
144
        return $v_result;
145
    }
146
147
    // --------------------------------------------------------------------------------
148
149
    // --------------------------------------------------------------------------------
150
    // Function : PclTarAdd()
151
    // Description :
152
    //   PLEASE DO NOT USE ANY MORE THIS FUNCTION. Use PclTarAddList().
153
    //
154
    //   This function is maintained only for compatibility reason
155
    //
156
    // Parameters :
157
    //   $p_tarname : Name of an existing tar file
158
    //   $p_filelist : An array containing file or directory names, or
159
    //                 a string containing one filename or directory name, or
160
    //                 a string containing a list of filenames and/or directory
161
    //                 names separated by spaces.
162
    // Return Values :
163
    //   1 on success,
164
    //   Or an error code (see list on top).
165
    // --------------------------------------------------------------------------------
166
    /**
167
     * @param $p_tarname
168
     * @param $p_filelist
169
     *
170
     * @return int
171
     */
172
    function PclTarAdd($p_tarname, $p_filelist)
173
    {
174
        TrFctStart(__FILE__, __LINE__, 'PclTarAdd', "tar=$p_tarname, file=$p_filelist");
175
        $v_result      = 1;
176
        $v_list_detail = array();
177
178
        // ----- Extract the tar format from the extension
179
        if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
180
            // ----- Return
181
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
182
183
            return PclErrorCode();
184
        }
185
186
        // ----- Look if the $p_filelist is really an array
187
        if (is_array($p_filelist)) {
188
            // ----- Call the add fct
189
            $v_result = PclTarHandleAppend($p_tarname, $p_filelist, $p_mode, $v_list_detail, '', '');
190
        } // ----- Look if the $p_filelist is a string
191
        else {
192
            if (is_string($p_filelist)) {
193
                // ----- Create a list with the elements from the string
194
                $v_list = explode(' ', $p_filelist);
195
196
                // ----- Call the add fct
197
                $v_result = PclTarHandleAppend($p_tarname, $v_list, $p_mode, $v_list_detail, '', '');
198
            } // ----- Invalid variable
199
            else {
200
                // ----- Error log
201
                PclErrorLog(-3, 'Invalid variable type p_filelist');
202
                $v_result = -3;
203
            }
204
        }
205
206
        // ----- Cleaning
207
        unset($v_list_detail);
208
209
        // ----- Return
210
        TrFctEnd(__FILE__, __LINE__, $v_result);
211
212
        return $v_result;
213
    }
214
215
    // --------------------------------------------------------------------------------
216
217
    // --------------------------------------------------------------------------------
218
    // Function : PclTarAddList()
219
    // Description :
220
    //   Add a list of files or directories ($p_filelist) in the tar archive $p_tarname.
221
    //   The list can be an array of file/directory names or a string with names
222
    //   separated by one space.
223
    //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
224
    //   different from the real path of the file. This is usefull if you want to have PclTar
225
    //   running in any directory, and memorize relative path from an other directory.
226
    //   If $p_mode is not set it will be automatically computed from the $p_tarname
227
    //   extension (.tar, .tar.gz or .tgz).
228
    // Parameters :
229
    //   $p_tarname : Name of an existing tar file
230
    //   $p_filelist : An array containing file or directory names, or
231
    //                 a string containing one filename or directory name, or
232
    //                 a string containing a list of filenames and/or directory
233
    //                 names separated by spaces.
234
    //   $p_add_dir : Path to add in the filename path archived
235
    //   $p_remove_dir : Path to remove in the filename path archived
236
    //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
237
    // Return Values :
238
    //   1 on success,
239
    //   Or an error code (see list on top).
240
    // --------------------------------------------------------------------------------
241
    /**
242
     * @param        $p_tarname
243
     * @param        $p_filelist
244
     * @param string $p_add_dir
245
     * @param string $p_remove_dir
246
     * @param string $p_mode
247
     *
248
     * @return array|int
249
     */
250
    function PclTarAddList($p_tarname, $p_filelist, $p_add_dir = '', $p_remove_dir = '', $p_mode = '')
251
    {
252
        TrFctStart(__FILE__, __LINE__, 'PclTarAddList', "tar=$p_tarname, file=$p_filelist, p_add_dir='$p_add_dir', p_remove_dir='$p_remove_dir', mode=$p_mode");
253
        $v_result      = 1;
254
        $p_list_detail = array();
255
256
        // ----- Extract the tar format from the extension
257
        if (($p_mode == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
258
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
259
                // ----- Return
260
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
261
262
                return PclErrorCode();
263
            }
264
        }
265
266
        // ----- Look if the $p_filelist is really an array
267 View Code Duplication
        if (is_array($p_filelist)) {
268
            // ----- Call the add fct
269
            $v_result = PclTarHandleAppend($p_tarname, $p_filelist, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
270
        } // ----- Look if the $p_filelist is a string
271
        else {
272
            if (is_string($p_filelist)) {
273
                // ----- Create a list with the elements from the string
274
                $v_list = explode(' ', $p_filelist);
275
276
                // ----- Call the add fct
277
                $v_result = PclTarHandleAppend($p_tarname, $v_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
278
            } // ----- Invalid variable
279
            else {
280
                // ----- Error log
281
                PclErrorLog(-3, 'Invalid variable type p_filelist');
282
                $v_result = -3;
283
            }
284
        }
285
286
        // ----- Return
287
        if ($v_result != 1) {
288
            TrFctEnd(__FILE__, __LINE__, 0);
289
290
            return 0;
291
        }
292
        TrFctEnd(__FILE__, __LINE__, $p_list_detail);
293
294
        return $p_list_detail;
295
    }
296
297
    // --------------------------------------------------------------------------------
298
299
    // --------------------------------------------------------------------------------
300
    // Function : PclTarList()
301
    // Description :
302
    //   Gives the list of all the files present in the tar archive $p_tarname.
303
    //   The list is the function result, it will be 0 on error.
304
    //   Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
305
    //   function will determine the type of the archive.
306
    // Parameters :
307
    //   $p_tarname : Name of an existing tar file
308
    //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
309
    // Return Values :
310
    //  0 on error (Use PclErrorCode() and PclErrorString() for more info)
311
    //  or
312
    //  An array containing file properties. Each file properties is an array of
313
    //  properties.
314
    //  The properties (array field names) are :
315
    //    filename, size, mode, uid, gid, mtime, typeflag, status
316
    //  Exemple : $v_list = PclTarList("my.tar");
317
    //            for ($i=0; $i<count($v_list); ++$i)
318
    //              echo "Filename :'".$v_list[$i]['filename']."'<br>";
319
    // --------------------------------------------------------------------------------
320
    /**
321
     * @param        $p_tarname
322
     * @param string $p_mode
323
     *
324
     * @return array|int
325
     */
326 View Code Duplication
    function PclTarList($p_tarname, $p_mode = '')
327
    {
328
        TrFctStart(__FILE__, __LINE__, 'PclTarList', "tar=$p_tarname, mode='$p_mode'");
329
        $v_result = 1;
330
331
        // ----- Extract the tar format from the extension
332
        if (($p_mode == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
333
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
334
                // ----- Return
335
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
336
337
                return 0;
338
            }
339
        }
340
341
        // ----- Call the extracting fct
342
        $p_list = array();
343
        if (($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, 'list', '', $p_mode, '')) != 1) {
344
            unset($p_list);
345
            TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
346
347
            return 0;
348
        }
349
350
        // ----- Return
351
        TrFctEnd(__FILE__, __LINE__, $p_list);
352
353
        return $p_list;
354
    }
355
356
    // --------------------------------------------------------------------------------
357
358
    // --------------------------------------------------------------------------------
359
    // Function : PclTarExtract()
360
    // Description :
361
    //   Extract all the files present in the archive $p_tarname, in the directory
362
    //   $p_path. The relative path of the archived files are keep and become
363
    //   relative to $p_path.
364
    //   If a file with the same name already exists it will be replaced.
365
    //   If the path to the file does not exist, it will be created.
366
    //   Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
367
    //   function will determine the type of the archive.
368
    // Parameters :
369
    //   $p_tarname : Name of an existing tar file.
370
    //   $p_path : Path where the files will be extracted. The files will use
371
    //             their memorized path from $p_path.
372
    //             If $p_path is "", files will be extracted in "./".
373
    //   $p_remove_path : Path to remove (from the file memorized path) while writing the
374
    //                    extracted files. If the path does not match the file path,
375
    //                    the file is extracted with its memorized path.
376
    //                    $p_path and $p_remove_path are commulative.
377
    //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
378
    // Return Values :
379
    //   Same as PclTarList()
380
    // --------------------------------------------------------------------------------
381
    /**
382
     * @param        $p_tarname
383
     * @param string $p_path
384
     * @param string $p_remove_path
385
     * @param string $p_mode
386
     *
387
     * @return int
388
     */
389 View Code Duplication
    function PclTarExtract($p_tarname, $p_path = './', $p_remove_path = '', $p_mode = '')
390
    {
391
        TrFctStart(__FILE__, __LINE__, 'PclTarExtract', "tar='$p_tarname', path='$p_path', remove_path='$p_remove_path', mode='$p_mode'");
392
        $v_result = 1;
393
394
        // ----- Extract the tar format from the extension
395
        if (($p_mode == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
396
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
397
                // ----- Return
398
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
399
400
                return 0;
401
            }
402
        }
403
404
        // ----- Call the extracting fct
405
        if (($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, 'complete', $p_path, $p_mode, $p_remove_path)) != 1) {
406
            TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
407
408
            return 0;
409
        }
410
411
        // ----- Return
412
        TrFctEnd(__FILE__, __LINE__, $p_list);
413
414
        return $p_list;
415
    }
416
417
    // --------------------------------------------------------------------------------
418
419
    // --------------------------------------------------------------------------------
420
    // Function : PclTarExtractList()
421
    // Description :
422
    //   Extract the files present in the archive $p_tarname and specified in
423
    //   $p_filelist, in the directory
424
    //   $p_path. The relative path of the archived files are keep and become
425
    //   relative to $p_path.
426
    //   If a directory is spécified in the list, all the files from this directory
427
    //   will be extracted.
428
    //   If a file with the same name already exists it will be replaced.
429
    //   If the path to the file does not exist, it will be created.
430
    //   Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
431
    //   function will determine the type of the archive.
432
    // Parameters :
433
    //   $p_tarname : Name of an existing tar file
434
    //   $p_filelist : An array containing file or directory names, or
435
    //                 a string containing one filename or directory name, or
436
    //                 a string containing a list of filenames and/or directory
437
    //                 names separated by spaces.
438
    //   $p_path : Path where the files will be extracted. The files will use
439
    //             their memorized path from $p_path.
440
    //             If $p_path is "", files will be extracted in "./".
441
    //   $p_remove_path : Path to remove (from the file memorized path) while writing the
442
    //                    extracted files. If the path does not match the file path,
443
    //                    the file is extracted with its memorized path.
444
    //                    $p_path and $p_remove_path are commulative.
445
    //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
446
    // Return Values :
447
    //   Same as PclTarList()
448
    // --------------------------------------------------------------------------------
449
    /**
450
     * @param        $p_tarname
451
     * @param        $p_filelist
452
     * @param string $p_path
453
     * @param string $p_remove_path
454
     * @param string $p_mode
455
     *
456
     * @return int
457
     */
458 View Code Duplication
    function PclTarExtractList($p_tarname, $p_filelist, $p_path = './', $p_remove_path = '', $p_mode = '')
459
    {
460
        TrFctStart(__FILE__, __LINE__, 'PclTarExtractList', "tar=$p_tarname, list, path=$p_path, remove_path='$p_remove_path', mode='$p_mode'");
461
        $v_result = 1;
462
463
        // ----- Extract the tar format from the extension
464
        if (($p_mode == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
465
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
466
                // ----- Return
467
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
468
469
                return 0;
470
            }
471
        }
472
473
        // ----- Look if the $p_filelist is really an array
474
        if (is_array($p_filelist)) {
475
            // ----- Call the extracting fct
476
            if (($v_result = PclTarHandleExtract($p_tarname, $p_filelist, $p_list, 'partial', $p_path, $v_tar_mode, $p_remove_path)) != 1) {
477
                TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
478
479
                return 0;
480
            }
481
        } // ----- Look if the $p_filelist is a string
482
        else {
483
            if (is_string($p_filelist)) {
484
                // ----- Create a list with the elements from the string
485
                $v_list = explode(' ', $p_filelist);
486
487
                // ----- Call the extracting fct
488
                if (($v_result = PclTarHandleExtract($p_tarname, $v_list, $p_list, 'partial', $p_path, $v_tar_mode, $p_remove_path)) != 1) {
489
                    TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
490
491
                    return 0;
492
                }
493
            } // ----- Invalid variable
494
            else {
495
                // ----- Error log
496
                PclErrorLog(-3, 'Invalid variable type p_filelist');
497
498
                // ----- Return
499
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
500
501
                return 0;
502
            }
503
        }
504
505
        // ----- Return
506
        TrFctEnd(__FILE__, __LINE__, $p_list);
507
508
        return $p_list;
509
    }
510
511
    // --------------------------------------------------------------------------------
512
513
    // --------------------------------------------------------------------------------
514
    // Function : PclTarExtractIndex()
515
    // Description :
516
    //   Extract the files present in the archive $p_tarname and specified at
517
    //   the indexes in $p_index, in the directory
518
    //   $p_path. The relative path of the archived files are keep and become
519
    //   relative to $p_path.
520
    //   If a directory is specified in the list, the directory only is created. All
521
    //   the file stored in this archive for this directory
522
    //   are not extracted.
523
    //   If a file with the same name already exists it will be replaced.
524
    //   If the path to the file does not exist, it will be created.
525
    //   Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
526
    //   function will determine the type of the archive.
527
    // Parameters :
528
    //   $p_tarname : Name of an existing tar file
529
    //   $p_index : A single index (integer) or a string of indexes of files to
530
    //              extract. The form of the string is "0,4-6,8-12" with only numbers
531
    //              and '-' for range or ',' to separate ranges. No spaces or ';'
532
    //              are allowed.
533
    //   $p_path : Path where the files will be extracted. The files will use
534
    //             their memorized path from $p_path.
535
    //             If $p_path is "", files will be extracted in "./".
536
    //   $p_remove_path : Path to remove (from the file memorized path) while writing the
537
    //                    extracted files. If the path does not match the file path,
538
    //                    the file is extracted with its memorized path.
539
    //                    $p_path and $p_remove_path are commulative.
540
    //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
541
    // Return Values :
542
    //   Same as PclTarList()
543
    // --------------------------------------------------------------------------------
544
    /**
545
     * @param        $p_tarname
546
     * @param        $p_index
547
     * @param string $p_path
548
     * @param string $p_remove_path
549
     * @param string $p_mode
550
     *
551
     * @return int
552
     */
553 View Code Duplication
    function PclTarExtractIndex($p_tarname, $p_index, $p_path = './', $p_remove_path = '', $p_mode = '')
554
    {
555
        TrFctStart(__FILE__, __LINE__, 'PclTarExtractIndex', "tar=$p_tarname, index='$p_index', path=$p_path, remove_path='$p_remove_path', mode='$p_mode'");
556
        $v_result = 1;
557
558
        // ----- Extract the tar format from the extension
559
        if (($p_mode == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
560
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
561
                // ----- Return
562
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
563
564
                return 0;
565
            }
566
        }
567
568
        // ----- Look if the $p_index is really an integer
569
        if (is_int($p_index)) {
570
            // ----- Call the extracting fct
571
            if (($v_result = PclTarHandleExtractByIndexList($p_tarname, "$p_index", $p_list, $p_path, $p_remove_path, $v_tar_mode)) != 1) {
572
                TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
573
574
                return 0;
575
            }
576
        } // ----- Look if the $p_filelist is a string
577
        else {
578
            if (is_string($p_index)) {
579
                // ----- Call the extracting fct
580
                if (($v_result = PclTarHandleExtractByIndexList($p_tarname, $p_index, $p_list, $p_path, $p_remove_path, $v_tar_mode)) != 1) {
581
                    TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
582
583
                    return 0;
584
                }
585
            } // ----- Invalid variable
586
            else {
587
                // ----- Error log
588
                PclErrorLog(-3, "Invalid variable type $p_index");
589
590
                // ----- Return
591
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
592
593
                return 0;
594
            }
595
        }
596
597
        // ----- Return
598
        TrFctEnd(__FILE__, __LINE__, $p_list);
599
600
        return $p_list;
601
    }
602
603
    // --------------------------------------------------------------------------------
604
605
    // --------------------------------------------------------------------------------
606
    // Function : PclTarDelete()
607
    // Description :
608
    //   This function deletes from the archive $p_tarname the files which are listed
609
    //   in $p_filelist. $p_filelist can be a string with file names separated by
610
    //   spaces, or an array containing the file names.
611
    // Parameters :
612
    //   $p_tarname : Name of an existing tar file
613
    //   $p_filelist : An array or a string containing file names to remove from the
614
    //                 archive.
615
    //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
616
    // Return Values :
617
    //   List of the files which are kept in the archive (same format as PclTarList())
618
    // --------------------------------------------------------------------------------
619
    /**
620
     * @param        $p_tarname
621
     * @param        $p_filelist
622
     * @param string $p_mode
623
     *
624
     * @return int
625
     */
626
    function PclTarDelete($p_tarname, $p_filelist, $p_mode = '')
627
    {
628
        TrFctStart(__FILE__, __LINE__, 'PclTarDelete', "tar='$p_tarname', list='$p_filelist', mode='$p_mode'");
629
        $v_result = 1;
630
631
        // ----- Extract the tar format from the extension
632
        if (($p_mode == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
633
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
634
                // ----- Return
635
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
636
637
                return 0;
638
            }
639
        }
640
641
        // ----- Look if the $p_filelist is really an array
642
        if (is_array($p_filelist)) {
643
            // ----- Call the extracting fct
644
            if (($v_result = PclTarHandleDelete($p_tarname, $p_filelist, $p_list, $p_mode)) != 1) {
645
                TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
646
647
                return 0;
648
            }
649
        } // ----- Look if the $p_filelist is a string
650
        else {
651
            if (is_string($p_filelist)) {
652
                // ----- Create a list with the elements from the string
653
                $v_list = explode(' ', $p_filelist);
654
655
                // ----- Call the extracting fct
656
                if (($v_result = PclTarHandleDelete($p_tarname, $v_list, $p_list, $p_mode)) != 1) {
657
                    TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
658
659
                    return 0;
660
                }
661
            } // ----- Invalid variable
662
            else {
663
                // ----- Error log
664
                PclErrorLog(-3, 'Invalid variable type p_filelist');
665
666
                // ----- Return
667
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
668
669
                return 0;
670
            }
671
        }
672
673
        // ----- Return
674
        TrFctEnd(__FILE__, __LINE__, $p_list);
675
676
        return $p_list;
677
    }
678
679
    // --------------------------------------------------------------------------------
680
681
    // --------------------------------------------------------------------------------
682
    // Function : PclTarUpdate()
683
    // Description :
684
    //   This function updates the files in $p_filelist which are already in the
685
    //   $p_tarname archive with an older last modified date. If the file does not
686
    //   exist, it is added at the end of the archive.
687
    // Parameters :
688
    //   $p_tarname : Name of an existing tar file
689
    //   $p_filelist : An array or a string containing file names to update from the
690
    //                 archive.
691
    //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
692
    // Return Values :
693
    //   List of the files contained in the archive. The field status contains
694
    //   "updated", "not_updated", "added" or "ok" for the files not concerned.
695
    // --------------------------------------------------------------------------------
696
    /**
697
     * @param        $p_tarname
698
     * @param        $p_filelist
699
     * @param string $p_mode
700
     * @param string $p_add_dir
701
     * @param string $p_remove_dir
702
     *
703
     * @return int
704
     */
705 View Code Duplication
    function PclTarUpdate($p_tarname, $p_filelist, $p_mode = '', $p_add_dir = '', $p_remove_dir = '')
706
    {
707
        TrFctStart(__FILE__, __LINE__, 'PclTarUpdate', "tar='$p_tarname', list='$p_filelist', mode='$p_mode'");
708
        $v_result = 1;
709
710
        // ----- Extract the tar format from the extension
711
        if (($p_mode == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
712
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
713
                // ----- Return
714
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
715
716
                return 0;
717
            }
718
        }
719
720
        // ----- Look if the $p_filelist is really an array
721
        if (is_array($p_filelist)) {
722
            // ----- Call the extracting fct
723
            if (($v_result = PclTarHandleUpdate($p_tarname, $p_filelist, $p_list, $p_mode, $p_add_dir, $p_remove_dir)) != 1) {
724
                TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
725
726
                return 0;
727
            }
728
        } // ----- Look if the $p_filelist is a string
729
        else {
730
            if (is_string($p_filelist)) {
731
                // ----- Create a list with the elements from the string
732
                $v_list = explode(' ', $p_filelist);
733
734
                // ----- Call the extracting fct
735
                if (($v_result = PclTarHandleUpdate($p_tarname, $v_list, $p_list, $p_mode, $p_add_dir, $p_remove_dir)) != 1) {
736
                    TrFctEnd(__FILE__, __LINE__, 0, PclErrorString());
737
738
                    return 0;
739
                }
740
            } // ----- Invalid variable
741
            else {
742
                // ----- Error log
743
                PclErrorLog(-3, 'Invalid variable type p_filelist');
744
745
                // ----- Return
746
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
747
748
                return 0;
749
            }
750
        }
751
752
        // ----- Return
753
        TrFctEnd(__FILE__, __LINE__, $p_list);
754
755
        return $p_list;
756
    }
757
758
    // --------------------------------------------------------------------------------
759
760
    // --------------------------------------------------------------------------------
761
    // Function : PclTarMerge()
762
    // Description :
763
    //   This function add the content of $p_tarname_add at the end of $p_tarname.
764
    // Parameters :
765
    //   $p_tarname : Name of an existing tar file
766
    //   $p_tarname_add : Name of an existing tar file taht will be added at the end
767
    //                    of $p_tarname.
768
    //   $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
769
    //   $p_mode_add : 'tar' or 'tgz', if not set, will be determined by $p_tarname_add
770
    //                 extension
771
    // Return Values :
772
    //   List of the files contained in the archive. The field status contains
773
    //   "updated", "not_updated", "added" or "ok" for the files not concerned.
774
    // --------------------------------------------------------------------------------
775
    /**
776
     * @param        $p_tarname
777
     * @param        $p_tarname_add
778
     * @param string $p_mode
779
     * @param string $p_mode_add
780
     *
781
     * @return int
782
     */
783
    function PclTarMerge($p_tarname, $p_tarname_add, $p_mode = '', $p_mode_add = '')
784
    {
785
        TrFctStart(__FILE__, __LINE__, 'PclTarMerge', "tar='$p_tarname', tar_add='$p_tarname_add', mode='$p_mode', mode_add='$p_mode_add'");
786
        $v_result = 1;
787
788
        // ----- Check the parameters
789
        if (($p_tarname == '') || ($p_tarname_add == '')) {
790
            // ----- Error log
791
            PclErrorLog(-3, 'Invalid empty archive name');
792
793
            // ----- Return
794
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
795
796
            return PclErrorCode();
797
        }
798
799
        // ----- Extract the tar format from the extension
800
        if (($p_mode === '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
801
            if (($p_mode = PclTarHandleExtension($p_tarname)) == '') {
802
                // ----- Return
803
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
804
805
                return 0;
806
            }
807
        }
808
        if (($p_mode_add === '') || (($p_mode_add !== 'tar') && ($p_mode_add !== 'tgz'))) {
809
            if (($p_mode_add = PclTarHandleExtension($p_tarname_add)) == '') {
810
                // ----- Return
811
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
812
813
                return 0;
814
            }
815
        }
816
817
        // ----- Clear filecache
818
        clearstatcache();
819
820
        // ----- Check the file size
821 View Code Duplication
        if ((!is_file($p_tarname)) || (((($v_size = filesize($p_tarname)) % 512) != 0) && ($p_mode === 'tar'))) {
822
            // ----- Error log
823
            if (!is_file($p_tarname)) {
824
                PclErrorLog(-4, "Archive '$p_tarname' does not exist");
825
            } else {
826
                PclErrorLog(-6, "Archive '$p_tarname' has invalid size " . filesize($p_tarname) . '(not a 512 block multiple)');
827
            }
828
829
            // ----- Return
830
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
831
832
            return PclErrorCode();
833
        }
834 View Code Duplication
        if ((!is_file($p_tarname_add))
835
            || (((($v_size_add = filesize($p_tarname_add)) % 512) != 0)
836
                && ($p_mode_add === 'tar'))
837
        ) {
838
            // ----- Error log
839
            if (!is_file($p_tarname_add)) {
840
                PclErrorLog(-4, "Archive '$p_tarname_add' does not exist");
841
            } else {
842
                PclErrorLog(-6, "Archive '$p_tarname_add' has invalid size " . filesize($p_tarname_add) . '(not a 512 block multiple)');
843
            }
844
845
            // ----- Return
846
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
847
848
            return PclErrorCode();
849
        }
850
851
        // ----- Look for compressed archive
852
        if ($p_mode === 'tgz') {
853
            // ----- Open the file in read mode
854
            if (($p_tar = @gzopen($p_tarname, 'rb')) == 0) {
855
                // ----- Error log
856
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
857
858
                // ----- Return
859
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
860
861
                return PclErrorCode();
862
            }
863
864
            // ----- Open a temporary file in write mode
865
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
866
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
867
            if (($v_temp_tar = @gzopen($v_temp_tarname, 'wb')) == 0) {
868
                // ----- Close tar file
869
                gzclose($p_tar);
870
871
                // ----- Error log
872
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
873
874
                // ----- Return
875
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
876
877
                return PclErrorCode();
878
            }
879
880
            // ----- Read the first 512 bytes block
881
            $v_buffer = gzread($p_tar, 512);
882
883
            // ----- Read the following blocks but not the last one
884 View Code Duplication
            if (!gzeof($p_tar)) {
885
                TrFctMessage(__FILE__, __LINE__, 3, 'More than one 512 block file');
886
                $i = 1;
887
888
                // ----- Read new 512 block and write the already read
889
                do {
890
                    // ----- Write the already read block
891
                    $v_binary_data = pack('a512', "$v_buffer");
892
                    gzputs($v_temp_tar, $v_binary_data);
893
894
                    ++$i;
895
                    TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
896
897
                    // ----- Read next block
898
                    $v_buffer = gzread($p_tar, 512);
899
                } while (!gzeof($p_tar));
900
901
                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
902
            }
903
        } // ----- Look for uncompressed tar file
904
        else {
905
            if ($p_mode === 'tar') {
906
                // ----- Open the tar file
907
                if (($p_tar = fopen($p_tarname, 'r+b')) == 0) {
908
                    // ----- Error log
909
                    PclErrorLog(-1, "Unable to open file '$p_tarname' in binary write mode");
910
911
                    // ----- Return
912
                    TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
913
914
                    return PclErrorCode();
915
                }
916
917
                // ----- Go to the beginning of last block
918
                TrFctMessage(__FILE__, __LINE__, 4, 'Position before :' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
919
                fseek($p_tar, $v_size - 512);
920
                TrFctMessage(__FILE__, __LINE__, 4, 'Position after :' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
921
            } // ----- Look for unknown type
922
            else {
923
                // ----- Error log
924
                PclErrorLog(-3, "Invalid tar mode $p_mode");
925
926
                // ----- Return
927
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
928
929
                return PclErrorCode();
930
            }
931
        }
932
933
        // ----- Look for type of archive to add
934
        if ($p_mode_add === 'tgz') {
935
            TrFctMessage(__FILE__, __LINE__, 4, "Opening file $p_tarname_add");
936
937
            // ----- Open the file in read mode
938
            if (($p_tar_add = @gzopen($p_tarname_add, 'rb')) == 0) {
939
                // ----- Error log
940
                PclErrorLog(-2, "Unable to open file '$p_tarname_add' in binary read mode");
941
942
                // ----- Return
943
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
944
945
                return PclErrorCode();
946
            }
947
948
            // ----- Read the first 512 bytes block
949
            $v_buffer = gzread($p_tar_add, 512);
950
951
            // ----- Read the following blocks but not the last one
952
            if (!gzeof($p_tar_add)) {
953
                TrFctMessage(__FILE__, __LINE__, 3, 'More than one 512 block file');
954
                $i = 1;
955
956
                // ----- Read new 512 block and write the already read
957
                do {
958
                    // ----- Write the already read block
959
                    $v_binary_data = pack('a512', "$v_buffer");
960
                    if ($p_mode === 'tar') {
961
                        fwrite($p_tar, $v_binary_data);
962
                    } else {
963
                        gzputs($v_temp_tar, $v_binary_data);
964
                    }
965
966
                    ++$i;
967
                    TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
968
969
                    // ----- Read next block
970
                    $v_buffer = gzread($p_tar_add, 512);
971
                } while (!gzeof($p_tar_add));
972
973
                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
974
            }
975
976
            // ----- Close the files
977
            gzclose($p_tar_add);
978
        } // ----- Look for uncompressed tar file
979
        else {
980
            if ($p_mode === 'tar') {
981
                // ----- Open the file in read mode
982
                if (($p_tar_add = @fopen($p_tarname_add, 'rb')) == 0) {
983
                    // ----- Error log
984
                    PclErrorLog(-2, "Unable to open file '$p_tarname_add' in binary read mode");
985
986
                    // ----- Return
987
                    TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
988
989
                    return PclErrorCode();
990
                }
991
992
                // ----- Read the first 512 bytes block
993
                $v_buffer = fread($p_tar_add, 512);
994
995
                // ----- Read the following blocks but not the last one
996
                if (!feof($p_tar_add)) {
997
                    TrFctMessage(__FILE__, __LINE__, 3, 'More than one 512 block file');
998
                    $i = 1;
999
1000
                    // ----- Read new 512 block and write the already read
1001
                    do {
1002
                        // ----- Write the already read block
1003
                        $v_binary_data = pack('a512', "$v_buffer");
1004
                        if ($p_mode === 'tar') {
1005
                            fwrite($p_tar, $v_binary_data);
1006
                        } else {
1007
                            gzputs($v_temp_tar, $v_binary_data);
1008
                        }
1009
1010
                        ++$i;
1011
                        TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
1012
1013
                        // ----- Read next block
1014
                        $v_buffer = fread($p_tar_add, 512);
1015
                    } while (!feof($p_tar_add));
1016
1017
                    TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
1018
                }
1019
1020
                // ----- Close the files
1021
                fclose($p_tar_add);
1022
            }
1023
        }
1024
1025
        // ----- Call the footer of the tar archive
1026
        $v_result = PclTarHandleFooter($p_tar, $p_mode);
1027
1028
        // ----- Look for closing compressed archive
1029
        if ($p_mode === 'tgz') {
1030
            // ----- Close the files
1031
            gzclose($p_tar);
1032
            gzclose($v_temp_tar);
1033
1034
            // ----- Unlink tar file
1035
            if (!@unlink($p_tarname)) {
1036
                // ----- Error log
1037
                PclErrorLog(-11, "Error while deleting archive name $p_tarname");
1038
            }
1039
1040
            // ----- Rename tar file
1041
            if (!@rename($v_temp_tarname, $p_tarname)) {
1042
                // ----- Error log
1043
                PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
1044
1045
                // ----- Return
1046
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1047
1048
                return PclErrorCode();
1049
            }
1050
1051
            // ----- Return
1052
            TrFctEnd(__FILE__, __LINE__, $v_result);
1053
1054
            return $v_result;
1055
        } // ----- Look for closing uncompressed tar file
1056
        else {
1057
            if ($p_mode === 'tar') {
1058
                // ----- Close the tarfile
1059
                fclose($p_tar);
1060
            }
1061
        }
1062
1063
        // ----- Return
1064
        TrFctEnd(__FILE__, __LINE__, $v_result);
1065
1066
        return $v_result;
1067
    }
1068
1069
    // --------------------------------------------------------------------------------
1070
1071
    // --------------------------------------------------------------------------------
1072
    // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1073
    // *****                                                        *****
1074
    // *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       *****
1075
    // --------------------------------------------------------------------------------
1076
1077
    // --------------------------------------------------------------------------------
1078
    // Function : PclTarHandleCreate()
1079
    // Description :
1080
    // Parameters :
1081
    //   $p_tarname : Name of the tar file
1082
    //   $p_list : An array containing the file or directory names to add in the tar
1083
    //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1084
    // Return Values :
1085
    // --------------------------------------------------------------------------------
1086
    /**
1087
     * @param        $p_tarname
1088
     * @param        $p_list
1089
     * @param        $p_mode
1090
     * @param string $p_add_dir
1091
     * @param string $p_remove_dir
1092
     *
1093
     * @return int
1094
     */
1095
    function PclTarHandleCreate($p_tarname, $p_list, $p_mode, $p_add_dir = '', $p_remove_dir = '')
1096
    {
1097
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleCreate', "tar=$p_tarname, list, mode=$p_mode, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1098
        $v_result      = 1;
1099
        $v_list_detail = array();
1100
1101
        // ----- Check the parameters
1102 View Code Duplication
        if (($p_tarname == '') || (($p_mode !== 'tar') && ($p_mode !== 'tgz'))) {
1103
            // ----- Error log
1104
            if ($p_tarname == '') {
1105
                PclErrorLog(-3, 'Invalid empty archive name');
1106
            } else {
1107
                PclErrorLog(-3, "Unknown mode '$p_mode'");
1108
            }
1109
1110
            // ----- Return
1111
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1112
1113
            return PclErrorCode();
1114
        }
1115
1116
        // ----- Look for tar file
1117
        if ($p_mode === 'tar') {
1118
            // ----- Open the tar file
1119
            if (($p_tar = fopen($p_tarname, 'wb')) == 0) {
1120
                // ----- Error log
1121
                PclErrorLog(-1, "Unable to open file [$p_tarname] in binary write mode");
1122
1123
                // ----- Return
1124
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1125
1126
                return PclErrorCode();
1127
            }
1128
1129
            // ----- Call the adding fct inside the tar
1130
            if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir)) == 1) {
1131
                // ----- Call the footer of the tar archive
1132
                $v_result = PclTarHandleFooter($p_tar, $p_mode);
1133
            }
1134
1135
            // ----- Close the tarfile
1136
            fclose($p_tar);
1137
        } // ----- Look for tgz file
1138
        else {
1139
            // ----- Open the tar file
1140
            if (($p_tar = @gzopen($p_tarname, 'wb')) == 0) {
1141
                // ----- Error log
1142
                PclErrorLog(-1, "Unable to open file [$p_tarname] in binary write mode");
1143
1144
                // ----- Return
1145
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1146
1147
                return PclErrorCode();
1148
            }
1149
1150
            // ----- Call the adding fct inside the tar
1151
            if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir)) == 1) {
1152
                // ----- Call the footer of the tar archive
1153
                $v_result = PclTarHandleFooter($p_tar, $p_mode);
1154
            }
1155
1156
            // ----- Close the tarfile
1157
            gzclose($p_tar);
1158
        }
1159
1160
        // ----- Return
1161
        TrFctEnd(__FILE__, __LINE__, $v_result);
1162
1163
        return $v_result;
1164
    }
1165
1166
    // --------------------------------------------------------------------------------
1167
1168
    // --------------------------------------------------------------------------------
1169
    // Function : PclTarHandleAppend()
1170
    // Description :
1171
    // Parameters :
1172
    //   $p_tarname : Name of the tar file
1173
    //   $p_list : An array containing the file or directory names to add in the tar
1174
    //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1175
    // Return Values :
1176
    // --------------------------------------------------------------------------------
1177
    /**
1178
     * @param $p_tarname
1179
     * @param $p_list
1180
     * @param $p_mode
1181
     * @param $p_list_detail
1182
     * @param $p_add_dir
1183
     * @param $p_remove_dir
1184
     *
1185
     * @return int
1186
     */
1187
    function PclTarHandleAppend($p_tarname, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir)
1188
    {
1189
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleAppend', "tar=$p_tarname, list, mode=$p_mode");
1190
        $v_result = 1;
1191
1192
        // ----- Check the parameters
1193
        if ($p_tarname == '') {
1194
            // ----- Error log
1195
            PclErrorLog(-3, 'Invalid empty archive name');
1196
1197
            // ----- Return
1198
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1199
1200
            return PclErrorCode();
1201
        }
1202
1203
        clearstatcache();
1204
1205
        // ----- Check the file size
1206 View Code Duplication
        if ((!is_file($p_tarname)) || (((($v_size = filesize($p_tarname)) % 512) != 0) && ($p_mode === 'tar'))) {
1207
            // ----- Error log
1208
            if (!is_file($p_tarname)) {
1209
                PclErrorLog(-4, "Archive '$p_tarname' does not exist");
1210
            } else {
1211
                PclErrorLog(-6, "Archive '$p_tarname' has invalid size " . filesize($p_tarname) . '(not a 512 block multiple)');
1212
            }
1213
1214
            // ----- Return
1215
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1216
1217
            return PclErrorCode();
1218
        }
1219
1220
        // ----- Look for compressed archive
1221
        if ($p_mode === 'tgz') {
1222
            // ----- Open the file in read mode
1223
            if (($p_tar = @gzopen($p_tarname, 'rb')) == 0) {
1224
                // ----- Error log
1225
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
1226
1227
                // ----- Return
1228
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1229
1230
                return PclErrorCode();
1231
            }
1232
1233
            // ----- Open a temporary file in write mode
1234
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
1235
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
1236
            if (($v_temp_tar = @gzopen($v_temp_tarname, 'wb')) == 0) {
1237
                // ----- Close tar file
1238
                gzclose($p_tar);
1239
1240
                // ----- Error log
1241
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
1242
1243
                // ----- Return
1244
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1245
1246
                return PclErrorCode();
1247
            }
1248
1249
            // ----- Read the first 512 bytes block
1250
            $v_buffer = gzread($p_tar, 512);
1251
1252
            // ----- Read the following blocks but not the last one
1253 View Code Duplication
            if (!gzeof($p_tar)) {
1254
                TrFctMessage(__FILE__, __LINE__, 3, 'More than one 512 block file');
1255
                $i = 1;
1256
1257
                // ----- Read new 512 block and write the already read
1258
                do {
1259
                    // ----- Write the already read block
1260
                    $v_binary_data = pack('a512', "$v_buffer");
1261
                    gzputs($v_temp_tar, $v_binary_data);
1262
1263
                    ++$i;
1264
                    TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
1265
1266
                    // ----- Read next block
1267
                    $v_buffer = gzread($p_tar, 512);
1268
                } while (!gzeof($p_tar));
1269
1270
                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
1271
            }
1272
1273
            // ----- Call the adding fct inside the tar
1274 View Code Duplication
            if (($v_result = PclTarHandleAddList($v_temp_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir)) == 1) {
1275
                // ----- Call the footer of the tar archive
1276
                $v_result = PclTarHandleFooter($v_temp_tar, $p_mode);
1277
            }
1278
1279
            // ----- Close the files
1280
            gzclose($p_tar);
1281
            gzclose($v_temp_tar);
1282
1283
            // ----- Unlink tar file
1284
            if (!@unlink($p_tarname)) {
1285
                // ----- Error log
1286
                PclErrorLog(-11, "Error while deleting archive name $p_tarname");
1287
            }
1288
1289
            // ----- Rename tar file
1290
            if (!@rename($v_temp_tarname, $p_tarname)) {
1291
                // ----- Error log
1292
                PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
1293
1294
                // ----- Return
1295
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1296
1297
                return PclErrorCode();
1298
            }
1299
1300
            // ----- Return
1301
            TrFctEnd(__FILE__, __LINE__, $v_result);
1302
1303
            return $v_result;
1304
        } // ----- Look for uncompressed tar file
1305
        else {
1306
            if ($p_mode === 'tar') {
1307
                // ----- Open the tar file
1308
                if (($p_tar = fopen($p_tarname, 'r+b')) == 0) {
1309
                    // ----- Error log
1310
                    PclErrorLog(-1, "Unable to open file '$p_tarname' in binary write mode");
1311
1312
                    // ----- Return
1313
                    TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1314
1315
                    return PclErrorCode();
1316
                }
1317
1318
                // ----- Go to the beginning of last block
1319
                TrFctMessage(__FILE__, __LINE__, 4, 'Position before :' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
1320
                fseek($p_tar, $v_size - 512);
1321
                TrFctMessage(__FILE__, __LINE__, 4, 'Position after :' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
1322
1323
                // ----- Call the adding fct inside the tar
1324 View Code Duplication
                if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir)) == 1) {
1325
                    // ----- Call the footer of the tar archive
1326
                    $v_result = PclTarHandleFooter($p_tar, $p_mode);
1327
                }
1328
1329
                // ----- Close the tarfile
1330
                fclose($p_tar);
1331
            } // ----- Look for unknown type
1332
            else {
1333
                // ----- Error log
1334
                PclErrorLog(-3, "Invalid tar mode $p_mode");
1335
1336
                // ----- Return
1337
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1338
1339
                return PclErrorCode();
1340
            }
1341
        }
1342
1343
        // ----- Return
1344
        TrFctEnd(__FILE__, __LINE__, $v_result);
1345
1346
        return $v_result;
1347
    }
1348
1349
    // --------------------------------------------------------------------------------
1350
1351
    // --------------------------------------------------------------------------------
1352
    // Function : PclTarHandleAddList()
1353
    // Description :
1354
    //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
1355
    //   different from the real path of the file. This is usefull if you want to have PclTar
1356
    //   running in any directory, and memorize relative path from an other directory.
1357
    // Parameters :
1358
    //   $p_tar : File descriptor of the tar archive
1359
    //   $p_list : An array containing the file or directory names to add in the tar
1360
    //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1361
    //   $p_list_detail : list of added files with their properties (specially the status field)
1362
    //   $p_add_dir : Path to add in the filename path archived
1363
    //   $p_remove_dir : Path to remove in the filename path archived
1364
    // Return Values :
1365
    // --------------------------------------------------------------------------------
1366
    /**
1367
     * @param $p_tar
1368
     * @param $p_list
1369
     * @param $p_mode
1370
     * @param $p_list_detail
1371
     * @param $p_add_dir
1372
     * @param $p_remove_dir
1373
     *
1374
     * @return int
1375
     */
1376
    function PclTarHandleAddList($p_tar, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir)
1377
    {
1378
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleAddList', "tar='$p_tar', list, mode='$p_mode', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1379
        $v_result = 1;
1380
        $v_header = array();
1381
1382
        // ----- Recuperate the current number of elt in list
1383
        $v_nb = count($p_list_detail);
1384
1385
        // ----- Check the parameters
1386 View Code Duplication
        if ($p_tar == 0) {
1387
            // ----- Error log
1388
            PclErrorLog(-3, 'Invalid file descriptor in file ' . __FILE__ . ', line ' . __LINE__);
1389
1390
            // ----- Return
1391
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1392
1393
            return PclErrorCode();
1394
        }
1395
1396
        // ----- Check the arguments
1397
        if (count($p_list) == 0) {
1398
            // ----- Error log
1399
            PclErrorLog(-3, 'Invalid file list parameter (invalid or empty list)');
1400
1401
            // ----- Return
1402
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1403
1404
            return PclErrorCode();
1405
        }
1406
1407
        // ----- Loop on the files
1408
        for ($j = 0; ($j < count($p_list)) && ($v_result == 1); ++$j) {
1409
            // ----- Recuperate the filename
1410
            $p_filename = $p_list[$j];
1411
1412
            TrFctMessage(__FILE__, __LINE__, 2, "Looking for file [$p_filename]");
1413
1414
            // ----- Skip empty file names
1415
            if ($p_filename == '') {
1416
                TrFctMessage(__FILE__, __LINE__, 2, 'Skip empty filename');
1417
                continue;
1418
            }
1419
1420
            // ----- Check the filename
1421
            if (!file_exists($p_filename)) {
1422
                // ----- Error log
1423
                TrFctMessage(__FILE__, __LINE__, 2, "File '$p_filename' does not exists");
1424
                PclErrorLog(-4, "File '$p_filename' does not exists");
1425
1426
                // ----- Return
1427
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1428
1429
                return PclErrorCode();
1430
            }
1431
1432
            // ----- Check the path length
1433
            if (strlen($p_filename) > 99) {
1434
                // ----- Error log
1435
                PclErrorLog(-5, "File name is too long (max. 99) : '$p_filename'");
1436
1437
                // ----- Return
1438
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1439
1440
                return PclErrorCode();
1441
            }
1442
1443
            TrFctMessage(__FILE__, __LINE__, 4, 'File position before header =' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
1444
1445
            // ----- Add the file
1446 View Code Duplication
            if (($v_result = PclTarHandleAddFile($p_tar, $p_filename, $p_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1) {
1447
                // ----- Return status
1448
                TrFctEnd(__FILE__, __LINE__, $v_result);
1449
1450
                return $v_result;
1451
            }
1452
1453
            // ----- Store the file infos
1454
            $p_list_detail[$v_nb++] = $v_header;
1455
1456
            // ----- Look for directory
1457
            if (is_dir($p_filename)) {
1458
                TrFctMessage(__FILE__, __LINE__, 2, "$p_filename is a directory");
1459
1460
                // ----- Look for path
1461
                $v_path = '';
1462
                if ($p_filename !== '.') {
1463
                    $v_path = $p_filename . '/';
1464
                }
1465
1466
                // ----- Read the directory for files and sub-directories
1467
                $p_hdir  = opendir($p_filename);
1468
                $p_hitem = readdir($p_hdir); // '.' directory
1469
                $p_hitem = readdir($p_hdir); // '..' directory
1470
                while ($p_hitem = readdir($p_hdir)) {
1471
                    // ----- Look for a file
1472
                    if (is_file($v_path . $p_hitem)) {
1473
                        TrFctMessage(__FILE__, __LINE__, 4, "Add the file '" . $v_path . $p_hitem . "'");
1474
1475
                        // ----- Add the file
1476 View Code Duplication
                        if (($v_result = PclTarHandleAddFile($p_tar, $v_path . $p_hitem, $p_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1) {
1477
                            // ----- Return status
1478
                            TrFctEnd(__FILE__, __LINE__, $v_result);
1479
1480
                            return $v_result;
1481
                        }
1482
1483
                        // ----- Store the file infos
1484
                        $p_list_detail[$v_nb++] = $v_header;
1485
                    } // ----- Recursive call to PclTarHandleAddFile()
1486
                    else {
1487
                        TrFctMessage(__FILE__, __LINE__, 4, "'" . $v_path . $p_hitem . "' is a directory");
1488
1489
                        // ----- Need an array as parameter
1490
                        $p_temp_list[0] = $v_path . $p_hitem;
1491
                        $v_result       = PclTarHandleAddList($p_tar, $p_temp_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
1492
                    }
1493
                }
1494
1495
                // ----- Free memory for the recursive loop
1496
                unset($p_temp_list, $p_hdir, $p_hitem);
1497
            } else {
1498
                TrFctMessage(__FILE__, __LINE__, 4, 'File position after blocks =' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
1499
            }
1500
        }
1501
1502
        // ----- Return
1503
        TrFctEnd(__FILE__, __LINE__, $v_result);
1504
1505
        return $v_result;
1506
    }
1507
1508
    // --------------------------------------------------------------------------------
1509
1510
    // --------------------------------------------------------------------------------
1511
    // Function : PclTarHandleAddFile()
1512
    // Description :
1513
    // Parameters :
1514
    // Return Values :
1515
    // --------------------------------------------------------------------------------
1516
    /**
1517
     * @param $p_tar
1518
     * @param $p_filename
1519
     * @param $p_mode
1520
     * @param $p_header
1521
     * @param $p_add_dir
1522
     * @param $p_remove_dir
1523
     *
1524
     * @return int
1525
     */
1526
    function PclTarHandleAddFile($p_tar, $p_filename, $p_mode, &$p_header, $p_add_dir, $p_remove_dir)
1527
    {
1528
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleAddFile', "tar='$p_tar', filename='$p_filename', p_mode='$p_mode', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1529
        $v_result = 1;
1530
1531
        // ----- Check the parameters
1532 View Code Duplication
        if ($p_tar == 0) {
1533
            // ----- Error log
1534
            PclErrorLog(-3, 'Invalid file descriptor in file ' . __FILE__ . ', line ' . __LINE__);
1535
1536
            // ----- Return
1537
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1538
1539
            return PclErrorCode();
1540
        }
1541
1542
        // ----- Skip empty file names
1543
        if ($p_filename == '') {
1544
            // ----- Error log
1545
            PclErrorLog(-3, 'Invalid file list parameter (invalid or empty list)');
1546
1547
            // ----- Return
1548
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1549
1550
            return PclErrorCode();
1551
        }
1552
1553
        // ----- Calculate the stored filename
1554
        $v_stored_filename = $p_filename;
1555
        if ($p_remove_dir != '') {
1556
            if (substr($p_remove_dir, -1) !== '/') {
1557
                $p_remove_dir .= '/';
1558
            }
1559
1560
            if ((0 === strpos($p_filename, './')) || (0 === strpos($p_remove_dir, './'))) {
1561 View Code Duplication
                if ((0 === strpos($p_filename, './')) && (0 !== strpos($p_remove_dir, './'))) {
1562
                    $p_remove_dir = './' . $p_remove_dir;
1563
                }
1564 View Code Duplication
                if ((0 !== strpos($p_filename, './')) && (0 === strpos($p_remove_dir, './'))) {
1565
                    $p_remove_dir = substr($p_remove_dir, 2);
1566
                }
1567
            }
1568
1569
            if (0 === strpos($p_filename, $p_remove_dir)) {
1570
                $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
1571
                TrFctMessage(__FILE__, __LINE__, 3, "Remove path '$p_remove_dir' in file '$p_filename' = '$v_stored_filename'");
1572
            }
1573
        }
1574
        if ($p_add_dir != '') {
1575
            if (substr($p_add_dir, -1) === '/') {
1576
                $v_stored_filename = $p_add_dir . $v_stored_filename;
1577
            } else {
1578
                $v_stored_filename = $p_add_dir . '/' . $v_stored_filename;
1579
            }
1580
            TrFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
1581
        }
1582
1583
        // ----- Check the path length
1584
        if (strlen($v_stored_filename) > 99) {
1585
            // ----- Error log
1586
            PclErrorLog(-5, "Stored file name is too long (max. 99) : '$v_stored_filename'");
1587
1588
            // ----- Return
1589
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1590
1591
            return PclErrorCode();
1592
        }
1593
1594
        // ----- Look for a file
1595
        if (is_file($p_filename)) {
1596
            // ----- Open the source file
1597
            if (($v_file = fopen($p_filename, 'rb')) == 0) {
1598
                // ----- Error log
1599
                PclErrorLog(-2, "Unable to open file '$p_filename' in binary read mode");
1600
1601
                // ----- Return
1602
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1603
1604
                return PclErrorCode();
1605
            }
1606
1607
            // ----- Call the header generation
1608 View Code Duplication
            if (($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename)) != 1) {
1609
                // ----- Return status
1610
                TrFctEnd(__FILE__, __LINE__, $v_result);
1611
1612
                return $v_result;
1613
            }
1614
1615
            TrFctMessage(__FILE__, __LINE__, 4, 'File position after header =' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
1616
1617
            // ----- Read the file by 512 octets blocks
1618
            $i = 0;
1619
            while (($v_buffer = fread($v_file, 512)) != '') {
1620
                $v_binary_data = pack('a512', "$v_buffer");
1621
                if ($p_mode === 'tar') {
1622
                    fwrite($p_tar, $v_binary_data);
1623
                } else {
1624
                    gzputs($p_tar, $v_binary_data);
1625
                }
1626
                ++$i;
1627
            }
1628
            TrFctMessage(__FILE__, __LINE__, 2, "$i 512 bytes blocks");
1629
1630
            // ----- Close the file
1631
            fclose($v_file);
1632
1633
            TrFctMessage(__FILE__, __LINE__, 4, 'File position after blocks =' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
1634
        } // ----- Look for a directory
1635
        else {
1636
            // ----- Call the header generation
1637 View Code Duplication
            if (($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename)) != 1) {
1638
                // ----- Return status
1639
                TrFctEnd(__FILE__, __LINE__, $v_result);
1640
1641
                return $v_result;
1642
            }
1643
1644
            TrFctMessage(__FILE__, __LINE__, 4, 'File position after header =' . ($p_mode === 'tar' ? ftell($p_tar) : gztell($p_tar)));
1645
        }
1646
1647
        // ----- Return
1648
        TrFctEnd(__FILE__, __LINE__, $v_result);
1649
1650
        return $v_result;
1651
    }
1652
1653
    // --------------------------------------------------------------------------------
1654
1655
    // --------------------------------------------------------------------------------
1656
    // Function : PclTarHandleHeader()
1657
    // Description :
1658
    //   This function creates in the TAR $p_tar, the TAR header for the file
1659
    //   $p_filename.
1660
    //
1661
    //   1. The informations needed to compose the header are recuperated and formatted
1662
    //   2. Two binary strings are composed for the first part of the header, before
1663
    //      and after checksum field.
1664
    //   3. The checksum is calculated from the two binary strings
1665
    //   4. The header is write in the tar file (first binary string, binary string
1666
    //      for checksum and last binary string).
1667
    // Parameters :
1668
    //   $p_tar : a valid file descriptor, opened in write mode,
1669
    //   $p_filename : The name of the file the header is for,
1670
    //   $p_mode : The mode of the archive ("tar" or "tgz").
1671
    //   $p_header : A pointer to a array where will be set the file properties
1672
    // Return Values :
1673
    // --------------------------------------------------------------------------------
1674
    /**
1675
     * @param $p_tar
1676
     * @param $p_filename
1677
     * @param $p_mode
1678
     * @param $p_header
1679
     * @param $p_stored_filename
1680
     *
1681
     * @return int
1682
     */
1683
    function PclTarHandleHeader($p_tar, $p_filename, $p_mode, &$p_header, $p_stored_filename)
1684
    {
1685
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleHeader', "tar=$p_tar, file='$p_filename', mode='$p_mode', stored_filename='$p_stored_filename'");
1686
        $v_result = 1;
1687
1688
        // ----- Check the parameters
1689 View Code Duplication
        if (($p_tar == 0) || ($p_filename == '')) {
1690
            // ----- Error log
1691
            PclErrorLog(-3, 'Invalid file descriptor in file ' . __FILE__ . ', line ' . __LINE__);
1692
1693
            // ----- Return
1694
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1695
1696
            return PclErrorCode();
1697
        }
1698
1699
        // ----- Filename (reduce the path of stored name)
1700
        if ($p_stored_filename == '') {
1701
            $p_stored_filename = $p_filename;
1702
        }
1703
        $v_reduce_filename = PclTarHandlePathReduction($p_stored_filename);
1704
        TrFctMessage(__FILE__, __LINE__, 2, "Filename (reduced) '$v_reduce_filename', strlen " . strlen($v_reduce_filename));
1705
1706
        // ----- Get file info
1707
        $v_info = stat($p_filename);
1708
        $v_uid  = sprintf('%6s ', decoct($v_info[4]));
1709
        $v_gid  = sprintf('%6s ', decoct($v_info[5]));
1710
        TrFctMessage(__FILE__, __LINE__, 3, "uid=$v_uid, gid=$v_gid");
1711
        $v_perms = sprintf('%6s ', decoct(fileperms($p_filename)));
1712
        TrFctMessage(__FILE__, __LINE__, 3, "file permissions $v_perms");
1713
1714
        // ----- File mtime
1715
        $v_mtime_data = filemtime($p_filename);
1716
        TrFctMessage(__FILE__, __LINE__, 2, "File mtime : $v_mtime_data");
1717
        $v_mtime = sprintf('%11s', decoct($v_mtime_data));
1718
1719
        // ----- File typeflag
1720
        // '0' or '\0' is the code for regular file
1721
        // '5' is directory
1722
        if (is_dir($p_filename)) {
1723
            $v_typeflag = '5';
1724
            $v_size     = 0;
1725
        } else {
1726
            $v_typeflag = '';
1727
1728
            // ----- Get the file size
1729
            clearstatcache();
1730
            $v_size = filesize($p_filename);
1731
        }
1732
1733
        TrFctMessage(__FILE__, __LINE__, 2, "File size : $v_size");
1734
        $v_size = sprintf('%11s ', decoct($v_size));
1735
1736
        TrFctMessage(__FILE__, __LINE__, 2, "File typeflag : $v_typeflag");
1737
1738
        // ----- Linkname
1739
        $v_linkname = '';
1740
1741
        // ----- Magic
1742
        $v_magic = '';
1743
1744
        // ----- Version
1745
        $v_version = '';
1746
1747
        // ----- uname
1748
        $v_uname = '';
1749
1750
        // ----- gname
1751
        $v_gname = '';
1752
1753
        // ----- devmajor
1754
        $v_devmajor = '';
1755
1756
        // ----- devminor
1757
        $v_devminor = '';
1758
1759
        // ----- prefix
1760
        $v_prefix = '';
1761
1762
        // ----- Compose the binary string of the header in two parts arround the checksum position
1763
        $v_binary_data_first = pack('a100a8a8a8a12A12', $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
1764
        $v_binary_data_last  = pack('a1a100a6a2a32a32a8a8a155a12', $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '');
1765
1766
        // ----- Calculate the checksum
1767
        $v_checksum = 0;
1768
        // ..... First part of the header
1769
        for ($i = 0; $i < 148; ++$i) {
1770
            $v_checksum += ord(substr($v_binary_data_first, $i, 1));
1771
        }
1772
        // ..... Ignore the checksum value and replace it by ' ' (space)
1773
        for ($i = 148; $i < 156; ++$i) {
1774
            $v_checksum += ord(' ');
1775
        }
1776
        // ..... Last part of the header
1777
        for ($i = 156, $j = 0; $i < 512; ++$i, ++$j) {
1778
            $v_checksum += ord(substr($v_binary_data_last, $j, 1));
1779
        }
1780
        TrFctMessage(__FILE__, __LINE__, 3, "Calculated checksum : $v_checksum");
1781
1782
        // ----- Write the first 148 bytes of the header in the archive
1783
        if ($p_mode === 'tar') {
1784
            fwrite($p_tar, $v_binary_data_first, 148);
1785
        } else {
1786
            gzputs($p_tar, $v_binary_data_first, 148);
1787
        }
1788
1789
        // ----- Write the calculated checksum
1790
        $v_checksum    = sprintf('%6s ', decoct($v_checksum));
1791
        $v_binary_data = pack('a8', $v_checksum);
1792
        if ($p_mode === 'tar') {
1793
            fwrite($p_tar, $v_binary_data, 8);
1794
        } else {
1795
            gzputs($p_tar, $v_binary_data, 8);
1796
        }
1797
1798
        // ----- Write the last 356 bytes of the header in the archive
1799
        if ($p_mode === 'tar') {
1800
            fwrite($p_tar, $v_binary_data_last, 356);
1801
        } else {
1802
            gzputs($p_tar, $v_binary_data_last, 356);
1803
        }
1804
1805
        // ----- Set the properties in the header "structure"
1806
        $p_header['filename'] = $v_reduce_filename;
1807
        $p_header['mode']     = $v_perms;
1808
        $p_header['uid']      = $v_uid;
1809
        $p_header['gid']      = $v_gid;
1810
        $p_header['size']     = $v_size;
1811
        $p_header['mtime']    = $v_mtime;
1812
        $p_header['typeflag'] = $v_typeflag;
1813
        $p_header['status']   = 'added';
1814
1815
        // ----- Return
1816
        TrFctEnd(__FILE__, __LINE__, $v_result);
1817
1818
        return $v_result;
1819
    }
1820
1821
    // --------------------------------------------------------------------------------
1822
1823
    // --------------------------------------------------------------------------------
1824
    // Function : PclTarHandleFooter()
1825
    // Description :
1826
    // Parameters :
1827
    // Return Values :
1828
    // --------------------------------------------------------------------------------
1829
    /**
1830
     * @param $p_tar
1831
     * @param $p_mode
1832
     *
1833
     * @return int
1834
     */
1835
    function PclTarHandleFooter($p_tar, $p_mode)
1836
    {
1837
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleFooter', "tar='$p_tar', p_mode=$p_mode");
1838
        $v_result = 1;
1839
1840
        // ----- Write the last 0 filled block for end of archive
1841
        $v_binary_data = pack('a512', '');
1842
        if ($p_mode === 'tar') {
1843
            fwrite($p_tar, $v_binary_data);
1844
        } else {
1845
            gzputs($p_tar, $v_binary_data);
1846
        }
1847
1848
        // ----- Return
1849
        TrFctEnd(__FILE__, __LINE__, $v_result);
1850
1851
        return $v_result;
1852
    }
1853
1854
    // --------------------------------------------------------------------------------
1855
1856
    // --------------------------------------------------------------------------------
1857
    // Function : PclTarHandleExtract()
1858
    // Description :
1859
    // Parameters :
1860
    //   $p_tarname : Filename of the tar (or tgz) archive
1861
    //   $p_file_list : An array which contains the list of files to extract, this
1862
    //                  array may be empty when $p_mode is 'complete'
1863
    //   $p_list_detail : An array where will be placed the properties of  each extracted/listed file
1864
    //   $p_mode : 'complete' will extract all files from the archive,
1865
    //             'partial' will look for files in $p_file_list
1866
    //             'list' will only list the files from the archive without any extract
1867
    //   $p_path : Path to add while writing the extracted files
1868
    //   $p_tar_mode : 'tar' for GNU TAR archive, 'tgz' for compressed archive
1869
    //   $p_remove_path : Path to remove (from the file memorized path) while writing the
1870
    //                    extracted files. If the path does not match the file path,
1871
    //                    the file is extracted with its memorized path.
1872
    //                    $p_remove_path does not apply to 'list' mode.
1873
    //                    $p_path and $p_remove_path are commulative.
1874
    // Return Values :
1875
    // --------------------------------------------------------------------------------
1876
    /**
1877
     * @param $p_tarname
1878
     * @param $p_file_list
1879
     * @param $p_list_detail
1880
     * @param $p_mode
1881
     * @param $p_path
1882
     * @param $p_tar_mode
1883
     * @param $p_remove_path
1884
     *
1885
     * @return int
1886
     */
1887
    function PclTarHandleExtract(
1888
        $p_tarname,
1889
        $p_file_list,
1890
        &$p_list_detail,
1891
        $p_mode,
1892
        $p_path,
1893
        $p_tar_mode,
1894
        $p_remove_path
1895
    ) {
1896
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtract', "archive='$p_tarname', list, mode=$p_mode, path=$p_path, tar_mode=$p_tar_mode, remove_path='$p_remove_path'");
1897
        $v_result      = 1;
1898
        $v_nb          = 0;
1899
        $v_extract_all = true;
1900
        $v_listing     = false;
1901
1902
        // ----- Check the path
1903
        //if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../")))
1904
        if ($p_path == '') {
1905
            $p_path = './' . $p_path;
1906
        }
1907
1908
        // ----- Look for path to remove format (should end by /)
1909
        if (($p_remove_path != '') && (substr($p_remove_path, -1) !== '/')) {
1910
            $p_remove_path .= '/';
1911
        }
1912
        $p_remove_path_size = strlen($p_remove_path);
1913
1914
        // ----- Study the mode
1915
        switch ($p_mode) {
1916
            case 'complete':
1917
                // ----- Flag extract of all files
1918
                $v_extract_all = true;
1919
                $v_listing     = false;
1920
                break;
1921
            case 'partial':
1922
                // ----- Flag extract of specific files
1923
                $v_extract_all = false;
1924
                $v_listing     = false;
1925
                break;
1926
            case 'list':
1927
                // ----- Flag list of all files
1928
                $v_extract_all = false;
1929
                $v_listing     = true;
1930
                break;
1931
            default:
1932
                // ----- Error log
1933
                PclErrorLog(-3, "Invalid extract mode ($p_mode)");
1934
1935
                // ----- Return
1936
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1937
1938
                return PclErrorCode();
1939
        }
1940
1941
        // ----- Open the tar file
1942 View Code Duplication
        if ($p_tar_mode === 'tar') {
1943
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in binary read mode');
1944
            $v_tar = fopen($p_tarname, 'rb');
1945
        } else {
1946
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in gzip binary read mode');
1947
            $v_tar = @gzopen($p_tarname, 'rb');
1948
        }
1949
1950
        // ----- Check that the archive is open
1951
        if ($v_tar == 0) {
1952
            // ----- Error log
1953
            PclErrorLog(-2, "Unable to open archive '$p_tarname' in binary read mode");
1954
1955
            // ----- Return
1956
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1957
1958
            return PclErrorCode();
1959
        }
1960
1961
        // ----- Read the blocks
1962
        while (!($v_end_of_file = ($p_tar_mode === 'tar' ? feof($v_tar) : gzeof($v_tar)))) {
1963
            TrFctMessage(__FILE__, __LINE__, 3, 'Looking for next header ...');
1964
1965
            // ----- Clear cache of file infos
1966
            clearstatcache();
1967
1968
            // ----- Reset extract tag
1969
            $v_extract_file       = false;
1970
            $v_extraction_stopped = 0;
1971
1972
            // ----- Read the 512 bytes header
1973
            if ($p_tar_mode === 'tar') {
1974
                $v_binary_data = fread($v_tar, 512);
1975
            } else {
1976
                $v_binary_data = gzread($v_tar, 512);
1977
            }
1978
1979
            // ----- Read the header properties
1980
            if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
1981
                // ----- Close the archive file
1982
                if ($p_tar_mode === 'tar') {
1983
                    fclose($v_tar);
1984
                } else {
1985
                    gzclose($v_tar);
1986
                }
1987
1988
                // ----- Return
1989
                TrFctEnd(__FILE__, __LINE__, $v_result);
1990
1991
                return $v_result;
1992
            }
1993
1994
            // ----- Look for empty blocks to skip
1995
            if ($v_header['filename'] == '') {
1996
                TrFctMessage(__FILE__, __LINE__, 2, 'Empty block found. End of archive?');
1997
                continue;
1998
            }
1999
2000
            TrFctMessage(__FILE__, __LINE__, 2, "Found file '" . $v_header['filename'] . "', size '" . $v_header['size'] . "'");
2001
2002
            // ----- Look for partial extract
2003
            if ((!$v_extract_all) && is_array($p_file_list)) {
2004
                TrFctMessage(__FILE__, __LINE__, 2, 'Look if the file ' . $v_header['filename'] . ' need to be extracted');
2005
2006
                // ----- By default no unzip if the file is not found
2007
                $v_extract_file = false;
2008
2009
                // ----- Look into the file list
2010
                for ($i = 0, $iMax = count($p_file_list); $i < $iMax; ++$i) {
2011
                    TrFctMessage(__FILE__, __LINE__, 2, 'Compare archived file ' . $v_header['filename'] . " from asked list file '" . $p_file_list[$i] . "'");
2012
2013
                    // ----- Look if it is a directory
2014
                    if (substr($p_file_list[$i], -1) === '/') {
2015
                        TrFctMessage(__FILE__, __LINE__, 3, 'Compare file ' . $v_header['filename'] . " with directory '$p_file_list[$i]'");
2016
2017
                        // ----- Look if the directory is in the filename path
2018
                        if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
2019
                            && (0 === strpos($v_header['filename'], $p_file_list[$i]))
2020
                        ) {
2021
                            // ----- The file is in the directory, so extract it
2022
                            TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . " is in directory '$p_file_list[$i]' : extract it");
2023
                            $v_extract_file = true;
2024
2025
                            // ----- End of loop
2026
                            break;
2027
                        }
2028
                    } // ----- It is a file, so compare the file names
2029
                    else {
2030
                        if ($p_file_list[$i] == $v_header['filename']) {
2031
                            // ----- File found
2032
                            TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' should be extracted');
2033
                            $v_extract_file = true;
2034
2035
                            // ----- End of loop
2036
                            break;
2037
                        }
2038
                    }
2039
                }
2040
2041
                // ----- Trace
2042
                if (!$v_extract_file) {
2043
                    TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' should not be extracted');
2044
                }
2045
            } else {
2046
                // ----- All files need to be extracted
2047
                $v_extract_file = true;
2048
            }
2049
2050
            // ----- Look if this file need to be extracted
2051
            if ($v_extract_file && (!$v_listing)) {
2052
                // ----- Look for path to remove
2053 View Code Duplication
                if (($p_remove_path != '') && (0 === strpos($v_header['filename'], $p_remove_path))) {
2054
                    TrFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file " . $v_header['filename'] . '');
2055
                    // ----- Remove the path
2056
                    $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
2057
                    TrFctMessage(__FILE__, __LINE__, 3, 'Reslting file is ' . $v_header['filename'] . '');
2058
                }
2059
2060
                // ----- Add the path to the file
2061 View Code Duplication
                if (($p_path !== './') && ($p_path !== '/')) {
2062
                    // ----- Look for the path end '/'
2063
                    while (substr($p_path, -1) === '/') {
2064
                        TrFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
2065
                        $p_path = substr($p_path, 0, -1);
2066
                        TrFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
2067
                    }
2068
2069
                    // ----- Add the path
2070
                    if (0 === strpos($v_header['filename'], '/')) {
2071
                        $v_header['filename'] = $p_path . $v_header['filename'];
2072
                    } else {
2073
                        $v_header['filename'] = $p_path . '/' . $v_header['filename'];
2074
                    }
2075
                }
2076
2077
                // ----- Trace
2078
                TrFctMessage(__FILE__, __LINE__, 2, 'Extracting file (with path) ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
2079
2080
                // ----- Check that the file does not exists
2081
                if (file_exists($v_header['filename'])) {
2082
                    TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' already exists');
2083
2084
                    // ----- Look if file is a directory
2085
                    if (is_dir($v_header['filename'])) {
2086
                        TrFctMessage(__FILE__, __LINE__, 2, 'Existing file ' . $v_header['filename'] . ' is a directory');
2087
2088
                        // ----- Change the file status
2089
                        $v_header['status'] = 'already_a_directory';
2090
2091
                        // ----- Skip the extract
2092
                        $v_extraction_stopped = 1;
2093
                        $v_extract_file       = 0;
2094
                    } // ----- Look if file is write protected
2095
                    else {
2096
                        if (!s_writable($v_header['filename'])) {
2097
                            TrFctMessage(__FILE__, __LINE__, 2, 'Existing file ' . $v_header['filename'] . ' is write protected');
2098
2099
                            // ----- Change the file status
2100
                            $v_header['status'] = 'write_protected';
2101
2102
                            // ----- Skip the extract
2103
                            $v_extraction_stopped = 1;
2104
                            $v_extract_file       = 0;
2105
                        }
2106
                    }
2107
                    // ----- Look if the extracted file is older
2108
                    /*else if (filemtime($v_header['filename']) > $v_header['mtime']) {
2109
            TrFctMessage(__FILE__, __LINE__, 2, "Existing file ".$v_header['filename']." is newer (".date("l dS of F Y h:i:s A", filemtime($v_header['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $v_header['mtime']).")");
2110
2111
            // ----- Change the file status
2112
            $v_header['status'] = "newer_exist";
2113
2114
            // ----- Skip the extract
2115
            $v_extraction_stopped = 1;
2116
            $v_extract_file = 0;
2117
          }*/
2118
                } // ----- Check the directory availability and create it if necessary
2119 View Code Duplication
                else {
2120
                    if ($v_header['typeflag'] == '5') {
2121
                        $v_dir_to_check = $v_header['filename'];
2122
                    } else {
2123
                        if (false === strpos($v_header['filename'], '/')) {
2124
                            $v_dir_to_check = '';
2125
                        } else {
2126
                            $v_dir_to_check = dirname($v_header['filename']);
2127
                        }
2128
                    }
2129
2130
                    if (($v_result = PclTarHandlerDirCheck($v_dir_to_check)) != 1) {
2131
                        TrFctMessage(__FILE__, __LINE__, 2, 'Unable to create path for ' . $v_header['filename'] . '');
2132
2133
                        // ----- Change the file status
2134
                        $v_header['status'] = 'path_creation_fail';
2135
2136
                        // ----- Skip the extract
2137
                        $v_extraction_stopped = 1;
2138
                        $v_extract_file       = 0;
2139
                    }
2140
                }
2141
2142
                // ----- Do the extraction
2143
                if ($v_extract_file && ($v_header['typeflag'] != '5')) {
2144
                    // ----- Open the destination file in write mode
2145 View Code Duplication
                    if (($v_dest_file = @fopen($v_header['filename'], 'wb')) == 0) {
2146
                        TrFctMessage(__FILE__, __LINE__, 2, 'Error while opening ' . $v_header['filename'] . ' in write binary mode');
2147
2148
                        // ----- Change the file status
2149
                        $v_header['status'] = 'write_error';
2150
2151
                        // ----- Jump to next file
2152
                        TrFctMessage(__FILE__, __LINE__, 2, 'Jump to next file');
2153
                        if ($p_tar_mode === 'tar') {
2154
                            fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2155
                        } else {
2156
                            gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2157
                        }
2158
                    } else {
2159
                        TrFctMessage(__FILE__, __LINE__, 2, 'Start extraction of ' . $v_header['filename'] . '');
2160
2161
                        // ----- Read data
2162
                        $n = floor($v_header['size'] / 512);
2163
                        for ($i = 0; $i < $n; ++$i) {
2164
                            TrFctMessage(__FILE__, __LINE__, 3, 'Read complete 512 bytes block number ' . ($i + 1));
2165
                            if ($p_tar_mode === 'tar') {
2166
                                $v_content = fread($v_tar, 512);
2167
                            } else {
2168
                                $v_content = gzread($v_tar, 512);
2169
                            }
2170
                            fwrite($v_dest_file, $v_content, 512);
2171
                        }
2172
                        if (($v_header['size'] % 512) != 0) {
2173
                            TrFctMessage(__FILE__, __LINE__, 3, 'Read last ' . ($v_header['size'] % 512) . ' bytes in a 512 block');
2174
                            if ($p_tar_mode === 'tar') {
2175
                                $v_content = fread($v_tar, 512);
2176
                            } else {
2177
                                $v_content = gzread($v_tar, 512);
2178
                            }
2179
                            fwrite($v_dest_file, $v_content, $v_header['size'] % 512);
2180
                        }
2181
2182
                        // ----- Close the destination file
2183
                        fclose($v_dest_file);
2184
2185
                        // ----- Change the file mode, mtime
2186
                        touch($v_header['filename'], $v_header['mtime']);
2187
                        //chmod($v_header['filename'], decoct($v_header['mode']));
2188
                    }
2189
2190
                    // ----- Check the file size
2191
                    clearstatcache();
2192
                    if (filesize($v_header['filename']) != $v_header['size']) {
2193
                        // ----- Close the archive file
2194
                        if ($p_tar_mode === 'tar') {
2195
                            fclose($v_tar);
2196
                        } else {
2197
                            gzclose($v_tar);
2198
                        }
2199
2200
                        // ----- Error log
2201
                        PclErrorLog(-7, 'Extracted file '
2202
                                        . $v_header['filename']
2203
                                        . " does not have the correct file size '"
2204
                                        . filesize($v_filename)
0 ignored issues
show
The variable $v_filename does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
2205
                                        . "' ('"
2206
                                        . $v_header['size']
2207
                                        . "' expected). Archive may be corrupted.");
2208
2209
                        // ----- Return
2210
                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2211
2212
                        return PclErrorCode();
2213
                    }
2214
2215
                    // ----- Trace
2216
                    TrFctMessage(__FILE__, __LINE__, 2, 'Extraction done');
2217 View Code Duplication
                } else {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2218
                    TrFctMessage(__FILE__, __LINE__, 2, 'Extraction of file ' . $v_header['filename'] . ' skipped.');
2219
2220
                    // ----- Jump to next file
2221
                    TrFctMessage(__FILE__, __LINE__, 2, 'Jump to next file');
2222
                    if ($p_tar_mode === 'tar') {
2223
                        fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2224
                    } else {
2225
                        gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2226
                    }
2227
                }
2228
            } // ----- Look for file that is not to be unzipped
2229 View Code Duplication
            else {
2230
                // ----- Trace
2231
                TrFctMessage(__FILE__, __LINE__, 2, 'Jump file ' . $v_header['filename'] . '');
2232
                TrFctMessage(__FILE__, __LINE__, 4, 'Position avant jump [' . ($p_tar_mode === 'tar' ? ftell($v_tar) : gztell($v_tar)) . ']');
2233
2234
                // ----- Jump to next file
2235
                if ($p_tar_mode === 'tar') {
2236
                    fseek($v_tar, ($p_tar_mode === 'tar' ? ftell($v_tar) : gztell($v_tar)) + (ceil($v_header['size'] / 512) * 512));
2237
                } else {
2238
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2239
                }
2240
2241
                TrFctMessage(__FILE__, __LINE__, 4, 'Position après jump [' . ($p_tar_mode === 'tar' ? ftell($v_tar) : gztell($v_tar)) . ']');
2242
            }
2243
2244
            if ($p_tar_mode === 'tar') {
2245
                $v_end_of_file = feof($v_tar);
2246
            } else {
2247
                $v_end_of_file = gzeof($v_tar);
2248
            }
2249
2250
            // ----- File name and properties are logged if listing mode or file is extracted
2251 View Code Duplication
            if ($v_listing || $v_extract_file || $v_extraction_stopped) {
2252
                TrFctMessage(__FILE__, __LINE__, 2, 'Memorize info about file ' . $v_header['filename'] . '');
2253
2254
                // ----- Log extracted files
2255
                if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
2256
                    $v_file_dir = '';
2257
                }
2258
                if (($v_file_dir === '') && (0 === strpos($v_header['filename'], '/'))) {
2259
                    $v_file_dir = '/';
2260
                }
2261
2262
                // ----- Add the array describing the file into the list
2263
                $p_list_detail[$v_nb] = $v_header;
2264
2265
                // ----- Increment
2266
                ++$v_nb;
2267
            }
2268
        }
2269
2270
        // ----- Close the tarfile
2271
        if ($p_tar_mode === 'tar') {
2272
            fclose($v_tar);
2273
        } else {
2274
            gzclose($v_tar);
2275
        }
2276
2277
        // ----- Return
2278
        TrFctEnd(__FILE__, __LINE__, $v_result);
2279
2280
        return $v_result;
2281
    }
2282
2283
    // --------------------------------------------------------------------------------
2284
2285
    // --------------------------------------------------------------------------------
2286
    // Function : PclTarHandleExtractByIndexList()
2287
    // Description :
2288
    //   Extract the files which are at the indexes specified. If the 'file' at the
2289
    //   index is a directory, the directory only is created, not all the files stored
2290
    //   for that directory.
2291
    // Parameters :
2292
    //   $p_index_string : String of indexes of files to extract. The form of the
2293
    //                     string is "0,4-6,8-12" with only numbers and '-' for
2294
    //                     for range, and ',' to separate ranges. No spaces or ';'
2295
    //                     are allowed.
2296
    // Return Values :
2297
    // --------------------------------------------------------------------------------
2298
    /**
2299
     * @param $p_tarname
2300
     * @param $p_index_string
2301
     * @param $p_list_detail
2302
     * @param $p_path
2303
     * @param $p_remove_path
2304
     * @param $p_tar_mode
2305
     *
2306
     * @return int
2307
     */
2308
    function PclTarHandleExtractByIndexList(
2309
        $p_tarname,
2310
        $p_index_string,
2311
        &$p_list_detail,
2312
        $p_path,
2313
        $p_remove_path,
2314
        $p_tar_mode
2315
    ) {
2316
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtractByIndexList',
2317
                   "archive='$p_tarname', index_string='$p_index_string', list, path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2318
        $v_result = 1;
2319
        $v_nb     = 0;
2320
2321
        // ----- TBC : I should check the string by a regexp
2322
2323
        // ----- Check the path
2324
        if (($p_path === '')
2325
            || ((0 !== strpos($p_path, '/')) && (0 !== strpos($p_path, '../'))
2326
                && (0 !== strpos($p_path, './')))
2327
        ) {
2328
            $p_path = './' . $p_path;
2329
        }
2330
2331
        // ----- Look for path to remove format (should end by /)
2332
        if (($p_remove_path != '') && (substr($p_remove_path, -1) !== '/')) {
2333
            $p_remove_path .= '/';
2334
        }
2335
        $p_remove_path_size = strlen($p_remove_path);
2336
2337
        // ----- Open the tar file
2338 View Code Duplication
        if ($p_tar_mode === 'tar') {
2339
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in binary read mode');
2340
            $v_tar = @fopen($p_tarname, 'rb');
2341
        } else {
2342
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in gzip binary read mode');
2343
            $v_tar = @gzopen($p_tarname, 'rb');
2344
        }
2345
2346
        // ----- Check that the archive is open
2347
        if ($v_tar == 0) {
2348
            // ----- Error log
2349
            PclErrorLog(-2, "Unable to open archive '$p_tarname' in binary read mode");
2350
2351
            // ----- Return
2352
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2353
2354
            return PclErrorCode();
2355
        }
2356
2357
        // ----- Manipulate the index list
2358
        $v_list = explode(',', $p_index_string);
2359
        sort($v_list);
2360
2361
        // ----- Loop on the index list
2362
        $v_index = 0;
2363
        for ($i = 0; ($i < count($v_list)) && $v_result; ++$i) {
2364
            TrFctMessage(__FILE__, __LINE__, 3, "Looking for index part '$v_list[$i]'");
2365
2366
            // ----- Extract range
2367
            $v_index_list      = explode('-', $v_list[$i]);
2368
            $v_size_index_list = count($v_index_list);
2369
            if ($v_size_index_list == 1) {
2370
                TrFctMessage(__FILE__, __LINE__, 3, "Only one index '$v_index_list[0]'");
2371
2372
                // ----- Do the extraction
2373
                $v_result = PclTarHandleExtractByIndex($v_tar, $v_index, $v_index_list[0], $v_index_list[0], $p_list_detail, $p_path, $p_remove_path, $p_tar_mode);
2374
            } else {
2375
                if ($v_size_index_list == 2) {
2376
                    TrFctMessage(__FILE__, __LINE__, 3, "Two indexes '$v_index_list[0]' and '$v_index_list[1]'");
2377
2378
                    // ----- Do the extraction
2379
                    $v_result = PclTarHandleExtractByIndex($v_tar, $v_index, $v_index_list[0], $v_index_list[1], $p_list_detail, $p_path, $p_remove_path, $p_tar_mode);
2380
                }
2381
            }
2382
        }
2383
2384
        // ----- Close the tarfile
2385
        if ($p_tar_mode === 'tar') {
2386
            fclose($v_tar);
2387
        } else {
2388
            gzclose($v_tar);
2389
        }
2390
2391
        // ----- Return
2392
        TrFctEnd(__FILE__, __LINE__, $v_result);
2393
2394
        return $v_result;
2395
    }
2396
2397
    // --------------------------------------------------------------------------------
2398
2399
    // --------------------------------------------------------------------------------
2400
    // Function : PclTarHandleExtractByIndex()
2401
    // Description :
2402
    // Parameters :
2403
    // Return Values :
2404
    // --------------------------------------------------------------------------------
2405
    /**
2406
     * @param $p_tar
2407
     * @param $p_index_current
2408
     * @param $p_index_start
2409
     * @param $p_index_stop
2410
     * @param $p_list_detail
2411
     * @param $p_path
2412
     * @param $p_remove_path
2413
     * @param $p_tar_mode
2414
     *
2415
     * @return int
2416
     */
2417
    function PclTarHandleExtractByIndex(
2418
        $p_tar,
2419
        &$p_index_current,
2420
        $p_index_start,
2421
        $p_index_stop,
2422
        &$p_list_detail,
2423
        $p_path,
2424
        $p_remove_path,
2425
        $p_tar_mode
2426
    ) {
2427
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtractByIndex',
2428
                   "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");
2429
        $v_result = 1;
2430
        $v_nb     = 0;
2431
2432
        // TBC : I should replace all $v_tar by $p_tar in this function ....
2433
        $v_tar = $p_tar;
2434
2435
        // ----- Look the number of elements already in $p_list_detail
2436
        $v_nb = count($p_list_detail);
2437
2438
        // ----- Read the blocks
2439
        while (!($v_end_of_file = ($p_tar_mode === 'tar' ? feof($v_tar) : gzeof($v_tar)))) {
2440
            TrFctMessage(__FILE__, __LINE__, 3, 'Looking for next file ...');
2441
            TrFctMessage(__FILE__, __LINE__, 3, "Index current=$p_index_current, range=[$p_index_start, $p_index_stop])");
2442
2443
            if ($p_index_current > $p_index_stop) {
2444
                TrFctMessage(__FILE__, __LINE__, 2, 'Stop extraction, past stop index');
2445
                break;
2446
            }
2447
2448
            // ----- Clear cache of file infos
2449
            clearstatcache();
2450
2451
            // ----- Reset extract tag
2452
            $v_extract_file       = false;
2453
            $v_extraction_stopped = 0;
2454
2455
            // ----- Read the 512 bytes header
2456
            if ($p_tar_mode === 'tar') {
2457
                $v_binary_data = fread($v_tar, 512);
2458
            } else {
2459
                $v_binary_data = gzread($v_tar, 512);
2460
            }
2461
2462
            // ----- Read the header properties
2463
            if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
2464
                // ----- Return
2465
                TrFctEnd(__FILE__, __LINE__, $v_result);
2466
2467
                return $v_result;
2468
            }
2469
2470
            // ----- Look for empty blocks to skip
2471
            if ($v_header['filename'] == '') {
2472
                TrFctMessage(__FILE__, __LINE__, 2, 'Empty block found. End of archive?');
2473
                continue;
2474
            }
2475
2476
            TrFctMessage(__FILE__, __LINE__, 2, 'Found file ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
2477
2478
            // ----- Look if file is in the range to be extracted
2479
            if (($p_index_current >= $p_index_start) && ($p_index_current <= $p_index_stop)) {
2480
                TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' is in the range to be extracted');
2481
                $v_extract_file = true;
2482
            } else {
2483
                TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' is out of the range');
2484
                $v_extract_file = false;
2485
            }
2486
2487
            // ----- Look if this file need to be extracted
2488
            if ($v_extract_file) {
2489
                if (($v_result = PclTarHandleExtractFile($v_tar, $v_header, $p_path, $p_remove_path, $p_tar_mode)) != 1) {
2490
                    // ----- Return
2491
                    TrFctEnd(__FILE__, __LINE__, $v_result);
2492
2493
                    return $v_result;
2494
                }
2495
            } // ----- Look for file that is not to be extracted
2496 View Code Duplication
            else {
2497
                // ----- Trace
2498
                TrFctMessage(__FILE__, __LINE__, 2, 'Jump file ' . $v_header['filename'] . '');
2499
                TrFctMessage(__FILE__, __LINE__, 4, 'Position avant jump [' . ($p_tar_mode === 'tar' ? ftell($v_tar) : gztell($v_tar)) . ']');
2500
2501
                // ----- Jump to next file
2502
                if ($p_tar_mode === 'tar') {
2503
                    fseek($v_tar, ($p_tar_mode === 'tar' ? ftell($v_tar) : gztell($v_tar)) + (ceil($v_header['size'] / 512) * 512));
2504
                } else {
2505
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2506
                }
2507
2508
                TrFctMessage(__FILE__, __LINE__, 4, 'Position après jump [' . ($p_tar_mode === 'tar' ? ftell($v_tar) : gztell($v_tar)) . ']');
2509
            }
2510
2511
            if ($p_tar_mode === 'tar') {
2512
                $v_end_of_file = feof($v_tar);
2513
            } else {
2514
                $v_end_of_file = gzeof($v_tar);
2515
            }
2516
2517
            // ----- File name and properties are logged if listing mode or file is extracted
2518 View Code Duplication
            if ($v_extract_file) {
2519
                TrFctMessage(__FILE__, __LINE__, 2, 'Memorize info about file ' . $v_header['filename'] . '');
2520
2521
                // ----- Log extracted files
2522
                if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
2523
                    $v_file_dir = '';
2524
                }
2525
                if (($v_file_dir === '') && (0 === strpos($v_header['filename'], '/'))) {
2526
                    $v_file_dir = '/';
2527
                }
2528
2529
                // ----- Add the array describing the file into the list
2530
                $p_list_detail[$v_nb] = $v_header;
2531
2532
                // ----- Increment
2533
                ++$v_nb;
2534
            }
2535
2536
            // ----- Increment the current file index
2537
            ++$p_index_current;
2538
        }
2539
2540
        // ----- Return
2541
        TrFctEnd(__FILE__, __LINE__, $v_result);
2542
2543
        return $v_result;
2544
    }
2545
2546
    // --------------------------------------------------------------------------------
2547
2548
    // --------------------------------------------------------------------------------
2549
    // Function : PclTarHandleExtractFile()
2550
    // Description :
2551
    // Parameters :
2552
    // Return Values :
2553
    // --------------------------------------------------------------------------------
2554
    /**
2555
     * @param $p_tar
2556
     * @param $v_header
2557
     * @param $p_path
2558
     * @param $p_remove_path
2559
     * @param $p_tar_mode
2560
     *
2561
     * @return int
2562
     */
2563
    function PclTarHandleExtractFile($p_tar, &$v_header, $p_path, $p_remove_path, $p_tar_mode)
2564
    {
2565
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtractFile', "archive_descr='$p_tar', path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2566
        $v_result = 1;
2567
2568
        // TBC : I should replace all $v_tar by $p_tar in this function ....
2569
        $v_tar          = $p_tar;
2570
        $v_extract_file = 1;
2571
2572
        $p_remove_path_size = strlen($p_remove_path);
2573
2574
        // ----- Look for path to remove
2575 View Code Duplication
        if (($p_remove_path != '') && (0 === strpos($v_header['filename'], $p_remove_path))) {
2576
            TrFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file " . $v_header['filename'] . '');
2577
            // ----- Remove the path
2578
            $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
2579
            TrFctMessage(__FILE__, __LINE__, 3, 'Resulting file is ' . $v_header['filename'] . '');
2580
        }
2581
2582
        // ----- Add the path to the file
2583 View Code Duplication
        if (($p_path !== './') && ($p_path !== '/')) {
2584
            // ----- Look for the path end '/'
2585
            while (substr($p_path, -1) === '/') {
2586
                TrFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
2587
                $p_path = substr($p_path, 0, -1);
2588
                TrFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
2589
            }
2590
2591
            // ----- Add the path
2592
            if (0 === strpos($v_header['filename'], '/')) {
2593
                $v_header['filename'] = $p_path . $v_header['filename'];
2594
            } else {
2595
                $v_header['filename'] = $p_path . '/' . $v_header['filename'];
2596
            }
2597
        }
2598
2599
        // ----- Trace
2600
        TrFctMessage(__FILE__, __LINE__, 2, 'Extracting file (with path) ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
2601
2602
        // ----- Check that the file does not exists
2603
        if (file_exists($v_header['filename'])) {
2604
            TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' already exists');
2605
2606
            // ----- Look if file is a directory
2607
            if (is_dir($v_header['filename'])) {
2608
                TrFctMessage(__FILE__, __LINE__, 2, 'Existing file ' . $v_header['filename'] . ' is a directory');
2609
2610
                // ----- Change the file status
2611
                $v_header['status'] = 'already_a_directory';
2612
2613
                // ----- Skip the extract
2614
                $v_extraction_stopped = 1;
2615
                $v_extract_file       = 0;
2616
            } // ----- Look if file is write protected
2617
            else {
2618
                if (!s_writable($v_header['filename'])) {
2619
                    TrFctMessage(__FILE__, __LINE__, 2, 'Existing file ' . $v_header['filename'] . ' is write protected');
2620
2621
                    // ----- Change the file status
2622
                    $v_header['status'] = 'write_protected';
2623
2624
                    // ----- Skip the extract
2625
                    $v_extraction_stopped = 1;
2626
                    $v_extract_file       = 0;
2627
                } // ----- Look if the extracted file is older
2628
                else {
2629
                    if (filemtime($v_header['filename']) > $v_header['mtime']) {
2630
                        TrFctMessage(__FILE__, __LINE__, 2, 'Existing file '
2631
                                                            . $v_header['filename']
2632
                                                            . ' is newer ('
2633
                                                            . date('l dS of F Y h:i:s A', filemtime($v_header['filename']))
2634
                                                            . ') than the extracted file ('
2635
                                                            . date('l dS of F Y h:i:s A', $v_header['mtime'])
2636
                                                            . ')');
2637
2638
                        // ----- Change the file status
2639
                        $v_header['status'] = 'newer_exist';
2640
2641
                        // ----- Skip the extract
2642
                        $v_extraction_stopped = 1;
2643
                        $v_extract_file       = 0;
2644
                    }
2645
                }
2646
            }
2647
        } // ----- Check the directory availability and create it if necessary
2648 View Code Duplication
        else {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2649
            if ($v_header['typeflag'] == '5') {
2650
                $v_dir_to_check = $v_header['filename'];
2651
            } else {
2652
                if (false === strpos($v_header['filename'], '/')) {
2653
                    $v_dir_to_check = '';
2654
                } else {
2655
                    $v_dir_to_check = dirname($v_header['filename']);
2656
                }
2657
            }
2658
2659
            if (($v_result = PclTarHandlerDirCheck($v_dir_to_check)) != 1) {
2660
                TrFctMessage(__FILE__, __LINE__, 2, 'Unable to create path for ' . $v_header['filename'] . '');
2661
2662
                // ----- Change the file status
2663
                $v_header['status'] = 'path_creation_fail';
2664
2665
                // ----- Skip the extract
2666
                $v_extraction_stopped = 1;
2667
                $v_extract_file       = 0;
2668
            }
2669
        }
2670
2671
        // ----- Do the real bytes extraction (if not a directory)
2672
        if ($v_extract_file && ($v_header['typeflag'] != '5')) {
2673
            // ----- Open the destination file in write mode
2674 View Code Duplication
            if (($v_dest_file = @fopen($v_header['filename'], 'wb')) == 0) {
2675
                TrFctMessage(__FILE__, __LINE__, 2, 'Error while opening ' . $v_header['filename'] . ' in write binary mode');
2676
2677
                // ----- Change the file status
2678
                $v_header['status'] = 'write_error';
2679
2680
                // ----- Jump to next file
2681
                TrFctMessage(__FILE__, __LINE__, 2, 'Jump to next file');
2682
                if ($p_tar_mode === 'tar') {
2683
                    fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2684
                } else {
2685
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2686
                }
2687
            } else {
2688
                TrFctMessage(__FILE__, __LINE__, 2, 'Start extraction of ' . $v_header['filename'] . '');
2689
2690
                // ----- Read data
2691
                $n = floor($v_header['size'] / 512);
2692
                for ($i = 0; $i < $n; ++$i) {
2693
                    TrFctMessage(__FILE__, __LINE__, 3, 'Read complete 512 bytes block number ' . ($i + 1));
2694
                    if ($p_tar_mode === 'tar') {
2695
                        $v_content = fread($v_tar, 512);
2696
                    } else {
2697
                        $v_content = gzread($v_tar, 512);
2698
                    }
2699
                    fwrite($v_dest_file, $v_content, 512);
2700
                }
2701
                if (($v_header['size'] % 512) != 0) {
2702
                    TrFctMessage(__FILE__, __LINE__, 3, 'Read last ' . ($v_header['size'] % 512) . ' bytes in a 512 block');
2703
                    if ($p_tar_mode === 'tar') {
2704
                        $v_content = fread($v_tar, 512);
2705
                    } else {
2706
                        $v_content = gzread($v_tar, 512);
2707
                    }
2708
                    fwrite($v_dest_file, $v_content, $v_header['size'] % 512);
2709
                }
2710
2711
                // ----- Close the destination file
2712
                fclose($v_dest_file);
2713
2714
                // ----- Change the file mode, mtime
2715
                touch($v_header['filename'], $v_header['mtime']);
2716
                //chmod($v_header['filename'], decoct($v_header['mode']));
2717
            }
2718
2719
            // ----- Check the file size
2720
            clearstatcache();
2721
            if (filesize($v_header['filename']) != $v_header['size']) {
2722
                // ----- Error log
2723
                PclErrorLog(-7, 'Extracted file '
2724
                                . $v_header['filename']
2725
                                . " does not have the correct file size '"
2726
                                . filesize($v_filename)
0 ignored issues
show
The variable $v_filename does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
2727
                                . "' ('"
2728
                                . $v_header['size']
2729
                                . "' expected). Archive may be corrupted.");
2730
2731
                // ----- Return
2732
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2733
2734
                return PclErrorCode();
2735
            }
2736
2737
            // ----- Trace
2738
            TrFctMessage(__FILE__, __LINE__, 2, 'Extraction done');
2739 View Code Duplication
        } else {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2740
            TrFctMessage(__FILE__, __LINE__, 2, 'Extraction of file ' . $v_header['filename'] . ' skipped.');
2741
2742
            // ----- Jump to next file
2743
            TrFctMessage(__FILE__, __LINE__, 2, 'Jump to next file');
2744
            if ($p_tar_mode === 'tar') {
2745
                fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2746
            } else {
2747
                gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2748
            }
2749
        }
2750
2751
        // ----- Return
2752
        TrFctEnd(__FILE__, __LINE__, $v_result);
2753
2754
        return $v_result;
2755
    }
2756
2757
    // --------------------------------------------------------------------------------
2758
2759
    // --------------------------------------------------------------------------------
2760
    // Function : PclTarHandleDelete()
2761
    // Description :
2762
    // Parameters :
2763
    // Return Values :
2764
    // --------------------------------------------------------------------------------
2765
    /**
2766
     * @param $p_tarname
2767
     * @param $p_file_list
2768
     * @param $p_list_detail
2769
     * @param $p_tar_mode
2770
     *
2771
     * @return int
2772
     */
2773
    function PclTarHandleDelete($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode)
2774
    {
2775
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleDelete', "archive='$p_tarname', list, tar_mode=$p_tar_mode");
2776
        $v_result = 1;
2777
        $v_nb     = 0;
2778
2779
        // ----- Look for regular tar file
2780 View Code Duplication
        if ($p_tar_mode === 'tar') {
2781
            // ----- Open file
2782
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in binary read mode');
2783
            if (($v_tar = @fopen($p_tarname, 'rb')) == 0) {
2784
                // ----- Error log
2785
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2786
2787
                // ----- Return
2788
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2789
2790
                return PclErrorCode();
2791
            }
2792
2793
            // ----- Open a temporary file in write mode
2794
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
2795
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
2796
            if (($v_temp_tar = @fopen($v_temp_tarname, 'wb')) == 0) {
2797
                // ----- Close tar file
2798
                fclose($v_tar);
2799
2800
                // ----- Error log
2801
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2802
2803
                // ----- Return
2804
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2805
2806
                return PclErrorCode();
2807
            }
2808
        } // ----- Look for compressed tar file
2809
        else {
2810
            // ----- Open the file in read mode
2811
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in gzip binary read mode');
2812
            if (($v_tar = @gzopen($p_tarname, 'rb')) == 0) {
2813
                // ----- Error log
2814
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2815
2816
                // ----- Return
2817
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2818
2819
                return PclErrorCode();
2820
            }
2821
2822
            // ----- Open a temporary file in write mode
2823
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
2824
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
2825
            if (($v_temp_tar = @gzopen($v_temp_tarname, 'wb')) == 0) {
2826
                // ----- Close tar file
2827
                gzclose($v_tar);
2828
2829
                // ----- Error log
2830
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2831
2832
                // ----- Return
2833
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2834
2835
                return PclErrorCode();
2836
            }
2837
        }
2838
2839
        // ----- Read the blocks
2840
        while (!($v_end_of_file = ($p_tar_mode === 'tar' ? feof($v_tar) : gzeof($v_tar)))) {
2841
            TrFctMessage(__FILE__, __LINE__, 3, 'Looking for next header ...');
2842
2843
            // ----- Clear cache of file infos
2844
            clearstatcache();
2845
2846
            // ----- Reset delete tag
2847
            $v_delete_file = false;
2848
2849
            // ----- Read the first 512 block header
2850
            if ($p_tar_mode === 'tar') {
2851
                $v_binary_data = fread($v_tar, 512);
2852
            } else {
2853
                $v_binary_data = gzread($v_tar, 512);
2854
            }
2855
2856
            // ----- Read the header properties
2857 View Code Duplication
            if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
2858
                // ----- Close the archive file
2859
                if ($p_tar_mode === 'tar') {
2860
                    fclose($v_tar);
2861
                    fclose($v_temp_tar);
2862
                } else {
2863
                    gzclose($v_tar);
2864
                    gzclose($v_temp_tar);
2865
                }
2866
                @unlink($v_temp_tarname);
2867
2868
                // ----- Return
2869
                TrFctEnd(__FILE__, __LINE__, $v_result);
2870
2871
                return $v_result;
2872
            }
2873
2874
            // ----- Look for empty blocks to skip
2875
            if ($v_header['filename'] == '') {
2876
                TrFctMessage(__FILE__, __LINE__, 2, 'Empty block found. End of archive?');
2877
                continue;
2878
            }
2879
2880
            TrFctMessage(__FILE__, __LINE__, 2, 'Found file ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
2881
2882
            // ----- Look for filenames to delete
2883
            for ($i = 0, $v_delete_file = false; ($i < count($p_file_list)) && (!$v_delete_file); ++$i) {
2884
                // ----- Compare the file names
2885
                //        if ($p_file_list[$i] == $v_header['filename'])
2886
                if (($v_len = strcmp($p_file_list[$i], $v_header['filename'])) <= 0) {
2887
                    if ($v_len == 0) {
2888
                        TrFctMessage(__FILE__, __LINE__, 3, 'Found that ' . $v_header['filename'] . ' need to be deleted');
2889
                        $v_delete_file = true;
2890
                    } else {
2891
                        TrFctMessage(__FILE__, __LINE__, 3, 'Look if ' . $v_header['filename'] . " is a file in $p_file_list[$i]");
2892
                        if (substr($v_header['filename'], strlen($p_file_list[$i]), 1) === '/') {
2893
                            TrFctMessage(__FILE__, __LINE__, 3, '' . $v_header['filename'] . " is a file in $p_file_list[$i]");
2894
                            $v_delete_file = true;
2895
                        }
2896
                    }
2897
                }
2898
            }
2899
2900
            // ----- Copy files that do not need to be deleted
2901
            if (!$v_delete_file) {
2902
                TrFctMessage(__FILE__, __LINE__, 2, 'Keep file ' . $v_header['filename'] . '');
2903
2904
                // ----- Write the file header
2905
                if ($p_tar_mode === 'tar') {
2906
                    fwrite($v_temp_tar, $v_binary_data, 512);
2907
                } else {
2908
                    gzputs($v_temp_tar, $v_binary_data, 512);
2909
                }
2910
2911
                // ----- Write the file data
2912
                $n = ceil($v_header['size'] / 512);
2913
                for ($i = 0; $i < $n; ++$i) {
2914
                    TrFctMessage(__FILE__, __LINE__, 3, 'Read complete 512 bytes block number ' . ($i + 1));
2915
                    if ($p_tar_mode === 'tar') {
2916
                        $v_content = fread($v_tar, 512);
2917
                        fwrite($v_temp_tar, $v_content, 512);
2918
                    } else {
2919
                        $v_content = gzread($v_tar, 512);
2920
                        gzwrite($v_temp_tar, $v_content, 512);
2921
                    }
2922
                }
2923
2924
                // ----- File name and properties are logged if listing mode or file is extracted
2925
                TrFctMessage(__FILE__, __LINE__, 2, 'Memorize info about file ' . $v_header['filename'] . '');
2926
2927
                // ----- Add the array describing the file into the list
2928
                $p_list_detail[$v_nb]           = $v_header;
2929
                $p_list_detail[$v_nb]['status'] = 'ok';
2930
2931
                // ----- Increment
2932
                ++$v_nb;
2933
            } // ----- Look for file that is to be deleted
2934 View Code Duplication
            else {
2935
                // ----- Trace
2936
                TrFctMessage(__FILE__, __LINE__, 2, 'Start deletion of ' . $v_header['filename'] . '');
2937
                TrFctMessage(__FILE__, __LINE__, 4, 'Position avant jump [' . ($p_tar_mode === 'tar' ? ftell($v_tar) : gztell($v_tar)) . ']');
2938
2939
                // ----- Jump to next file
2940
                if ($p_tar_mode === 'tar') {
2941
                    fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2942
                } else {
2943
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2944
                }
2945
2946
                TrFctMessage(__FILE__, __LINE__, 4, 'Position après jump [' . ($p_tar_mode === 'tar' ? ftell($v_tar) : gztell($v_tar)) . ']');
2947
            }
2948
2949
            // ----- Look for end of file
2950
            if ($p_tar_mode === 'tar') {
2951
                $v_end_of_file = feof($v_tar);
2952
            } else {
2953
                $v_end_of_file = gzeof($v_tar);
2954
            }
2955
        }
2956
2957
        // ----- Write the last empty buffer
2958
        PclTarHandleFooter($v_temp_tar, $p_tar_mode);
2959
2960
        // ----- Close the tarfile
2961
        if ($p_tar_mode === 'tar') {
2962
            fclose($v_tar);
2963
            fclose($v_temp_tar);
2964
        } else {
2965
            gzclose($v_tar);
2966
            gzclose($v_temp_tar);
2967
        }
2968
2969
        // ----- Unlink tar file
2970
        if (!@unlink($p_tarname)) {
2971
            // ----- Error log
2972
            PclErrorLog(-11, "Error while deleting archive name $p_tarname");
2973
        }
2974
2975
        // ----- Rename tar file
2976
        if (!@rename($v_temp_tarname, $p_tarname)) {
2977
            // ----- Error log
2978
            PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
2979
2980
            // ----- Return
2981
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2982
2983
            return PclErrorCode();
2984
        }
2985
2986
        // ----- Return
2987
        TrFctEnd(__FILE__, __LINE__, $v_result);
2988
2989
        return $v_result;
2990
    }
2991
2992
    // --------------------------------------------------------------------------------
2993
2994
    // --------------------------------------------------------------------------------
2995
    // Function : PclTarHandleUpdate()
2996
    // Description :
2997
    // Parameters :
2998
    // Return Values :
2999
    // --------------------------------------------------------------------------------
3000
    /**
3001
     * @param $p_tarname
3002
     * @param $p_file_list
3003
     * @param $p_list_detail
3004
     * @param $p_tar_mode
3005
     * @param $p_add_dir
3006
     * @param $p_remove_dir
3007
     *
3008
     * @return int
3009
     */
3010
    function PclTarHandleUpdate($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode, $p_add_dir, $p_remove_dir)
3011
    {
3012
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleUpdate', "archive='$p_tarname', list, tar_mode=$p_tar_mode");
3013
        $v_result     = 1;
3014
        $v_nb         = 0;
3015
        $v_found_list = array();
3016
3017
        // ----- Look for regular tar file
3018 View Code Duplication
        if ($p_tar_mode === 'tar') {
3019
            // ----- Open file
3020
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in binary read mode');
3021
            if (($v_tar = @fopen($p_tarname, 'rb')) == 0) {
3022
                // ----- Error log
3023
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
3024
3025
                // ----- Return
3026
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3027
3028
                return PclErrorCode();
3029
            }
3030
3031
            // ----- Open a temporary file in write mode
3032
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
3033
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
3034
            if (($v_temp_tar = @fopen($v_temp_tarname, 'wb')) == 0) {
3035
                // ----- Close tar file
3036
                fclose($v_tar);
3037
3038
                // ----- Error log
3039
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
3040
3041
                // ----- Return
3042
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3043
3044
                return PclErrorCode();
3045
            }
3046
        } // ----- Look for compressed tar file
3047
        else {
3048
            // ----- Open the file in read mode
3049
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in gzip binary read mode');
3050
            if (($v_tar = @gzopen($p_tarname, 'rb')) == 0) {
3051
                // ----- Error log
3052
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
3053
3054
                // ----- Return
3055
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3056
3057
                return PclErrorCode();
3058
            }
3059
3060
            // ----- Open a temporary file in write mode
3061
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
3062
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
3063
            if (($v_temp_tar = @gzopen($v_temp_tarname, 'wb')) == 0) {
3064
                // ----- Close tar file
3065
                gzclose($v_tar);
3066
3067
                // ----- Error log
3068
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
3069
3070
                // ----- Return
3071
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3072
3073
                return PclErrorCode();
3074
            }
3075
        }
3076
3077
        // ----- Prepare the list of files
3078
        for ($i = 0, $iMax = count($p_file_list); $i < $iMax; ++$i) {
3079
            // ----- Reset the found list
3080
            $v_found_list[$i] = 0;
3081
3082
            // ----- Calculate the stored filename
3083
            $v_stored_list[$i] = $p_file_list[$i];
3084
            if ($p_remove_dir != '') {
3085
                if (substr($p_file_list[$i], -1) !== '/') {
3086
                    $p_remove_dir .= '/';
3087
                }
3088
3089
                if (0 === strpos($p_file_list[$i], $p_remove_dir)) {
3090
                    $v_stored_list[$i] = substr($p_file_list[$i], strlen($p_remove_dir));
3091
                    TrFctMessage(__FILE__, __LINE__, 3, "Remove path '$p_remove_dir' in file '$p_file_list[$i]' = '$v_stored_list[$i]'");
3092
                }
3093
            }
3094
            if ($p_add_dir != '') {
3095
                if (substr($p_add_dir, -1) === '/') {
3096
                    $v_stored_list[$i] = $p_add_dir . $v_stored_list[$i];
3097
                } else {
3098
                    $v_stored_list[$i] = $p_add_dir . '/' . $v_stored_list[$i];
3099
                }
3100
                TrFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_file_list[$i]' = '$v_stored_list[$i]'");
3101
            }
3102
            $v_stored_list[$i] = PclTarHandlePathReduction($v_stored_list[$i]);
3103
            TrFctMessage(__FILE__, __LINE__, 3, "After reduction '$v_stored_list[$i]'");
3104
        }
3105
3106
        // ----- Update file cache
3107
        clearstatcache();
3108
3109
        // ----- Read the blocks
3110
        while (!($v_end_of_file = ($p_tar_mode === 'tar' ? feof($v_tar) : gzeof($v_tar)))) {
3111
            TrFctMessage(__FILE__, __LINE__, 3, 'Looking for next header ...');
3112
3113
            // ----- Clear cache of file infos
3114
            clearstatcache();
3115
3116
            // ----- Reset current found filename
3117
            $v_current_filename = '';
3118
3119
            // ----- Reset delete tag
3120
            $v_delete_file = false;
3121
3122
            // ----- Read the first 512 block header
3123
            if ($p_tar_mode === 'tar') {
3124
                $v_binary_data = fread($v_tar, 512);
3125
            } else {
3126
                $v_binary_data = gzread($v_tar, 512);
3127
            }
3128
3129
            // ----- Read the header properties
3130 View Code Duplication
            if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
3131
                // ----- Close the archive file
3132
                if ($p_tar_mode === 'tar') {
3133
                    fclose($v_tar);
3134
                    fclose($v_temp_tar);
3135
                } else {
3136
                    gzclose($v_tar);
3137
                    gzclose($v_temp_tar);
3138
                }
3139
                @unlink($v_temp_tarname);
3140
3141
                // ----- Return
3142
                TrFctEnd(__FILE__, __LINE__, $v_result);
3143
3144
                return $v_result;
3145
            }
3146
3147
            // ----- Look for empty blocks to skip
3148
            if ($v_header['filename'] == '') {
3149
                TrFctMessage(__FILE__, __LINE__, 2, 'Empty block found. End of archive?');
3150
                continue;
3151
            }
3152
3153
            TrFctMessage(__FILE__, __LINE__, 2, 'Found file ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
3154
3155
            // ----- Look for filenames to update
3156
            for ($i = 0, $v_update_file = false, $v_found_file = false; ($i < count($v_stored_list)) && (!$v_update_file); ++$i) {
3157
                TrFctMessage(__FILE__, __LINE__, 4, "Compare with file '$v_stored_list[$i]'");
3158
3159
                // ----- Compare the file names
3160
                if ($v_stored_list[$i] == $v_header['filename']) {
3161
                    TrFctMessage(__FILE__, __LINE__, 3, "File '$v_stored_list[$i]' is present in archive");
3162
                    TrFctMessage(__FILE__, __LINE__, 3, "File '$v_stored_list[$i]' mtime=" . filemtime($p_file_list[$i]) . ' ' . date('l dS of F Y h:i:s A', filemtime($p_file_list[$i])));
3163
                    TrFctMessage(__FILE__, __LINE__, 3, 'Archived mtime=' . $v_header['mtime'] . ' ' . date('l dS of F Y h:i:s A', $v_header['mtime']));
3164
3165
                    // ----- Store found informations
3166
                    $v_found_file       = true;
3167
                    $v_current_filename = $p_file_list[$i];
3168
3169
                    // ----- Look if the file need to be updated
3170
                    if (filemtime($p_file_list[$i]) > $v_header['mtime']) {
3171
                        TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' need to be updated");
3172
                        $v_update_file = true;
3173
                    } else {
3174
                        TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' does not need to be updated");
3175
                        $v_update_file = false;
3176
                    }
3177
3178
                    // ----- Flag the name in order not to add the file at the end
3179
                    $v_found_list[$i] = 1;
3180
                } else {
3181
                    TrFctMessage(__FILE__, __LINE__, 4, "File '$p_file_list[$i]' is not " . $v_header['filename'] . '');
3182
                }
3183
            }
3184
3185
            // ----- Copy files that do not need to be updated
3186
            if (!$v_update_file) {
3187
                TrFctMessage(__FILE__, __LINE__, 2, 'Keep file ' . $v_header['filename'] . '');
3188
3189
                // ----- Write the file header
3190
                if ($p_tar_mode === 'tar') {
3191
                    fwrite($v_temp_tar, $v_binary_data, 512);
3192
                } else {
3193
                    gzputs($v_temp_tar, $v_binary_data, 512);
3194
                }
3195
3196
                // ----- Write the file data
3197
                $n = ceil($v_header['size'] / 512);
3198
                for ($j = 0; $j < $n; ++$j) {
3199
                    TrFctMessage(__FILE__, __LINE__, 3, 'Read complete 512 bytes block number ' . ($j + 1));
3200
                    if ($p_tar_mode === 'tar') {
3201
                        $v_content = fread($v_tar, 512);
3202
                        fwrite($v_temp_tar, $v_content, 512);
3203
                    } else {
3204
                        $v_content = gzread($v_tar, 512);
3205
                        gzwrite($v_temp_tar, $v_content, 512);
3206
                    }
3207
                }
3208
3209
                // ----- File name and properties are logged if listing mode or file is extracted
3210
                TrFctMessage(__FILE__, __LINE__, 2, 'Memorize info about file ' . $v_header['filename'] . '');
3211
3212
                // ----- Add the array describing the file into the list
3213
                $p_list_detail[$v_nb]           = $v_header;
3214
                $p_list_detail[$v_nb]['status'] = ($v_found_file ? 'not_updated' : 'ok');
3215
3216
                // ----- Increment
3217
                ++$v_nb;
3218
            } // ----- Look for file that need to be updated
3219
            else {
3220
                // ----- Trace
3221
                TrFctMessage(__FILE__, __LINE__, 2, "Start update of file '$v_current_filename'");
3222
3223
                // ----- Store the old file size
3224
                $v_old_size = $v_header['size'];
3225
3226
                // ----- Add the file
3227 View Code Duplication
                if (($v_result = PclTarHandleAddFile($v_temp_tar, $v_current_filename, $p_tar_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1) {
3228
                    // ----- Close the tarfile
3229
                    if ($p_tar_mode === 'tar') {
3230
                        fclose($v_tar);
3231
                        fclose($v_temp_tar);
3232
                    } else {
3233
                        gzclose($v_tar);
3234
                        gzclose($v_temp_tar);
3235
                    }
3236
                    @unlink($p_temp_tarname);
3237
3238
                    // ----- Return status
3239
                    TrFctEnd(__FILE__, __LINE__, $v_result);
3240
3241
                    return $v_result;
3242
                }
3243
3244
                // ----- Trace
3245
                TrFctMessage(__FILE__, __LINE__, 2, 'Skip old file ' . $v_header['filename'] . '');
3246
3247
                // ----- Jump to next file
3248
                if ($p_tar_mode === 'tar') {
3249
                    fseek($v_tar, ftell($v_tar) + (ceil($v_old_size / 512) * 512));
3250
                } else {
3251
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_old_size / 512) * 512));
3252
                }
3253
3254
                // ----- Add the array describing the file into the list
3255
                $p_list_detail[$v_nb]           = $v_header;
3256
                $p_list_detail[$v_nb]['status'] = 'updated';
3257
3258
                // ----- Increment
3259
                ++$v_nb;
3260
            }
3261
3262
            // ----- Look for end of file
3263
            if ($p_tar_mode === 'tar') {
3264
                $v_end_of_file = feof($v_tar);
3265
            } else {
3266
                $v_end_of_file = gzeof($v_tar);
3267
            }
3268
        }
3269
3270
        // ----- Look for files that does not exists in the archive and need to be added
3271
        for ($i = 0, $iMax = count($p_file_list); $i < $iMax; ++$i) {
3272
            // ----- Look if file not found in the archive
3273
            if (!$v_found_list[$i]) {
3274
                TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' need to be added");
3275
3276
                // ----- Add the file
3277 View Code Duplication
                if (($v_result = PclTarHandleAddFile($v_temp_tar, $p_file_list[$i], $p_tar_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1) {
3278
                    // ----- Close the tarfile
3279
                    if ($p_tar_mode === 'tar') {
3280
                        fclose($v_tar);
3281
                        fclose($v_temp_tar);
3282
                    } else {
3283
                        gzclose($v_tar);
3284
                        gzclose($v_temp_tar);
3285
                    }
3286
                    @unlink($p_temp_tarname);
3287
3288
                    // ----- Return status
3289
                    TrFctEnd(__FILE__, __LINE__, $v_result);
3290
3291
                    return $v_result;
3292
                }
3293
3294
                // ----- Add the array describing the file into the list
3295
                $p_list_detail[$v_nb]           = $v_header;
3296
                $p_list_detail[$v_nb]['status'] = 'added';
3297
3298
                // ----- Increment
3299
                ++$v_nb;
3300
            } else {
3301
                TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' was already updated if needed");
3302
            }
3303
        }
3304
3305
        // ----- Write the last empty buffer
3306
        PclTarHandleFooter($v_temp_tar, $p_tar_mode);
3307
3308
        // ----- Close the tarfile
3309
        if ($p_tar_mode === 'tar') {
3310
            fclose($v_tar);
3311
            fclose($v_temp_tar);
3312
        } else {
3313
            gzclose($v_tar);
3314
            gzclose($v_temp_tar);
3315
        }
3316
3317
        // ----- Unlink tar file
3318
        if (!@unlink($p_tarname)) {
3319
            // ----- Error log
3320
            PclErrorLog(-11, "Error while deleting archive name $p_tarname");
3321
        }
3322
3323
        // ----- Rename tar file
3324
        if (!@rename($v_temp_tarname, $p_tarname)) {
3325
            // ----- Error log
3326
            PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
3327
3328
            // ----- Return
3329
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3330
3331
            return PclErrorCode();
3332
        }
3333
3334
        // ----- Return
3335
        TrFctEnd(__FILE__, __LINE__, $v_result);
3336
3337
        return $v_result;
3338
    }
3339
3340
    // --------------------------------------------------------------------------------
3341
3342
    // --------------------------------------------------------------------------------
3343
    // Function : PclTarHandleReadHeader()
3344
    // Description :
3345
    // Parameters :
3346
    // Return Values :
3347
    // --------------------------------------------------------------------------------
3348
    /**
3349
     * @param $v_binary_data
3350
     * @param $v_header
3351
     *
3352
     * @return int
3353
     */
3354
    function PclTarHandleReadHeader($v_binary_data, &$v_header)
3355
    {
3356
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleReadHeader', '');
3357
        $v_result = 1;
3358
3359
        // ----- Read the 512 bytes header
3360
        /*
3361
    if ($p_tar_mode == "tar")
3362
      $v_binary_data = fread($p_tar, 512);
3363
    else
3364
      $v_binary_data = gzread($p_tar, 512);
3365
    */
3366
3367
        // ----- Look for no more block
3368 View Code Duplication
        if ('' === $v_binary_data) {
3369
            $v_header['filename'] = '';
3370
            $v_header['status']   = 'empty';
3371
3372
            // ----- Return
3373
            TrFctEnd(__FILE__, __LINE__, $v_result, 'End of archive found');
3374
3375
            return $v_result;
3376
        }
3377
3378
        // ----- Look for invalid block size
3379
        if (strlen($v_binary_data) != 512) {
3380
            $v_header['filename'] = '';
3381
            $v_header['status']   = 'invalid_header';
3382
            TrFctMessage(__FILE__, __LINE__, 2, 'Invalid block size : ' . strlen($v_binary_data));
3383
3384
            // ----- Error log
3385
            PclErrorLog(-10, 'Invalid block size : ' . strlen($v_binary_data));
3386
3387
            // ----- Return
3388
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3389
3390
            return PclErrorCode();
3391
        }
3392
3393
        // ----- Calculate the checksum
3394
        $v_checksum = 0;
3395
        // ..... First part of the header
3396 View Code Duplication
        for ($i = 0; $i < 148; ++$i) {
3397
            $v_checksum += ord(substr($v_binary_data, $i, 1));
3398
        }
3399
        // ..... Ignore the checksum value and replace it by ' ' (space)
3400
        for ($i = 148; $i < 156; ++$i) {
3401
            $v_checksum += ord(' ');
3402
        }
3403
        // ..... Last part of the header
3404 View Code Duplication
        for ($i = 156; $i < 512; ++$i) {
3405
            $v_checksum += ord(substr($v_binary_data, $i, 1));
3406
        }
3407
        TrFctMessage(__FILE__, __LINE__, 3, "Calculated checksum : $v_checksum");
3408
3409
        // ----- Extract the values
3410
        TrFctMessage(__FILE__, __LINE__, 2, "Header : '$v_binary_data'");
3411
        $v_data = unpack('a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor', $v_binary_data);
3412
3413
        // ----- Extract the checksum for check
3414
        $v_header['checksum'] = octdec(trim($v_data['checksum']));
3415
        TrFctMessage(__FILE__, __LINE__, 3, 'File checksum : ' . $v_header['checksum'] . '');
3416
        if ($v_header['checksum'] != $v_checksum) {
3417
            TrFctMessage(__FILE__, __LINE__, 2, "File checksum is invalid : $v_checksum calculated, " . $v_header['checksum'] . ' expected');
3418
3419
            $v_header['filename'] = '';
3420
            $v_header['status']   = 'invalid_header';
3421
3422
            // ----- Look for last block (empty block)
3423 View Code Duplication
            if (($v_checksum == 256) && ($v_header['checksum'] == 0)) {
3424
                $v_header['status'] = 'empty';
3425
                // ----- Return
3426
                TrFctEnd(__FILE__, __LINE__, $v_result, 'End of archive found');
3427
3428
                return $v_result;
3429
            }
3430
3431
            // ----- Error log
3432
            PclErrorLog(-13, "Invalid checksum : $v_checksum calculated, " . $v_header['checksum'] . ' expected');
3433
3434
            // ----- Return
3435
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3436
3437
            return PclErrorCode();
3438
        }
3439
        TrFctMessage(__FILE__, __LINE__, 2, "File checksum is valid ($v_checksum)");
3440
3441
        // ----- Extract the properties
3442
        $v_header['filename'] = trim($v_data['filename']);
3443
        TrFctMessage(__FILE__, __LINE__, 2, 'Name : ' . $v_header['filename'] . '');
3444
        $v_header['mode'] = octdec(trim($v_data['mode']));
3445
        TrFctMessage(__FILE__, __LINE__, 2, "Mode : '" . decoct($v_header['mode']) . "'");
3446
        $v_header['uid'] = octdec(trim($v_data['uid']));
3447
        TrFctMessage(__FILE__, __LINE__, 2, "Uid : '" . $v_header['uid'] . "'");
3448
        $v_header['gid'] = octdec(trim($v_data['gid']));
3449
        TrFctMessage(__FILE__, __LINE__, 2, "Gid : '" . $v_header['gid'] . "'");
3450
        $v_header['size'] = octdec(trim($v_data['size']));
3451
        TrFctMessage(__FILE__, __LINE__, 2, "Size : '" . $v_header['size'] . "'");
3452
        $v_header['mtime'] = octdec(trim($v_data['mtime']));
3453
        TrFctMessage(__FILE__, __LINE__, 2, 'Date : ' . date('l dS of F Y h:i:s A', $v_header['mtime']));
3454
        if (($v_header['typeflag'] = $v_data['typeflag']) == '5') {
3455
            $v_header['size'] = 0;
3456
            TrFctMessage(__FILE__, __LINE__, 2, "Size (folder) : '" . $v_header['size'] . "'");
3457
        }
3458
        TrFctMessage(__FILE__, __LINE__, 2, 'File typeflag : ' . $v_header['typeflag'] . '');
3459
        /* ----- All these fields are removed form the header because they do not carry interesting info
3460
    $v_header[link] = trim($v_data[link]);
3461
    TrFctMessage(__FILE__, __LINE__, 2, "Linkname : $v_header[linkname]");
3462
    $v_header[magic] = trim($v_data[magic]);
3463
    TrFctMessage(__FILE__, __LINE__, 2, "Magic : $v_header[magic]");
3464
    $v_header[version] = trim($v_data[version]);
3465
    TrFctMessage(__FILE__, __LINE__, 2, "Version : $v_header[version]");
3466
    $v_header[uname] = trim($v_data[uname]);
3467
    TrFctMessage(__FILE__, __LINE__, 2, "Uname : $v_header[uname]");
3468
    $v_header[gname] = trim($v_data[gname]);
3469
    TrFctMessage(__FILE__, __LINE__, 2, "Gname : $v_header[gname]");
3470
    $v_header[devmajor] = trim($v_data[devmajor]);
3471
    TrFctMessage(__FILE__, __LINE__, 2, "Devmajor : $v_header[devmajor]");
3472
    $v_header[devminor] = trim($v_data[devminor]);
3473
    TrFctMessage(__FILE__, __LINE__, 2, "Devminor : $v_header[devminor]");
3474
    */
3475
3476
        // ----- Set the status field
3477
        $v_header['status'] = 'ok';
3478
3479
        // ----- Return
3480
        TrFctEnd(__FILE__, __LINE__, $v_result);
3481
3482
        return $v_result;
3483
    }
3484
3485
    // --------------------------------------------------------------------------------
3486
3487
    // --------------------------------------------------------------------------------
3488
    // Function : PclTarHandlerDirCheck()
3489
    // Description :
3490
    //   Check if a directory exists, if not it creates it and all the parents directory
3491
    //   which may be useful.
3492
    // Parameters :
3493
    //   $p_dir : Directory path to check (without / at the end).
3494
    // Return Values :
3495
    //    1 : OK
3496
    //   -1 : Unable to create directory
3497
    // --------------------------------------------------------------------------------
3498
    /**
3499
     * @param $p_dir
3500
     *
3501
     * @return int
3502
     */
3503
    function PclTarHandlerDirCheck($p_dir)
3504
    {
3505
        $v_result = 1;
3506
3507
        TrFctStart(__FILE__, __LINE__, 'PclTarHandlerDirCheck', "$p_dir");
3508
3509
        // ----- Check the directory availability
3510
        if (('' == $p_dir) || is_dir($p_dir)) {
3511
            TrFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
3512
3513
            return 1;
3514
        }
3515
3516
        // ----- Look for file alone
3517
        /*
3518
    if (!strstr("$p_dir", "/")) {
3519
      TrFctEnd(__FILE__, __LINE__,  "'$p_dir' is a file with no directory");
3520
3521
      return 1;
3522
    }
3523
    */
3524
3525
        // ----- Extract parent directory
3526
        $p_parent_dir = dirname($p_dir);
3527
        TrFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
3528
3529
        // ----- Just a check
3530
        if ($p_parent_dir != $p_dir) {
3531
            // ----- Look for parent directory
3532
            if ($p_parent_dir != '') {
3533
                if (($v_result = PclTarHandlerDirCheck($p_parent_dir)) != 1) {
3534
                    TrFctEnd(__FILE__, __LINE__, $v_result);
3535
3536
                    return $v_result;
3537
                }
3538
            }
3539
        }
3540
3541
        // ----- Create the directory
3542
        TrFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
3543
        if (!@mkdir($p_dir, 0777)) {
3544
            // ----- Error log
3545
            PclErrorLog(-8, "Unable to create directory '$p_dir'");
3546
3547
            // ----- Return
3548
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3549
3550
            return PclErrorCode();
3551
        }
3552
3553
        // ----- Return
3554
        TrFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
3555
3556
        return $v_result;
3557
    }
3558
3559
    // --------------------------------------------------------------------------------
3560
3561
    // --------------------------------------------------------------------------------
3562
    // Function : PclTarHandleExtension()
3563
    // Description :
3564
    // Parameters :
3565
    // Return Values :
3566
    // --------------------------------------------------------------------------------
3567
    /**
3568
     * @param $p_tarname
3569
     *
3570
     * @return string
3571
     */
3572
    function PclTarHandleExtension($p_tarname)
3573
    {
3574
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtension', "tar=$p_tarname");
3575
3576
        // ----- Look for file extension
3577
        if ((substr($p_tarname, -7) === '.tar.gz') || (substr($p_tarname, -4) === '.tgz')) {
3578
            TrFctMessage(__FILE__, __LINE__, 2, 'Archive is a gzip tar');
3579
            $v_tar_mode = 'tgz';
3580
        } else {
3581
            if (substr($p_tarname, -4) === '.tar') {
3582
                TrFctMessage(__FILE__, __LINE__, 2, 'Archive is a tar');
3583
                $v_tar_mode = 'tar';
3584
            } else {
3585
                // ----- Error log
3586
                PclErrorLog(-9, 'Invalid archive extension');
3587
3588
                TrFctMessage(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3589
3590
                $v_tar_mode = '';
3591
            }
3592
        }
3593
3594
        // ----- Return
3595
        TrFctEnd(__FILE__, __LINE__, $v_tar_mode);
3596
3597
        return $v_tar_mode;
3598
    }
3599
3600
    // --------------------------------------------------------------------------------
3601
3602
    // --------------------------------------------------------------------------------
3603
    // Function : PclTarHandlePathReduction()
3604
    // Description :
3605
    // Parameters :
3606
    // Return Values :
3607
    // --------------------------------------------------------------------------------
3608
    /**
3609
     * @param $p_dir
3610
     *
3611
     * @return string
3612
     */
3613
    function PclTarHandlePathReduction($p_dir)
3614
    {
3615
        TrFctStart(__FILE__, __LINE__, 'PclTarHandlePathReduction', "dir='$p_dir'");
3616
        $v_result = '';
3617
3618
        // ----- Look for not empty path
3619
        if ($p_dir != '') {
3620
            // ----- Explode path by directory names
3621
            $v_list = explode('/', $p_dir);
3622
3623
            // ----- Study directories from last to first
3624
            for ($i = count($v_list) - 1; $i >= 0; --$i) {
3625
                // ----- Look for current path
3626
                if ($v_list[$i] === '.') {
3627
                    // ----- Ignore this directory
3628
                    // Should be the first $i=0, but no check is done
3629
                } else {
3630
                    if ($v_list[$i] === '..') {
3631
                        // ----- Ignore it and ignore the $i-1
3632
                        --$i;
3633
                    } else {
3634
                        if ((0 != $i) && ('' == $v_list[$i]) && ($i != (count($v_list) - 1))) {
3635
                            // ----- Ignore only the double '//' in path,
3636
                            // but not the first and last '/'
3637
                        } else {
3638
                            $v_result = $v_list[$i] . ($i != (count($v_list) - 1) ? '/' . $v_result : '');
3639
                        }
3640
                    }
3641
                }
3642
            }
3643
        }
3644
3645
        // ----- Return
3646
        TrFctEnd(__FILE__, __LINE__, $v_result);
3647
3648
        return $v_result;
3649
    }
3650
3651
    // --------------------------------------------------------------------------------
3652
3653
    // ----- End of double include look
3654
}
3655