PclTarMerge()   F
last analyzed

Complexity

Conditions 42
Paths 564

Size

Total Lines 282
Code Lines 128

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 128
dl 0
loc 282
rs 0.4844
c 0
b 0
f 0
cc 42
nc 564
nop 4

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
        require_once $gPcltarLibDir . '/pclerror.lib.php';
64
    }
65
    if (!defined('PCLTRACE_LIB')) {
66
        require_once $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
        if (('' == $p_mode) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
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
        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)) {
0 ignored issues
show
introduced by
The condition is_string($p_filelist) is always true.
Loading history...
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 = [];
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 = [];
255
256
        // ----- Extract the tar format from the extension
257
        if (('' == $p_mode) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
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
        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 (1 != $v_result) {
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
    function PclTarList($p_tarname, $p_mode = '')
327
    {
328
        TrFctStart(__FILE__, __LINE__, 'PclTarList', "tar=$p_tarname, mode='$p_mode'");
329
        $v_result = 1;
0 ignored issues
show
Unused Code introduced by
The assignment to $v_result is dead and can be removed.
Loading history...
330
331
        // ----- Extract the tar format from the extension
332
        if (('' == $p_mode) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
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 = [];
343
        if (1 != ($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, 'list', '', $p_mode, ''))) {
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
    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;
0 ignored issues
show
Unused Code introduced by
The assignment to $v_result is dead and can be removed.
Loading history...
393
394
        // ----- Extract the tar format from the extension
395
        if (('' == $p_mode) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
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 (1 != ($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, 'complete', $p_path, $p_mode, $p_remove_path))) {
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
    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) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
465
            if ('' == ($p_mode = PclTarHandleExtension($p_tarname))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $p_mode is dead and can be removed.
Loading history...
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 (1 != ($v_result = PclTarHandleExtract($p_tarname, $p_filelist, $p_list, 'partial', $p_path, $v_tar_mode, $p_remove_path))) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $v_tar_mode seems to be never defined.
Loading history...
Unused Code introduced by
The assignment to $v_result is dead and can be removed.
Loading history...
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 (1 != ($v_result = PclTarHandleExtract($p_tarname, $v_list, $p_list, 'partial', $p_path, $v_tar_mode, $p_remove_path))) {
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
    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) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
560
            if ('' == ($p_mode = PclTarHandleExtension($p_tarname))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $p_mode is dead and can be removed.
Loading history...
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 (1 != ($v_result = PclTarHandleExtractByIndexList($p_tarname, (string)$p_index, $p_list, $p_path, $p_remove_path, $v_tar_mode))) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $v_tar_mode seems to be never defined.
Loading history...
Unused Code introduced by
The assignment to $v_result is dead and can be removed.
Loading history...
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 (1 != ($v_result = PclTarHandleExtractByIndexList($p_tarname, $p_index, $p_list, $p_path, $p_remove_path, $v_tar_mode))) {
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) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
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 (1 != ($v_result = PclTarHandleDelete($p_tarname, $p_filelist, $p_list, $p_mode))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $v_result is dead and can be removed.
Loading history...
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 (1 != ($v_result = PclTarHandleDelete($p_tarname, $v_list, $p_list, $p_mode))) {
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
    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) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
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 (1 != ($v_result = PclTarHandleUpdate($p_tarname, $p_filelist, $p_list, $p_mode, $p_add_dir, $p_remove_dir))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $v_result is dead and can be removed.
Loading history...
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 (1 != ($v_result = PclTarHandleUpdate($p_tarname, $v_list, $p_list, $p_mode, $p_add_dir, $p_remove_dir))) {
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;
0 ignored issues
show
Unused Code introduced by
The assignment to $v_result is dead and can be removed.
Loading history...
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) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
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) || (('tar' !== $p_mode_add) && ('tgz' !== $p_mode_add))) {
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
        if ((!is_file($p_tarname)) || ((0 != (($v_size = filesize($p_tarname)) % 512)) && ('tar' === $p_mode))) {
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
        if ((!is_file($p_tarname_add))
835
            || ((0 != (($v_size_add = filesize($p_tarname_add)) % 512))
0 ignored issues
show
Unused Code introduced by
The assignment to $v_size_add is dead and can be removed.
Loading history...
836
                && ('tar' === $p_mode_add))) {
837
            // ----- Error log
838
            if (!is_file($p_tarname_add)) {
839
                PclErrorLog(-4, "Archive '$p_tarname_add' does not exist");
840
            } else {
841
                PclErrorLog(-6, "Archive '$p_tarname_add' has invalid size " . filesize($p_tarname_add) . '(not a 512 block multiple)');
842
            }
843
844
            // ----- Return
845
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
846
847
            return PclErrorCode();
848
        }
849
850
        // ----- Look for compressed archive
851
        if ('tgz' === $p_mode) {
852
            // ----- Open the file in read mode
853
            if (0 == ($p_tar = @gzopen($p_tarname, 'rb'))) {
854
                // ----- Error log
855
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
856
857
                // ----- Return
858
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
859
860
                return PclErrorCode();
861
            }
862
863
            // ----- Open a temporary file in write mode
864
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
865
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
866
            if (0 == ($v_temp_tar = @gzopen($v_temp_tarname, 'wb'))) {
867
                // ----- Close tar file
868
                gzclose($p_tar);
0 ignored issues
show
Bug introduced by
It seems like $p_tar can also be of type false; however, parameter $stream of gzclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

868
                gzclose(/** @scrutinizer ignore-type */ $p_tar);
Loading history...
869
870
                // ----- Error log
871
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
872
873
                // ----- Return
874
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
875
876
                return PclErrorCode();
877
            }
878
879
            // ----- Read the first 512 bytes block
880
            $v_buffer = gzread($p_tar, 512);
0 ignored issues
show
Bug introduced by
It seems like $p_tar can also be of type false; however, parameter $stream of gzread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

880
            $v_buffer = gzread(/** @scrutinizer ignore-type */ $p_tar, 512);
Loading history...
881
882
            // ----- Read the following blocks but not the last one
883
            if (!gzeof($p_tar)) {
0 ignored issues
show
Bug introduced by
It seems like $p_tar can also be of type false; however, parameter $stream of gzeof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

883
            if (!gzeof(/** @scrutinizer ignore-type */ $p_tar)) {
Loading history...
884
                TrFctMessage(__FILE__, __LINE__, 3, 'More than one 512 block file');
885
                $i = 1;
886
887
                // ----- Read new 512 block and write the already read
888
                do {
889
                    // ----- Write the already read block
890
                    $v_binary_data = pack('a512', $v_buffer);
891
                    gzputs($v_temp_tar, $v_binary_data);
0 ignored issues
show
Bug introduced by
It seems like $v_temp_tar can also be of type false; however, parameter $stream of gzputs() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

891
                    gzputs(/** @scrutinizer ignore-type */ $v_temp_tar, $v_binary_data);
Loading history...
892
893
                    ++$i;
894
                    TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
895
896
                    // ----- Read next block
897
                    $v_buffer = gzread($p_tar, 512);
898
                } while (!gzeof($p_tar));
899
900
                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
901
            }
902
        } // ----- Look for uncompressed tar file
903
        else {
904
            if ('tar' === $p_mode) {
905
                // ----- Open the tar file
906
                if (0 == ($p_tar = fopen($p_tarname, 'r+b'))) {
907
                    // ----- Error log
908
                    PclErrorLog(-1, "Unable to open file '$p_tarname' in binary write mode");
909
910
                    // ----- Return
911
                    TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
912
913
                    return PclErrorCode();
914
                }
915
916
                // ----- Go to the beginning of last block
917
                TrFctMessage(__FILE__, __LINE__, 4, 'Position before :' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
918
                fseek($p_tar, $v_size - 512);
919
                TrFctMessage(__FILE__, __LINE__, 4, 'Position after :' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
920
            } // ----- Look for unknown type
921
            else {
922
                // ----- Error log
923
                PclErrorLog(-3, "Invalid tar mode $p_mode");
924
925
                // ----- Return
926
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
927
928
                return PclErrorCode();
929
            }
930
        }
931
932
        // ----- Look for type of archive to add
933
        if ('tgz' === $p_mode_add) {
934
            TrFctMessage(__FILE__, __LINE__, 4, "Opening file $p_tarname_add");
935
936
            // ----- Open the file in read mode
937
            if (0 == ($p_tar_add = @gzopen($p_tarname_add, 'rb'))) {
938
                // ----- Error log
939
                PclErrorLog(-2, "Unable to open file '$p_tarname_add' in binary read mode");
940
941
                // ----- Return
942
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
943
944
                return PclErrorCode();
945
            }
946
947
            // ----- Read the first 512 bytes block
948
            $v_buffer = gzread($p_tar_add, 512);
949
950
            // ----- Read the following blocks but not the last one
951
            if (!gzeof($p_tar_add)) {
952
                TrFctMessage(__FILE__, __LINE__, 3, 'More than one 512 block file');
953
                $i = 1;
954
955
                // ----- Read new 512 block and write the already read
956
                do {
957
                    // ----- Write the already read block
958
                    $v_binary_data = pack('a512', $v_buffer);
959
                    if ('tar' === $p_mode) {
960
                        fwrite($p_tar, $v_binary_data);
0 ignored issues
show
Bug introduced by
It seems like $p_tar can also be of type false; however, parameter $stream of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

960
                        fwrite(/** @scrutinizer ignore-type */ $p_tar, $v_binary_data);
Loading history...
961
                    } else {
962
                        gzputs($v_temp_tar, $v_binary_data);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $v_temp_tar does not seem to be defined for all execution paths leading up to this point.
Loading history...
963
                    }
964
965
                    ++$i;
966
                    TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
967
968
                    // ----- Read next block
969
                    $v_buffer = gzread($p_tar_add, 512);
970
                } while (!gzeof($p_tar_add));
971
972
                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
973
            }
974
975
            // ----- Close the files
976
            gzclose($p_tar_add);
977
        } // ----- Look for uncompressed tar file
978
        else {
979
            if ('tar' === $p_mode) {
980
                // ----- Open the file in read mode
981
                if (0 == ($p_tar_add = @fopen($p_tarname_add, 'rb'))) {
982
                    // ----- Error log
983
                    PclErrorLog(-2, "Unable to open file '$p_tarname_add' in binary read mode");
984
985
                    // ----- Return
986
                    TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
987
988
                    return PclErrorCode();
989
                }
990
991
                // ----- Read the first 512 bytes block
992
                $v_buffer = fread($p_tar_add, 512);
0 ignored issues
show
Bug introduced by
It seems like $p_tar_add can also be of type false; however, parameter $stream of fread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

992
                $v_buffer = fread(/** @scrutinizer ignore-type */ $p_tar_add, 512);
Loading history...
993
994
                // ----- Read the following blocks but not the last one
995
                if (!feof($p_tar_add)) {
0 ignored issues
show
Bug introduced by
It seems like $p_tar_add can also be of type false; however, parameter $stream of feof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

995
                if (!feof(/** @scrutinizer ignore-type */ $p_tar_add)) {
Loading history...
996
                    TrFctMessage(__FILE__, __LINE__, 3, 'More than one 512 block file');
997
                    $i = 1;
998
999
                    // ----- Read new 512 block and write the already read
1000
                    do {
1001
                        // ----- Write the already read block
1002
                        $v_binary_data = pack('a512', (string)$v_buffer);
1003
                        if ('tar' === $p_mode) {
1004
                            fwrite($p_tar, $v_binary_data);
1005
                        } else {
1006
                            gzputs($v_temp_tar, $v_binary_data);
1007
                        }
1008
1009
                        ++$i;
1010
                        TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
1011
1012
                        // ----- Read next block
1013
                        $v_buffer = fread($p_tar_add, 512);
1014
                    } while (!feof($p_tar_add));
1015
1016
                    TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
1017
                }
1018
1019
                // ----- Close the files
1020
                fclose($p_tar_add);
0 ignored issues
show
Bug introduced by
It seems like $p_tar_add can also be of type false; however, parameter $stream of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1020
                fclose(/** @scrutinizer ignore-type */ $p_tar_add);
Loading history...
1021
            }
1022
        }
1023
1024
        // ----- Call the footer of the tar archive
1025
        $v_result = PclTarHandleFooter($p_tar, $p_mode);
1026
1027
        // ----- Look for closing compressed archive
1028
        if ('tgz' === $p_mode) {
1029
            // ----- Close the files
1030
            gzclose($p_tar);
1031
            gzclose($v_temp_tar);
1032
1033
            // ----- Unlink tar file
1034
            if (!@unlink($p_tarname)) {
1035
                // ----- Error log
1036
                PclErrorLog(-11, "Error while deleting archive name $p_tarname");
1037
            }
1038
1039
            // ----- Rename tar file
1040
            if (!@rename($v_temp_tarname, $p_tarname)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $v_temp_tarname does not seem to be defined for all execution paths leading up to this point.
Loading history...
1041
                // ----- Error log
1042
                PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
1043
1044
                // ----- Return
1045
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1046
1047
                return PclErrorCode();
1048
            }
1049
1050
            // ----- Return
1051
            TrFctEnd(__FILE__, __LINE__, $v_result);
1052
1053
            return $v_result;
1054
        } // ----- Look for closing uncompressed tar file
1055
1056
        if ('tar' === $p_mode) {
1057
            // ----- Close the tarfile
1058
            fclose($p_tar);
1059
        }
1060
1061
        // ----- Return
1062
        TrFctEnd(__FILE__, __LINE__, $v_result);
1063
1064
        return $v_result;
1065
    }
1066
1067
    // --------------------------------------------------------------------------------
1068
1069
    // --------------------------------------------------------------------------------
1070
    // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1071
    // *****                                                        *****
1072
    // *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       *****
1073
    // --------------------------------------------------------------------------------
1074
1075
    // --------------------------------------------------------------------------------
1076
    // Function : PclTarHandleCreate()
1077
    // Description :
1078
    // Parameters :
1079
    //   $p_tarname : Name of the tar file
1080
    //   $p_list : An array containing the file or directory names to add in the tar
1081
    //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1082
    // Return Values :
1083
    // --------------------------------------------------------------------------------
1084
    /**
1085
     * @param        $p_tarname
1086
     * @param        $p_list
1087
     * @param        $p_mode
1088
     * @param string $p_add_dir
1089
     * @param string $p_remove_dir
1090
     *
1091
     * @return int
1092
     */
1093
    function PclTarHandleCreate($p_tarname, $p_list, $p_mode, $p_add_dir = '', $p_remove_dir = '')
1094
    {
1095
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleCreate', "tar=$p_tarname, list, mode=$p_mode, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1096
        $v_result      = 1;
1097
        $v_list_detail = [];
1098
1099
        // ----- Check the parameters
1100
        if (('' == $p_tarname) || (('tar' !== $p_mode) && ('tgz' !== $p_mode))) {
1101
            // ----- Error log
1102
            if ('' == $p_tarname) {
1103
                PclErrorLog(-3, 'Invalid empty archive name');
1104
            } else {
1105
                PclErrorLog(-3, "Unknown mode '$p_mode'");
1106
            }
1107
1108
            // ----- Return
1109
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1110
1111
            return PclErrorCode();
1112
        }
1113
1114
        // ----- Look for tar file
1115
        if ('tar' === $p_mode) {
1116
            // ----- Open the tar file
1117
            if (0 == ($p_tar = fopen($p_tarname, 'wb'))) {
1118
                // ----- Error log
1119
                PclErrorLog(-1, "Unable to open file [$p_tarname] in binary write mode");
1120
1121
                // ----- Return
1122
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1123
1124
                return PclErrorCode();
1125
            }
1126
1127
            // ----- Call the adding fct inside the tar
1128
            if (1 == ($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir))) {
1129
                // ----- Call the footer of the tar archive
1130
                $v_result = PclTarHandleFooter($p_tar, $p_mode);
1131
            }
1132
1133
            // ----- Close the tarfile
1134
            fclose($p_tar);
1135
        } // ----- Look for tgz file
1136
        else {
1137
            // ----- Open the tar file
1138
            if (0 == ($p_tar = @gzopen($p_tarname, 'wb'))) {
1139
                // ----- Error log
1140
                PclErrorLog(-1, "Unable to open file [$p_tarname] in binary write mode");
1141
1142
                // ----- Return
1143
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1144
1145
                return PclErrorCode();
1146
            }
1147
1148
            // ----- Call the adding fct inside the tar
1149
            if (1 == ($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir))) {
1150
                // ----- Call the footer of the tar archive
1151
                $v_result = PclTarHandleFooter($p_tar, $p_mode);
1152
            }
1153
1154
            // ----- Close the tarfile
1155
            gzclose($p_tar);
0 ignored issues
show
Bug introduced by
It seems like $p_tar can also be of type false; however, parameter $stream of gzclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1155
            gzclose(/** @scrutinizer ignore-type */ $p_tar);
Loading history...
1156
        }
1157
1158
        // ----- Return
1159
        TrFctEnd(__FILE__, __LINE__, $v_result);
1160
1161
        return $v_result;
1162
    }
1163
1164
    // --------------------------------------------------------------------------------
1165
1166
    // --------------------------------------------------------------------------------
1167
    // Function : PclTarHandleAppend()
1168
    // Description :
1169
    // Parameters :
1170
    //   $p_tarname : Name of the tar file
1171
    //   $p_list : An array containing the file or directory names to add in the tar
1172
    //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1173
    // Return Values :
1174
    // --------------------------------------------------------------------------------
1175
    /**
1176
     * @param $p_tarname
1177
     * @param $p_list
1178
     * @param $p_mode
1179
     * @param $p_list_detail
1180
     * @param $p_add_dir
1181
     * @param $p_remove_dir
1182
     *
1183
     * @return int
1184
     */
1185
    function PclTarHandleAppend($p_tarname, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir)
1186
    {
1187
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleAppend', "tar=$p_tarname, list, mode=$p_mode");
1188
        $v_result = 1;
1189
1190
        // ----- Check the parameters
1191
        if ('' == $p_tarname) {
1192
            // ----- Error log
1193
            PclErrorLog(-3, 'Invalid empty archive name');
1194
1195
            // ----- Return
1196
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1197
1198
            return PclErrorCode();
1199
        }
1200
1201
        clearstatcache();
1202
1203
        // ----- Check the file size
1204
        if ((!is_file($p_tarname)) || ((0 != (($v_size = filesize($p_tarname)) % 512)) && ('tar' === $p_mode))) {
1205
            // ----- Error log
1206
            if (!is_file($p_tarname)) {
1207
                PclErrorLog(-4, "Archive '$p_tarname' does not exist");
1208
            } else {
1209
                PclErrorLog(-6, "Archive '$p_tarname' has invalid size " . filesize($p_tarname) . '(not a 512 block multiple)');
1210
            }
1211
1212
            // ----- Return
1213
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1214
1215
            return PclErrorCode();
1216
        }
1217
1218
        // ----- Look for compressed archive
1219
        if ('tgz' === $p_mode) {
1220
            // ----- Open the file in read mode
1221
            if (0 == ($p_tar = @gzopen($p_tarname, 'rb'))) {
1222
                // ----- Error log
1223
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
1224
1225
                // ----- Return
1226
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1227
1228
                return PclErrorCode();
1229
            }
1230
1231
            // ----- Open a temporary file in write mode
1232
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
1233
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
1234
            if (0 == ($v_temp_tar = @gzopen($v_temp_tarname, 'wb'))) {
1235
                // ----- Close tar file
1236
                gzclose($p_tar);
0 ignored issues
show
Bug introduced by
It seems like $p_tar can also be of type false; however, parameter $stream of gzclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1236
                gzclose(/** @scrutinizer ignore-type */ $p_tar);
Loading history...
1237
1238
                // ----- Error log
1239
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
1240
1241
                // ----- Return
1242
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1243
1244
                return PclErrorCode();
1245
            }
1246
1247
            // ----- Read the first 512 bytes block
1248
            $v_buffer = gzread($p_tar, 512);
0 ignored issues
show
Bug introduced by
It seems like $p_tar can also be of type false; however, parameter $stream of gzread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1248
            $v_buffer = gzread(/** @scrutinizer ignore-type */ $p_tar, 512);
Loading history...
1249
1250
            // ----- Read the following blocks but not the last one
1251
            if (!gzeof($p_tar)) {
0 ignored issues
show
Bug introduced by
It seems like $p_tar can also be of type false; however, parameter $stream of gzeof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1251
            if (!gzeof(/** @scrutinizer ignore-type */ $p_tar)) {
Loading history...
1252
                TrFctMessage(__FILE__, __LINE__, 3, 'More than one 512 block file');
1253
                $i = 1;
1254
1255
                // ----- Read new 512 block and write the already read
1256
                do {
1257
                    // ----- Write the already read block
1258
                    $v_binary_data = pack('a512', $v_buffer);
1259
                    gzputs($v_temp_tar, $v_binary_data);
0 ignored issues
show
Bug introduced by
It seems like $v_temp_tar can also be of type false; however, parameter $stream of gzputs() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1259
                    gzputs(/** @scrutinizer ignore-type */ $v_temp_tar, $v_binary_data);
Loading history...
1260
1261
                    ++$i;
1262
                    TrFctMessage(__FILE__, __LINE__, 3, "Reading block $i");
1263
1264
                    // ----- Read next block
1265
                    $v_buffer = gzread($p_tar, 512);
1266
                } while (!gzeof($p_tar));
1267
1268
                TrFctMessage(__FILE__, __LINE__, 3, "$i 512 bytes blocks");
1269
            }
1270
1271
            // ----- Call the adding fct inside the tar
1272
            if (1 == ($v_result = PclTarHandleAddList($v_temp_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir))) {
1273
                // ----- Call the footer of the tar archive
1274
                $v_result = PclTarHandleFooter($v_temp_tar, $p_mode);
1275
            }
1276
1277
            // ----- Close the files
1278
            gzclose($p_tar);
1279
            gzclose($v_temp_tar);
1280
1281
            // ----- Unlink tar file
1282
            if (!@unlink($p_tarname)) {
1283
                // ----- Error log
1284
                PclErrorLog(-11, "Error while deleting archive name $p_tarname");
1285
            }
1286
1287
            // ----- Rename tar file
1288
            if (!@rename($v_temp_tarname, $p_tarname)) {
1289
                // ----- Error log
1290
                PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
1291
1292
                // ----- Return
1293
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1294
1295
                return PclErrorCode();
1296
            }
1297
1298
            // ----- Return
1299
            TrFctEnd(__FILE__, __LINE__, $v_result);
1300
1301
            return $v_result;
1302
        } // ----- Look for uncompressed tar file
1303
1304
        if ('tar' === $p_mode) {
1305
            // ----- Open the tar file
1306
            if (0 == ($p_tar = fopen($p_tarname, 'r+b'))) {
1307
                // ----- Error log
1308
                PclErrorLog(-1, "Unable to open file '$p_tarname' in binary write mode");
1309
1310
                // ----- Return
1311
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1312
1313
                return PclErrorCode();
1314
            }
1315
1316
            // ----- Go to the beginning of last block
1317
            TrFctMessage(__FILE__, __LINE__, 4, 'Position before :' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
1318
            fseek($p_tar, $v_size - 512);
1319
            TrFctMessage(__FILE__, __LINE__, 4, 'Position after :' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
1320
1321
            // ----- Call the adding fct inside the tar
1322
            if (1 == ($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir))) {
1323
                // ----- Call the footer of the tar archive
1324
                $v_result = PclTarHandleFooter($p_tar, $p_mode);
1325
            }
1326
1327
            // ----- Close the tarfile
1328
            fclose($p_tar);
1329
        } // ----- Look for unknown type
1330
        else {
1331
            // ----- Error log
1332
            PclErrorLog(-3, "Invalid tar mode $p_mode");
1333
1334
            // ----- Return
1335
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1336
1337
            return PclErrorCode();
1338
        }
1339
1340
        // ----- Return
1341
        TrFctEnd(__FILE__, __LINE__, $v_result);
1342
1343
        return $v_result;
1344
    }
1345
1346
    // --------------------------------------------------------------------------------
1347
1348
    // --------------------------------------------------------------------------------
1349
    // Function : PclTarHandleAddList()
1350
    // Description :
1351
    //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
1352
    //   different from the real path of the file. This is usefull if you want to have PclTar
1353
    //   running in any directory, and memorize relative path from an other directory.
1354
    // Parameters :
1355
    //   $p_tar : File descriptor of the tar archive
1356
    //   $p_list : An array containing the file or directory names to add in the tar
1357
    //   $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1358
    //   $p_list_detail : list of added files with their properties (specially the status field)
1359
    //   $p_add_dir : Path to add in the filename path archived
1360
    //   $p_remove_dir : Path to remove in the filename path archived
1361
    // Return Values :
1362
    // --------------------------------------------------------------------------------
1363
    /**
1364
     * @param $p_tar
1365
     * @param $p_list
1366
     * @param $p_mode
1367
     * @param $p_list_detail
1368
     * @param $p_add_dir
1369
     * @param $p_remove_dir
1370
     *
1371
     * @return int
1372
     */
1373
    function PclTarHandleAddList($p_tar, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir)
1374
    {
1375
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleAddList', "tar='$p_tar', list, mode='$p_mode', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1376
        $v_result = 1;
1377
        $v_header = [];
1378
1379
        // ----- Recuperate the current number of elt in list
1380
        $v_nb = count($p_list_detail);
1381
1382
        // ----- Check the parameters
1383
        if (0 == $p_tar) {
1384
            // ----- Error log
1385
            PclErrorLog(-3, 'Invalid file descriptor in file ' . __FILE__ . ', line ' . __LINE__);
1386
1387
            // ----- Return
1388
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1389
1390
            return PclErrorCode();
1391
        }
1392
1393
        // ----- Check the arguments
1394
        if (0 == count($p_list)) {
1395
            // ----- Error log
1396
            PclErrorLog(-3, 'Invalid file list parameter (invalid or empty list)');
1397
1398
            // ----- Return
1399
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1400
1401
            return PclErrorCode();
1402
        }
1403
1404
        // ----- Loop on the files
1405
        for ($j = 0; ($j < count($p_list)) && (1 == $v_result); ++$j) {
1406
            // ----- Recuperate the filename
1407
            $p_filename = $p_list[$j];
1408
1409
            TrFctMessage(__FILE__, __LINE__, 2, "Looking for file [$p_filename]");
1410
1411
            // ----- Skip empty file names
1412
            if ('' == $p_filename) {
1413
                TrFctMessage(__FILE__, __LINE__, 2, 'Skip empty filename');
1414
                continue;
1415
            }
1416
1417
            // ----- Check the filename
1418
            if (!is_dir($p_filename)) {
1419
                // ----- Error log
1420
                TrFctMessage(__FILE__, __LINE__, 2, "File '$p_filename' does not exists");
1421
                PclErrorLog(-4, "File '$p_filename' does not exists");
1422
1423
                // ----- Return
1424
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1425
1426
                return PclErrorCode();
1427
            }
1428
1429
            // ----- Check the path length
1430
            if (mb_strlen($p_filename) > 99) {
1431
                // ----- Error log
1432
                PclErrorLog(-5, "File name is too long (max. 99) : '$p_filename'");
1433
1434
                // ----- Return
1435
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1436
1437
                return PclErrorCode();
1438
            }
1439
1440
            TrFctMessage(__FILE__, __LINE__, 4, 'File position before header =' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
1441
1442
            // ----- Add the file
1443
            if (1 != ($v_result = PclTarHandleAddFile($p_tar, $p_filename, $p_mode, $v_header, $p_add_dir, $p_remove_dir))) {
1444
                // ----- Return status
1445
                TrFctEnd(__FILE__, __LINE__, $v_result);
1446
1447
                return $v_result;
1448
            }
1449
1450
            // ----- Store the file infos
1451
            $p_list_detail[$v_nb++] = $v_header;
1452
1453
            // ----- Look for directory
1454
            if (is_dir($p_filename)) {
1455
                TrFctMessage(__FILE__, __LINE__, 2, "$p_filename is a directory");
1456
1457
                // ----- Look for path
1458
                $v_path = '';
1459
                if ('.' !== $p_filename) {
1460
                    $v_path = $p_filename . '/';
1461
                }
1462
1463
                // ----- Read the directory for files and sub-directories
1464
                $p_hdir  = opendir($p_filename);
1465
                $p_hitem = readdir($p_hdir); // '.' directory
0 ignored issues
show
Unused Code introduced by
The assignment to $p_hitem is dead and can be removed.
Loading history...
1466
                $p_hitem = readdir($p_hdir); // '..' directory
1467
                while ($p_hitem = readdir($p_hdir)) {
1468
                    // ----- Look for a file
1469
                    if (is_file($v_path . $p_hitem)) {
1470
                        TrFctMessage(__FILE__, __LINE__, 4, "Add the file '" . $v_path . $p_hitem . "'");
1471
1472
                        // ----- Add the file
1473
                        if (1 != ($v_result = PclTarHandleAddFile($p_tar, $v_path . $p_hitem, $p_mode, $v_header, $p_add_dir, $p_remove_dir))) {
1474
                            // ----- Return status
1475
                            TrFctEnd(__FILE__, __LINE__, $v_result);
1476
1477
                            return $v_result;
1478
                        }
1479
1480
                        // ----- Store the file infos
1481
                        $p_list_detail[$v_nb++] = $v_header;
1482
                    } // ----- Recursive call to PclTarHandleAddFile()
1483
                    else {
1484
                        TrFctMessage(__FILE__, __LINE__, 4, "'" . $v_path . $p_hitem . "' is a directory");
1485
1486
                        // ----- Need an array as parameter
1487
                        $p_temp_list[0] = $v_path . $p_hitem;
1488
                        $v_result       = PclTarHandleAddList($p_tar, $p_temp_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
1489
                    }
1490
                }
1491
1492
                // ----- Free memory for the recursive loop
1493
                unset($p_temp_list, $p_hdir, $p_hitem);
1494
            } else {
1495
                TrFctMessage(__FILE__, __LINE__, 4, 'File position after blocks =' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
1496
            }
1497
        }
1498
1499
        // ----- Return
1500
        TrFctEnd(__FILE__, __LINE__, $v_result);
1501
1502
        return $v_result;
1503
    }
1504
1505
    // --------------------------------------------------------------------------------
1506
1507
    // --------------------------------------------------------------------------------
1508
    // Function : PclTarHandleAddFile()
1509
    // Description :
1510
    // Parameters :
1511
    // Return Values :
1512
    // --------------------------------------------------------------------------------
1513
    /**
1514
     * @param $p_tar
1515
     * @param $p_filename
1516
     * @param $p_mode
1517
     * @param $p_header
1518
     * @param $p_add_dir
1519
     * @param $p_remove_dir
1520
     *
1521
     * @return int
1522
     */
1523
    function PclTarHandleAddFile($p_tar, $p_filename, $p_mode, &$p_header, $p_add_dir, $p_remove_dir)
1524
    {
1525
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleAddFile', "tar='$p_tar', filename='$p_filename', p_mode='$p_mode', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1526
        $v_result = 1;
1527
1528
        // ----- Check the parameters
1529
        if (0 == $p_tar) {
1530
            // ----- Error log
1531
            PclErrorLog(-3, 'Invalid file descriptor in file ' . __FILE__ . ', line ' . __LINE__);
1532
1533
            // ----- Return
1534
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1535
1536
            return PclErrorCode();
1537
        }
1538
1539
        // ----- Skip empty file names
1540
        if ('' == $p_filename) {
1541
            // ----- Error log
1542
            PclErrorLog(-3, 'Invalid file list parameter (invalid or empty list)');
1543
1544
            // ----- Return
1545
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1546
1547
            return PclErrorCode();
1548
        }
1549
1550
        // ----- Calculate the stored filename
1551
        $v_stored_filename = $p_filename;
1552
        if ('' != $p_remove_dir) {
1553
            if ('/' !== mb_substr($p_remove_dir, -1)) {
1554
                $p_remove_dir .= '/';
1555
            }
1556
1557
            if ((0 === mb_strpos($p_filename, './')) || (0 === mb_strpos($p_remove_dir, './'))) {
1558
                if ((0 === mb_strpos($p_filename, './')) && (0 !== mb_strpos($p_remove_dir, './'))) {
1559
                    $p_remove_dir = './' . $p_remove_dir;
1560
                }
1561
                if ((0 !== mb_strpos($p_filename, './')) && (0 === mb_strpos($p_remove_dir, './'))) {
1562
                    $p_remove_dir = mb_substr($p_remove_dir, 2);
1563
                }
1564
            }
1565
1566
            if (0 === mb_strpos($p_filename, $p_remove_dir)) {
1567
                $v_stored_filename = mb_substr($p_filename, mb_strlen($p_remove_dir));
1568
                TrFctMessage(__FILE__, __LINE__, 3, "Remove path '$p_remove_dir' in file '$p_filename' = '$v_stored_filename'");
1569
            }
1570
        }
1571
        if ('' != $p_add_dir) {
1572
            if ('/' === mb_substr($p_add_dir, -1)) {
1573
                $v_stored_filename = $p_add_dir . $v_stored_filename;
1574
            } else {
1575
                $v_stored_filename = $p_add_dir . '/' . $v_stored_filename;
1576
            }
1577
            TrFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
1578
        }
1579
1580
        // ----- Check the path length
1581
        if (mb_strlen($v_stored_filename) > 99) {
1582
            // ----- Error log
1583
            PclErrorLog(-5, "Stored file name is too long (max. 99) : '$v_stored_filename'");
1584
1585
            // ----- Return
1586
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1587
1588
            return PclErrorCode();
1589
        }
1590
1591
        // ----- Look for a file
1592
        if (is_file($p_filename)) {
1593
            // ----- Open the source file
1594
            if (0 == ($v_file = fopen($p_filename, 'rb'))) {
1595
                // ----- Error log
1596
                PclErrorLog(-2, "Unable to open file '$p_filename' in binary read mode");
1597
1598
                // ----- Return
1599
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1600
1601
                return PclErrorCode();
1602
            }
1603
1604
            // ----- Call the header generation
1605
            if (1 != ($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename))) {
1606
                // ----- Return status
1607
                TrFctEnd(__FILE__, __LINE__, $v_result);
1608
1609
                return $v_result;
1610
            }
1611
1612
            TrFctMessage(__FILE__, __LINE__, 4, 'File position after header =' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
1613
1614
            // ----- Read the file by 512 octets blocks
1615
            $i = 0;
1616
            while ('' != ($v_buffer = fread($v_file, 512))) {
1617
                $v_binary_data = pack('a512', (string)$v_buffer);
1618
                if ('tar' === $p_mode) {
1619
                    fwrite($p_tar, $v_binary_data);
1620
                } else {
1621
                    gzputs($p_tar, $v_binary_data);
1622
                }
1623
                ++$i;
1624
            }
1625
            TrFctMessage(__FILE__, __LINE__, 2, "$i 512 bytes blocks");
1626
1627
            // ----- Close the file
1628
            fclose($v_file);
1629
1630
            TrFctMessage(__FILE__, __LINE__, 4, 'File position after blocks =' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
1631
        } // ----- Look for a directory
1632
        else {
1633
            // ----- Call the header generation
1634
            if (1 != ($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename))) {
1635
                // ----- Return status
1636
                TrFctEnd(__FILE__, __LINE__, $v_result);
1637
1638
                return $v_result;
1639
            }
1640
1641
            TrFctMessage(__FILE__, __LINE__, 4, 'File position after header =' . ('tar' === $p_mode ? ftell($p_tar) : gztell($p_tar)));
1642
        }
1643
1644
        // ----- Return
1645
        TrFctEnd(__FILE__, __LINE__, $v_result);
1646
1647
        return $v_result;
1648
    }
1649
1650
    // --------------------------------------------------------------------------------
1651
1652
    // --------------------------------------------------------------------------------
1653
    // Function : PclTarHandleHeader()
1654
    // Description :
1655
    //   This function creates in the TAR $p_tar, the TAR header for the file
1656
    //   $p_filename.
1657
    //
1658
    //   1. The informations needed to compose the header are recuperated and formatted
1659
    //   2. Two binary strings are composed for the first part of the header, before
1660
    //      and after checksum field.
1661
    //   3. The checksum is calculated from the two binary strings
1662
    //   4. The header is write in the tar file (first binary string, binary string
1663
    //      for checksum and last binary string).
1664
    // Parameters :
1665
    //   $p_tar : a valid file descriptor, opened in write mode,
1666
    //   $p_filename : The name of the file the header is for,
1667
    //   $p_mode : The mode of the archive ("tar" or "tgz").
1668
    //   $p_header : A pointer to a array where will be set the file properties
1669
    // Return Values :
1670
    // --------------------------------------------------------------------------------
1671
    /**
1672
     * @param $p_tar
1673
     * @param $p_filename
1674
     * @param $p_mode
1675
     * @param $p_header
1676
     * @param $p_stored_filename
1677
     *
1678
     * @return int
1679
     */
1680
    function PclTarHandleHeader($p_tar, $p_filename, $p_mode, &$p_header, $p_stored_filename)
1681
    {
1682
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleHeader', "tar=$p_tar, file='$p_filename', mode='$p_mode', stored_filename='$p_stored_filename'");
1683
        $v_result = 1;
1684
1685
        // ----- Check the parameters
1686
        if ((0 == $p_tar) || ('' == $p_filename)) {
1687
            // ----- Error log
1688
            PclErrorLog(-3, 'Invalid file descriptor in file ' . __FILE__ . ', line ' . __LINE__);
1689
1690
            // ----- Return
1691
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1692
1693
            return PclErrorCode();
1694
        }
1695
1696
        // ----- Filename (reduce the path of stored name)
1697
        if ('' == $p_stored_filename) {
1698
            $p_stored_filename = $p_filename;
1699
        }
1700
        $v_reduce_filename = PclTarHandlePathReduction($p_stored_filename);
1701
        TrFctMessage(__FILE__, __LINE__, 2, "Filename (reduced) '$v_reduce_filename', strlen " . mb_strlen($v_reduce_filename));
1702
1703
        // ----- Get file info
1704
        $v_info = stat($p_filename);
1705
        $v_uid  = sprintf('%6s ', decoct($v_info[4]));
1706
        $v_gid  = sprintf('%6s ', decoct($v_info[5]));
1707
        TrFctMessage(__FILE__, __LINE__, 3, "uid=$v_uid, gid=$v_gid");
1708
        $v_perms = sprintf('%6s ', decoct(fileperms($p_filename)));
1709
        TrFctMessage(__FILE__, __LINE__, 3, "file permissions $v_perms");
1710
1711
        // ----- File mtime
1712
        $v_mtime_data = filemtime($p_filename);
1713
        TrFctMessage(__FILE__, __LINE__, 2, "File mtime : $v_mtime_data");
1714
        $v_mtime = sprintf('%11s', decoct($v_mtime_data));
1715
1716
        // ----- File typeflag
1717
        // '0' or '\0' is the code for regular file
1718
        // '5' is directory
1719
        if (is_dir($p_filename)) {
1720
            $v_typeflag = '5';
1721
            $v_size     = 0;
1722
        } else {
1723
            $v_typeflag = '';
1724
1725
            // ----- Get the file size
1726
            clearstatcache();
1727
            $v_size = filesize($p_filename);
1728
        }
1729
1730
        TrFctMessage(__FILE__, __LINE__, 2, "File size : $v_size");
1731
        $v_size = sprintf('%11s ', decoct($v_size));
1732
1733
        TrFctMessage(__FILE__, __LINE__, 2, "File typeflag : $v_typeflag");
1734
1735
        // ----- Linkname
1736
        $v_linkname = '';
1737
1738
        // ----- Magic
1739
        $v_magic = '';
1740
1741
        // ----- Version
1742
        $v_version = '';
1743
1744
        // ----- uname
1745
        $v_uname = '';
1746
1747
        // ----- gname
1748
        $v_gname = '';
1749
1750
        // ----- devmajor
1751
        $v_devmajor = '';
1752
1753
        // ----- devminor
1754
        $v_devminor = '';
1755
1756
        // ----- prefix
1757
        $v_prefix = '';
1758
1759
        // ----- Compose the binary string of the header in two parts arround the checksum position
1760
        $v_binary_data_first = pack('a100a8a8a8a12A12', $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
1761
        $v_binary_data_last  = pack('a1a100a6a2a32a32a8a8a155a12', $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '');
1762
1763
        // ----- Calculate the checksum
1764
        $v_checksum = 0;
1765
        // ..... First part of the header
1766
        for ($i = 0; $i < 148; ++$i) {
1767
            $v_checksum += ord(mb_substr($v_binary_data_first, $i, 1));
1768
        }
1769
        // ..... Ignore the checksum value and replace it by ' ' (space)
1770
        for ($i = 148; $i < 156; ++$i) {
1771
            $v_checksum += ord(' ');
1772
        }
1773
        // ..... Last part of the header
1774
        for ($i = 156, $j = 0; $i < 512; ++$i, ++$j) {
1775
            $v_checksum += ord(mb_substr($v_binary_data_last, $j, 1));
1776
        }
1777
        TrFctMessage(__FILE__, __LINE__, 3, "Calculated checksum : $v_checksum");
1778
1779
        // ----- Write the first 148 bytes of the header in the archive
1780
        if ('tar' === $p_mode) {
1781
            fwrite($p_tar, $v_binary_data_first, 148);
1782
        } else {
1783
            gzputs($p_tar, $v_binary_data_first, 148);
1784
        }
1785
1786
        // ----- Write the calculated checksum
1787
        $v_checksum    = sprintf('%6s ', decoct($v_checksum));
1788
        $v_binary_data = pack('a8', $v_checksum);
1789
        if ('tar' === $p_mode) {
1790
            fwrite($p_tar, $v_binary_data, 8);
1791
        } else {
1792
            gzputs($p_tar, $v_binary_data, 8);
1793
        }
1794
1795
        // ----- Write the last 356 bytes of the header in the archive
1796
        if ('tar' === $p_mode) {
1797
            fwrite($p_tar, $v_binary_data_last, 356);
1798
        } else {
1799
            gzputs($p_tar, $v_binary_data_last, 356);
1800
        }
1801
1802
        // ----- Set the properties in the header "structure"
1803
        $p_header['filename'] = $v_reduce_filename;
1804
        $p_header['mode']     = $v_perms;
1805
        $p_header['uid']      = $v_uid;
1806
        $p_header['gid']      = $v_gid;
1807
        $p_header['size']     = $v_size;
1808
        $p_header['mtime']    = $v_mtime;
1809
        $p_header['typeflag'] = $v_typeflag;
1810
        $p_header['status']   = 'added';
1811
1812
        // ----- Return
1813
        TrFctEnd(__FILE__, __LINE__, $v_result);
1814
1815
        return $v_result;
1816
    }
1817
1818
    // --------------------------------------------------------------------------------
1819
1820
    // --------------------------------------------------------------------------------
1821
    // Function : PclTarHandleFooter()
1822
    // Description :
1823
    // Parameters :
1824
    // Return Values :
1825
    // --------------------------------------------------------------------------------
1826
    /**
1827
     * @param $p_tar
1828
     * @param $p_mode
1829
     *
1830
     * @return int
1831
     */
1832
    function PclTarHandleFooter($p_tar, $p_mode)
1833
    {
1834
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleFooter', "tar='$p_tar', p_mode=$p_mode");
1835
        $v_result = 1;
1836
1837
        // ----- Write the last 0 filled block for end of archive
1838
        $v_binary_data = pack('a512', '');
1839
        if ('tar' === $p_mode) {
1840
            fwrite($p_tar, $v_binary_data);
1841
        } else {
1842
            gzputs($p_tar, $v_binary_data);
1843
        }
1844
1845
        // ----- Return
1846
        TrFctEnd(__FILE__, __LINE__, $v_result);
1847
1848
        return $v_result;
1849
    }
1850
1851
    // --------------------------------------------------------------------------------
1852
1853
    // --------------------------------------------------------------------------------
1854
    // Function : PclTarHandleExtract()
1855
    // Description :
1856
    // Parameters :
1857
    //   $p_tarname : Filename of the tar (or tgz) archive
1858
    //   $p_file_list : An array which contains the list of files to extract, this
1859
    //                  array may be empty when $p_mode is 'complete'
1860
    //   $p_list_detail : An array where will be placed the properties of  each extracted/listed file
1861
    //   $p_mode : 'complete' will extract all files from the archive,
1862
    //             'partial' will look for files in $p_file_list
1863
    //             'list' will only list the files from the archive without any extract
1864
    //   $p_path : Path to add while writing the extracted files
1865
    //   $p_tar_mode : 'tar' for GNU TAR archive, 'tgz' for compressed archive
1866
    //   $p_remove_path : Path to remove (from the file memorized path) while writing the
1867
    //                    extracted files. If the path does not match the file path,
1868
    //                    the file is extracted with its memorized path.
1869
    //                    $p_remove_path does not apply to 'list' mode.
1870
    //                    $p_path and $p_remove_path are commulative.
1871
    // Return Values :
1872
    // --------------------------------------------------------------------------------
1873
    /**
1874
     * @param $p_tarname
1875
     * @param $p_file_list
1876
     * @param $p_list_detail
1877
     * @param $p_mode
1878
     * @param $p_path
1879
     * @param $p_tar_mode
1880
     * @param $p_remove_path
1881
     *
1882
     * @return int
1883
     */
1884
    function PclTarHandleExtract(
1885
        $p_tarname,
1886
        $p_file_list,
1887
        &$p_list_detail,
1888
        $p_mode,
1889
        $p_path,
1890
        $p_tar_mode,
1891
        $p_remove_path
1892
    ) {
1893
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtract', "archive='$p_tarname', list, mode=$p_mode, path=$p_path, tar_mode=$p_tar_mode, remove_path='$p_remove_path'");
1894
        $v_result      = 1;
1895
        $v_nb          = 0;
1896
        $v_extract_all = true;
1897
        $v_listing     = false;
1898
1899
        // ----- Check the path
1900
        //if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../")))
1901
        if ('' == $p_path) {
1902
            $p_path = './' . $p_path;
1903
        }
1904
1905
        // ----- Look for path to remove format (should end by /)
1906
        if (('' != $p_remove_path) && ('/' !== mb_substr($p_remove_path, -1))) {
1907
            $p_remove_path .= '/';
1908
        }
1909
        $p_remove_path_size = mb_strlen($p_remove_path);
1910
1911
        // ----- Study the mode
1912
        switch ($p_mode) {
1913
            case 'complete':
1914
                // ----- Flag extract of all files
1915
                $v_extract_all = true;
1916
                $v_listing     = false;
1917
                break;
1918
            case 'partial':
1919
                // ----- Flag extract of specific files
1920
                $v_extract_all = false;
1921
                $v_listing     = false;
1922
                break;
1923
            case 'list':
1924
                // ----- Flag list of all files
1925
                $v_extract_all = false;
1926
                $v_listing     = true;
1927
                break;
1928
            default:
1929
                // ----- Error log
1930
                PclErrorLog(-3, "Invalid extract mode ($p_mode)");
1931
1932
                // ----- Return
1933
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1934
1935
                return PclErrorCode();
1936
        }
1937
1938
        // ----- Open the tar file
1939
        if ('tar' === $p_tar_mode) {
1940
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in binary read mode');
1941
            $v_tar = fopen($p_tarname, 'rb');
1942
        } else {
1943
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in gzip binary read mode');
1944
            $v_tar = @gzopen($p_tarname, 'rb');
1945
        }
1946
1947
        // ----- Check that the archive is open
1948
        if (0 == $v_tar) {
1949
            // ----- Error log
1950
            PclErrorLog(-2, "Unable to open archive '$p_tarname' in binary read mode");
1951
1952
            // ----- Return
1953
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
1954
1955
            return PclErrorCode();
1956
        }
1957
1958
        // ----- Read the blocks
1959
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof($v_tar) : gzeof($v_tar)))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $v_end_of_file is dead and can be removed.
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzeof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1959
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof($v_tar) : gzeof(/** @scrutinizer ignore-type */ $v_tar)))) {
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of feof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1959
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof(/** @scrutinizer ignore-type */ $v_tar) : gzeof($v_tar)))) {
Loading history...
1960
            TrFctMessage(__FILE__, __LINE__, 3, 'Looking for next header ...');
1961
1962
            // ----- Clear cache of file infos
1963
            clearstatcache();
1964
1965
            // ----- Reset extract tag
1966
            $v_extract_file       = false;
1967
            $v_extraction_stopped = 0;
1968
1969
            // ----- Read the 512 bytes header
1970
            if ('tar' === $p_tar_mode) {
1971
                $v_binary_data = fread($v_tar, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1971
                $v_binary_data = fread(/** @scrutinizer ignore-type */ $v_tar, 512);
Loading history...
1972
            } else {
1973
                $v_binary_data = gzread($v_tar, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1973
                $v_binary_data = gzread(/** @scrutinizer ignore-type */ $v_tar, 512);
Loading history...
1974
            }
1975
1976
            // ----- Read the header properties
1977
            if (1 != ($v_result = PclTarHandleReadHeader($v_binary_data, $v_header))) {
1978
                // ----- Close the archive file
1979
                if ('tar' === $p_tar_mode) {
1980
                    fclose($v_tar);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1980
                    fclose(/** @scrutinizer ignore-type */ $v_tar);
Loading history...
1981
                } else {
1982
                    gzclose($v_tar);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1982
                    gzclose(/** @scrutinizer ignore-type */ $v_tar);
Loading history...
1983
                }
1984
1985
                // ----- Return
1986
                TrFctEnd(__FILE__, __LINE__, $v_result);
1987
1988
                return $v_result;
1989
            }
1990
1991
            // ----- Look for empty blocks to skip
1992
            if ('' == $v_header['filename']) {
1993
                TrFctMessage(__FILE__, __LINE__, 2, 'Empty block found. End of archive?');
1994
                continue;
1995
            }
1996
1997
            TrFctMessage(__FILE__, __LINE__, 2, "Found file '" . $v_header['filename'] . "', size '" . $v_header['size'] . "'");
1998
1999
            // ----- Look for partial extract
2000
            if ((!$v_extract_all) && is_array($p_file_list)) {
2001
                TrFctMessage(__FILE__, __LINE__, 2, 'Look if the file ' . $v_header['filename'] . ' need to be extracted');
2002
2003
                // ----- By default no unzip if the file is not found
2004
                $v_extract_file = false;
2005
2006
                // ----- Look into the file list
2007
                for ($i = 0, $iMax = count($p_file_list); $i < $iMax; ++$i) {
2008
                    TrFctMessage(__FILE__, __LINE__, 2, 'Compare archived file ' . $v_header['filename'] . " from asked list file '" . $p_file_list[$i] . "'");
2009
2010
                    // ----- Look if it is a directory
2011
                    if ('/' === mb_substr($p_file_list[$i], -1)) {
2012
                        TrFctMessage(__FILE__, __LINE__, 3, 'Compare file ' . $v_header['filename'] . " with directory '$p_file_list[$i]'");
2013
2014
                        // ----- Look if the directory is in the filename path
2015
                        if ((mb_strlen($v_header['filename']) > mb_strlen($p_file_list[$i]))
2016
                            && (0 === mb_strpos($v_header['filename'], $p_file_list[$i]))) {
2017
                            // ----- The file is in the directory, so extract it
2018
                            TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . " is in directory '$p_file_list[$i]' : extract it");
2019
                            $v_extract_file = true;
2020
2021
                            // ----- End of loop
2022
                            break;
2023
                        }
2024
                    } // ----- It is a file, so compare the file names
2025
                    else {
2026
                        if ($p_file_list[$i] == $v_header['filename']) {
2027
                            // ----- File found
2028
                            TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' should be extracted');
2029
                            $v_extract_file = true;
2030
2031
                            // ----- End of loop
2032
                            break;
2033
                        }
2034
                    }
2035
                }
2036
2037
                // ----- Trace
2038
                if (!$v_extract_file) {
2039
                    TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' should not be extracted');
2040
                }
2041
            } else {
2042
                // ----- All files need to be extracted
2043
                $v_extract_file = true;
2044
            }
2045
2046
            // ----- Look if this file need to be extracted
2047
            if ($v_extract_file && (!$v_listing)) {
2048
                // ----- Look for path to remove
2049
                if (('' != $p_remove_path) && (0 === mb_strpos($v_header['filename'], $p_remove_path))) {
2050
                    TrFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file " . $v_header['filename'] . '');
2051
                    // ----- Remove the path
2052
                    $v_header['filename'] = mb_substr($v_header['filename'], $p_remove_path_size);
2053
                    TrFctMessage(__FILE__, __LINE__, 3, 'Reslting file is ' . $v_header['filename'] . '');
2054
                }
2055
2056
                // ----- Add the path to the file
2057
                if (('./' !== $p_path) && ('/' !== $p_path)) {
2058
                    // ----- Look for the path end '/'
2059
                    while ('/' === mb_substr($p_path, -1)) {
2060
                        TrFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
2061
                        $p_path = mb_substr($p_path, 0, -1);
2062
                        TrFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
2063
                    }
2064
2065
                    // ----- Add the path
2066
                    if (0 === mb_strpos($v_header['filename'], '/')) {
2067
                        $v_header['filename'] = $p_path . $v_header['filename'];
2068
                    } else {
2069
                        $v_header['filename'] = $p_path . '/' . $v_header['filename'];
2070
                    }
2071
                }
2072
2073
                // ----- Trace
2074
                TrFctMessage(__FILE__, __LINE__, 2, 'Extracting file (with path) ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
2075
2076
                // ----- Check that the file does not exists
2077
                if (file_exists($v_header['filename'])) {
2078
                    TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' already exists');
2079
2080
                    // ----- Look if file is a directory
2081
                    if (is_dir($v_header['filename'])) {
2082
                        TrFctMessage(__FILE__, __LINE__, 2, 'Existing file ' . $v_header['filename'] . ' is a directory');
2083
2084
                        // ----- Change the file status
2085
                        $v_header['status'] = 'already_a_directory';
2086
2087
                        // ----- Skip the extract
2088
                        $v_extraction_stopped = 1;
2089
                        $v_extract_file       = 0;
2090
                    } // ----- Look if file is write protected
2091
                    else {
2092
                        if (!is_writable($v_header['filename'])) {
2093
                            TrFctMessage(__FILE__, __LINE__, 2, 'Existing file ' . $v_header['filename'] . ' is write protected');
2094
2095
                            // ----- Change the file status
2096
                            $v_header['status'] = 'write_protected';
2097
2098
                            // ----- Skip the extract
2099
                            $v_extraction_stopped = 1;
2100
                            $v_extract_file       = 0;
2101
                        }
2102
                    }
2103
                    // ----- Look if the extracted file is older
2104
                    /*else if (filemtime($v_header['filename']) > $v_header['mtime']) {
2105
            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']).")");
2106
2107
            // ----- Change the file status
2108
            $v_header['status'] = "newer_exist";
2109
2110
            // ----- Skip the extract
2111
            $v_extraction_stopped = 1;
2112
            $v_extract_file = 0;
2113
          }*/
2114
                } // ----- Check the directory availability and create it if necessary
2115
                else {
2116
                    if ('5' == $v_header['typeflag']) {
2117
                        $v_dir_to_check = $v_header['filename'];
2118
                    } else {
2119
                        if (false === mb_strpos($v_header['filename'], '/')) {
2120
                            $v_dir_to_check = '';
2121
                        } else {
2122
                            $v_dir_to_check = dirname($v_header['filename']);
2123
                        }
2124
                    }
2125
2126
                    if (1 != ($v_result = PclTarHandlerDirCheck($v_dir_to_check))) {
2127
                        TrFctMessage(__FILE__, __LINE__, 2, 'Unable to create path for ' . $v_header['filename'] . '');
2128
2129
                        // ----- Change the file status
2130
                        $v_header['status'] = 'path_creation_fail';
2131
2132
                        // ----- Skip the extract
2133
                        $v_extraction_stopped = 1;
2134
                        $v_extract_file       = 0;
2135
                    }
2136
                }
2137
2138
                // ----- Do the extraction
2139
                if ($v_extract_file && ('5' != $v_header['typeflag'])) {
2140
                    // ----- Open the destination file in write mode
2141
                    if (0 == ($v_dest_file = @fopen($v_header['filename'], 'wb'))) {
2142
                        TrFctMessage(__FILE__, __LINE__, 2, 'Error while opening ' . $v_header['filename'] . ' in write binary mode');
2143
2144
                        // ----- Change the file status
2145
                        $v_header['status'] = 'write_error';
2146
2147
                        // ----- Jump to next file
2148
                        TrFctMessage(__FILE__, __LINE__, 2, 'Jump to next file');
2149
                        if ('tar' === $p_tar_mode) {
2150
                            fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
0 ignored issues
show
Bug introduced by
ftell($v_tar) + ceil($v_...er['size'] / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of fseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2150
                            fseek($v_tar, /** @scrutinizer ignore-type */ ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of ftell() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2150
                            fseek($v_tar, ftell(/** @scrutinizer ignore-type */ $v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fseek() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2150
                            fseek(/** @scrutinizer ignore-type */ $v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
2151
                        } else {
2152
                            gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
0 ignored issues
show
Bug introduced by
gztell($v_tar) + ceil($v...er['size'] / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of gzseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2152
                            gzseek($v_tar, /** @scrutinizer ignore-type */ gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gztell() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2152
                            gzseek($v_tar, gztell(/** @scrutinizer ignore-type */ $v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzseek() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2152
                            gzseek(/** @scrutinizer ignore-type */ $v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
2153
                        }
2154
                    } else {
2155
                        TrFctMessage(__FILE__, __LINE__, 2, 'Start extraction of ' . $v_header['filename'] . '');
2156
2157
                        // ----- Read data
2158
                        $n = floor($v_header['size'] / 512);
2159
                        for ($i = 0; $i < $n; ++$i) {
2160
                            TrFctMessage(__FILE__, __LINE__, 3, 'Read complete 512 bytes block number ' . ($i + 1));
2161
                            if ('tar' === $p_tar_mode) {
2162
                                $v_content = fread($v_tar, 512);
2163
                            } else {
2164
                                $v_content = gzread($v_tar, 512);
2165
                            }
2166
                            fwrite($v_dest_file, $v_content, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_dest_file can also be of type false; however, parameter $stream of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2166
                            fwrite(/** @scrutinizer ignore-type */ $v_dest_file, $v_content, 512);
Loading history...
2167
                        }
2168
                        if (0 != ($v_header['size'] % 512)) {
2169
                            TrFctMessage(__FILE__, __LINE__, 3, 'Read last ' . ($v_header['size'] % 512) . ' bytes in a 512 block');
2170
                            if ('tar' === $p_tar_mode) {
2171
                                $v_content = fread($v_tar, 512);
2172
                            } else {
2173
                                $v_content = gzread($v_tar, 512);
2174
                            }
2175
                            fwrite($v_dest_file, $v_content, $v_header['size'] % 512);
2176
                        }
2177
2178
                        // ----- Close the destination file
2179
                        fclose($v_dest_file);
2180
2181
                        // ----- Change the file mode, mtime
2182
                        touch($v_header['filename'], $v_header['mtime']);
2183
                        //chmod($v_header['filename'], decoct($v_header['mode']));
2184
                    }
2185
2186
                    // ----- Check the file size
2187
                    clearstatcache();
2188
                    if (filesize($v_header['filename']) != $v_header['size']) {
2189
                        // ----- Close the archive file
2190
                        if ('tar' === $p_tar_mode) {
2191
                            fclose($v_tar);
2192
                        } else {
2193
                            gzclose($v_tar);
2194
                        }
2195
2196
                        // ----- Error log
2197
                        PclErrorLog(-7, 'Extracted file ' . $v_header['filename'] . " does not have the correct file size '" . filesize($v_filename) . "' ('" . $v_header['size'] . "' expected). Archive may be corrupted.");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $v_filename seems to be never defined.
Loading history...
2198
2199
                        // ----- Return
2200
                        TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2201
2202
                        return PclErrorCode();
2203
                    }
2204
2205
                    // ----- Trace
2206
                    TrFctMessage(__FILE__, __LINE__, 2, 'Extraction done');
2207
                } else {
2208
                    TrFctMessage(__FILE__, __LINE__, 2, 'Extraction of file ' . $v_header['filename'] . ' skipped.');
2209
2210
                    // ----- Jump to next file
2211
                    TrFctMessage(__FILE__, __LINE__, 2, 'Jump to next file');
2212
                    if ('tar' === $p_tar_mode) {
2213
                        fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2214
                    } else {
2215
                        gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2216
                    }
2217
                }
2218
            } // ----- Look for file that is not to be unzipped
2219
            else {
2220
                // ----- Trace
2221
                TrFctMessage(__FILE__, __LINE__, 2, 'Jump file ' . $v_header['filename'] . '');
2222
                TrFctMessage(__FILE__, __LINE__, 4, 'Position avant jump [' . ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) . ']');
2223
2224
                // ----- Jump to next file
2225
                if ('tar' === $p_tar_mode) {
2226
                    fseek($v_tar, ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) + (ceil($v_header['size'] / 512) * 512));
2227
                } else {
2228
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2229
                }
2230
2231
                TrFctMessage(__FILE__, __LINE__, 4, 'Position après jump [' . ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) . ']');
2232
            }
2233
2234
            if ('tar' === $p_tar_mode) {
2235
                $v_end_of_file = feof($v_tar);
2236
            } else {
2237
                $v_end_of_file = gzeof($v_tar);
2238
            }
2239
2240
            // ----- File name and properties are logged if listing mode or file is extracted
2241
            if ($v_listing || $v_extract_file || $v_extraction_stopped) {
2242
                TrFctMessage(__FILE__, __LINE__, 2, 'Memorize info about file ' . $v_header['filename'] . '');
2243
2244
                // ----- Log extracted files
2245
                if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
2246
                    $v_file_dir = '';
2247
                }
2248
                if (('' === $v_file_dir) && (0 === mb_strpos($v_header['filename'], '/'))) {
2249
                    $v_file_dir = '/';
0 ignored issues
show
Unused Code introduced by
The assignment to $v_file_dir is dead and can be removed.
Loading history...
2250
                }
2251
2252
                // ----- Add the array describing the file into the list
2253
                $p_list_detail[$v_nb] = $v_header;
2254
2255
                // ----- Increment
2256
                ++$v_nb;
2257
            }
2258
        }
2259
2260
        // ----- Close the tarfile
2261
        if ('tar' === $p_tar_mode) {
2262
            fclose($v_tar);
2263
        } else {
2264
            gzclose($v_tar);
2265
        }
2266
2267
        // ----- Return
2268
        TrFctEnd(__FILE__, __LINE__, $v_result);
2269
2270
        return $v_result;
2271
    }
2272
2273
    // --------------------------------------------------------------------------------
2274
2275
    // --------------------------------------------------------------------------------
2276
    // Function : PclTarHandleExtractByIndexList()
2277
    // Description :
2278
    //   Extract the files which are at the indexes specified. If the 'file' at the
2279
    //   index is a directory, the directory only is created, not all the files stored
2280
    //   for that directory.
2281
    // Parameters :
2282
    //   $p_index_string : String of indexes of files to extract. The form of the
2283
    //                     string is "0,4-6,8-12" with only numbers and '-' for
2284
    //                     for range, and ',' to separate ranges. No spaces or ';'
2285
    //                     are allowed.
2286
    // Return Values :
2287
    // --------------------------------------------------------------------------------
2288
    /**
2289
     * @param $p_tarname
2290
     * @param $p_index_string
2291
     * @param $p_list_detail
2292
     * @param $p_path
2293
     * @param $p_remove_path
2294
     * @param $p_tar_mode
2295
     *
2296
     * @return int
2297
     */
2298
    function PclTarHandleExtractByIndexList(
2299
        $p_tarname,
2300
        $p_index_string,
2301
        &$p_list_detail,
2302
        $p_path,
2303
        $p_remove_path,
2304
        $p_tar_mode
2305
    ) {
2306
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtractByIndexList', "archive='$p_tarname', index_string='$p_index_string', list, path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2307
        $v_result = 1;
2308
        $v_nb     = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $v_nb is dead and can be removed.
Loading history...
2309
2310
        // ----- TBC : I should check the string by a regexp
2311
2312
        // ----- Check the path
2313
        if (('' === $p_path)
2314
            || ((0 !== mb_strpos($p_path, '/')) && (0 !== mb_strpos($p_path, '../'))
2315
                && (0 !== mb_strpos($p_path, './')))) {
2316
            $p_path = './' . $p_path;
2317
        }
2318
2319
        // ----- Look for path to remove format (should end by /)
2320
        if (('' != $p_remove_path) && ('/' !== mb_substr($p_remove_path, -1))) {
2321
            $p_remove_path .= '/';
2322
        }
2323
        $p_remove_path_size = mb_strlen($p_remove_path);
0 ignored issues
show
Unused Code introduced by
The assignment to $p_remove_path_size is dead and can be removed.
Loading history...
2324
2325
        // ----- Open the tar file
2326
        if ('tar' === $p_tar_mode) {
2327
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in binary read mode');
2328
            $v_tar = @fopen($p_tarname, 'rb');
2329
        } else {
2330
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in gzip binary read mode');
2331
            $v_tar = @gzopen($p_tarname, 'rb');
2332
        }
2333
2334
        // ----- Check that the archive is open
2335
        if (0 == $v_tar) {
2336
            // ----- Error log
2337
            PclErrorLog(-2, "Unable to open archive '$p_tarname' in binary read mode");
2338
2339
            // ----- Return
2340
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2341
2342
            return PclErrorCode();
2343
        }
2344
2345
        // ----- Manipulate the index list
2346
        $v_list = explode(',', $p_index_string);
2347
        sort($v_list);
2348
2349
        // ----- Loop on the index list
2350
        $v_index = 0;
2351
        for ($i = 0; ($i < count($v_list)) && $v_result; ++$i) {
2352
            TrFctMessage(__FILE__, __LINE__, 3, "Looking for index part '$v_list[$i]'");
2353
2354
            // ----- Extract range
2355
            $v_index_list      = explode('-', $v_list[$i]);
2356
            $v_size_index_list = count($v_index_list);
2357
            if (1 == $v_size_index_list) {
2358
                TrFctMessage(__FILE__, __LINE__, 3, "Only one index '$v_index_list[0]'");
2359
2360
                // ----- Do the extraction
2361
                $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);
2362
            } else {
2363
                if (2 == $v_size_index_list) {
2364
                    TrFctMessage(__FILE__, __LINE__, 3, "Two indexes '$v_index_list[0]' and '$v_index_list[1]'");
2365
2366
                    // ----- Do the extraction
2367
                    $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);
2368
                }
2369
            }
2370
        }
2371
2372
        // ----- Close the tarfile
2373
        if ('tar' === $p_tar_mode) {
2374
            fclose($v_tar);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2374
            fclose(/** @scrutinizer ignore-type */ $v_tar);
Loading history...
2375
        } else {
2376
            gzclose($v_tar);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2376
            gzclose(/** @scrutinizer ignore-type */ $v_tar);
Loading history...
2377
        }
2378
2379
        // ----- Return
2380
        TrFctEnd(__FILE__, __LINE__, $v_result);
2381
2382
        return $v_result;
2383
    }
2384
2385
    // --------------------------------------------------------------------------------
2386
2387
    // --------------------------------------------------------------------------------
2388
    // Function : PclTarHandleExtractByIndex()
2389
    // Description :
2390
    // Parameters :
2391
    // Return Values :
2392
    // --------------------------------------------------------------------------------
2393
    /**
2394
     * @param $p_tar
2395
     * @param $p_index_current
2396
     * @param $p_index_start
2397
     * @param $p_index_stop
2398
     * @param $p_list_detail
2399
     * @param $p_path
2400
     * @param $p_remove_path
2401
     * @param $p_tar_mode
2402
     *
2403
     * @return int
2404
     */
2405
    function PclTarHandleExtractByIndex(
2406
        $p_tar,
2407
        &$p_index_current,
2408
        $p_index_start,
2409
        $p_index_stop,
2410
        &$p_list_detail,
2411
        $p_path,
2412
        $p_remove_path,
2413
        $p_tar_mode
2414
    ) {
2415
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtractByIndex', "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");
2416
        $v_result = 1;
2417
        $v_nb     = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $v_nb is dead and can be removed.
Loading history...
2418
2419
        // TBC : I should replace all $v_tar by $p_tar in this function ....
2420
        $v_tar = $p_tar;
2421
2422
        // ----- Look the number of elements already in $p_list_detail
2423
        $v_nb = count($p_list_detail);
2424
2425
        // ----- Read the blocks
2426
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof($v_tar) : gzeof($v_tar)))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $v_end_of_file is dead and can be removed.
Loading history...
2427
            TrFctMessage(__FILE__, __LINE__, 3, 'Looking for next file ...');
2428
            TrFctMessage(__FILE__, __LINE__, 3, "Index current=$p_index_current, range=[$p_index_start, $p_index_stop])");
2429
2430
            if ($p_index_current > $p_index_stop) {
2431
                TrFctMessage(__FILE__, __LINE__, 2, 'Stop extraction, past stop index');
2432
                break;
2433
            }
2434
2435
            // ----- Clear cache of file infos
2436
            clearstatcache();
2437
2438
            // ----- Reset extract tag
2439
            $v_extract_file       = false;
2440
            $v_extraction_stopped = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $v_extraction_stopped is dead and can be removed.
Loading history...
2441
2442
            // ----- Read the 512 bytes header
2443
            if ('tar' === $p_tar_mode) {
2444
                $v_binary_data = fread($v_tar, 512);
2445
            } else {
2446
                $v_binary_data = gzread($v_tar, 512);
2447
            }
2448
2449
            // ----- Read the header properties
2450
            if (1 != ($v_result = PclTarHandleReadHeader($v_binary_data, $v_header))) {
2451
                // ----- Return
2452
                TrFctEnd(__FILE__, __LINE__, $v_result);
2453
2454
                return $v_result;
2455
            }
2456
2457
            // ----- Look for empty blocks to skip
2458
            if ('' == $v_header['filename']) {
2459
                TrFctMessage(__FILE__, __LINE__, 2, 'Empty block found. End of archive?');
2460
                continue;
2461
            }
2462
2463
            TrFctMessage(__FILE__, __LINE__, 2, 'Found file ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
2464
2465
            // ----- Look if file is in the range to be extracted
2466
            if (($p_index_current >= $p_index_start) && ($p_index_current <= $p_index_stop)) {
2467
                TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' is in the range to be extracted');
2468
                $v_extract_file = true;
2469
            } else {
2470
                TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' is out of the range');
2471
                $v_extract_file = false;
2472
            }
2473
2474
            // ----- Look if this file need to be extracted
2475
            if ($v_extract_file) {
2476
                if (1 != ($v_result = PclTarHandleExtractFile($v_tar, $v_header, $p_path, $p_remove_path, $p_tar_mode))) {
2477
                    // ----- Return
2478
                    TrFctEnd(__FILE__, __LINE__, $v_result);
2479
2480
                    return $v_result;
2481
                }
2482
            } // ----- Look for file that is not to be extracted
2483
            else {
2484
                // ----- Trace
2485
                TrFctMessage(__FILE__, __LINE__, 2, 'Jump file ' . $v_header['filename'] . '');
2486
                TrFctMessage(__FILE__, __LINE__, 4, 'Position avant jump [' . ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) . ']');
2487
2488
                // ----- Jump to next file
2489
                if ('tar' === $p_tar_mode) {
2490
                    fseek($v_tar, ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) + (ceil($v_header['size'] / 512) * 512));
0 ignored issues
show
Bug introduced by
'tar' === $p_tar_mode ? ...er['size'] / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of fseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2490
                    fseek($v_tar, /** @scrutinizer ignore-type */ ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) + (ceil($v_header['size'] / 512) * 512));
Loading history...
2491
                } else {
2492
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
0 ignored issues
show
Bug introduced by
gztell($v_tar) + ceil($v...er['size'] / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of gzseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2492
                    gzseek($v_tar, /** @scrutinizer ignore-type */ gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
2493
                }
2494
2495
                TrFctMessage(__FILE__, __LINE__, 4, 'Position après jump [' . ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) . ']');
2496
            }
2497
2498
            if ('tar' === $p_tar_mode) {
2499
                $v_end_of_file = feof($v_tar);
2500
            } else {
2501
                $v_end_of_file = gzeof($v_tar);
2502
            }
2503
2504
            // ----- File name and properties are logged if listing mode or file is extracted
2505
            if ($v_extract_file) {
2506
                TrFctMessage(__FILE__, __LINE__, 2, 'Memorize info about file ' . $v_header['filename'] . '');
2507
2508
                // ----- Log extracted files
2509
                if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
2510
                    $v_file_dir = '';
2511
                }
2512
                if (('' === $v_file_dir) && (0 === mb_strpos($v_header['filename'], '/'))) {
2513
                    $v_file_dir = '/';
0 ignored issues
show
Unused Code introduced by
The assignment to $v_file_dir is dead and can be removed.
Loading history...
2514
                }
2515
2516
                // ----- Add the array describing the file into the list
2517
                $p_list_detail[$v_nb] = $v_header;
2518
2519
                // ----- Increment
2520
                ++$v_nb;
2521
            }
2522
2523
            // ----- Increment the current file index
2524
            ++$p_index_current;
2525
        }
2526
2527
        // ----- Return
2528
        TrFctEnd(__FILE__, __LINE__, $v_result);
2529
2530
        return $v_result;
2531
    }
2532
2533
    // --------------------------------------------------------------------------------
2534
2535
    // --------------------------------------------------------------------------------
2536
    // Function : PclTarHandleExtractFile()
2537
    // Description :
2538
    // Parameters :
2539
    // Return Values :
2540
    // --------------------------------------------------------------------------------
2541
    /**
2542
     * @param $p_tar
2543
     * @param $v_header
2544
     * @param $p_path
2545
     * @param $p_remove_path
2546
     * @param $p_tar_mode
2547
     *
2548
     * @return int
2549
     */
2550
    function PclTarHandleExtractFile($p_tar, &$v_header, $p_path, $p_remove_path, $p_tar_mode)
2551
    {
2552
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtractFile', "archive_descr='$p_tar', path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2553
        $v_result = 1;
2554
2555
        // TBC : I should replace all $v_tar by $p_tar in this function ....
2556
        $v_tar          = $p_tar;
2557
        $v_extract_file = 1;
2558
2559
        $p_remove_path_size = mb_strlen($p_remove_path);
2560
2561
        // ----- Look for path to remove
2562
        if (('' != $p_remove_path) && (0 === mb_strpos($v_header['filename'], $p_remove_path))) {
2563
            TrFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file " . $v_header['filename'] . '');
2564
            // ----- Remove the path
2565
            $v_header['filename'] = mb_substr($v_header['filename'], $p_remove_path_size);
2566
            TrFctMessage(__FILE__, __LINE__, 3, 'Resulting file is ' . $v_header['filename'] . '');
2567
        }
2568
2569
        // ----- Add the path to the file
2570
        if (('./' !== $p_path) && ('/' !== $p_path)) {
2571
            // ----- Look for the path end '/'
2572
            while ('/' === mb_substr($p_path, -1)) {
2573
                TrFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
2574
                $p_path = mb_substr($p_path, 0, -1);
2575
                TrFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
2576
            }
2577
2578
            // ----- Add the path
2579
            if (0 === mb_strpos($v_header['filename'], '/')) {
2580
                $v_header['filename'] = $p_path . $v_header['filename'];
2581
            } else {
2582
                $v_header['filename'] = $p_path . '/' . $v_header['filename'];
2583
            }
2584
        }
2585
2586
        // ----- Trace
2587
        TrFctMessage(__FILE__, __LINE__, 2, 'Extracting file (with path) ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
2588
2589
        // ----- Check that the file does not exists
2590
        if (file_exists($v_header['filename'])) {
2591
            TrFctMessage(__FILE__, __LINE__, 2, 'File ' . $v_header['filename'] . ' already exists');
2592
2593
            // ----- Look if file is a directory
2594
            if (is_dir($v_header['filename'])) {
2595
                TrFctMessage(__FILE__, __LINE__, 2, 'Existing file ' . $v_header['filename'] . ' is a directory');
2596
2597
                // ----- Change the file status
2598
                $v_header['status'] = 'already_a_directory';
2599
2600
                // ----- Skip the extract
2601
                $v_extraction_stopped = 1;
0 ignored issues
show
Unused Code introduced by
The assignment to $v_extraction_stopped is dead and can be removed.
Loading history...
2602
                $v_extract_file       = 0;
2603
            } // ----- Look if file is write protected
2604
            else {
2605
                if (!is_writable($v_header['filename'])) {
2606
                    TrFctMessage(__FILE__, __LINE__, 2, 'Existing file ' . $v_header['filename'] . ' is write protected');
2607
2608
                    // ----- Change the file status
2609
                    $v_header['status'] = 'write_protected';
2610
2611
                    // ----- Skip the extract
2612
                    $v_extraction_stopped = 1;
2613
                    $v_extract_file       = 0;
2614
                } // ----- Look if the extracted file is older
2615
                else {
2616
                    if (filemtime($v_header['filename']) > $v_header['mtime']) {
2617
                        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']) . ')');
2618
2619
                        // ----- Change the file status
2620
                        $v_header['status'] = 'newer_exist';
2621
2622
                        // ----- Skip the extract
2623
                        $v_extraction_stopped = 1;
2624
                        $v_extract_file       = 0;
2625
                    }
2626
                }
2627
            }
2628
        } // ----- Check the directory availability and create it if necessary
2629
        else {
2630
            if ('5' == $v_header['typeflag']) {
2631
                $v_dir_to_check = $v_header['filename'];
2632
            } else {
2633
                if (false === mb_strpos($v_header['filename'], '/')) {
2634
                    $v_dir_to_check = '';
2635
                } else {
2636
                    $v_dir_to_check = dirname($v_header['filename']);
2637
                }
2638
            }
2639
2640
            if (1 != ($v_result = PclTarHandlerDirCheck($v_dir_to_check))) {
2641
                TrFctMessage(__FILE__, __LINE__, 2, 'Unable to create path for ' . $v_header['filename'] . '');
2642
2643
                // ----- Change the file status
2644
                $v_header['status'] = 'path_creation_fail';
2645
2646
                // ----- Skip the extract
2647
                $v_extraction_stopped = 1;
2648
                $v_extract_file       = 0;
2649
            }
2650
        }
2651
2652
        // ----- Do the real bytes extraction (if not a directory)
2653
        if ($v_extract_file && ('5' != $v_header['typeflag'])) {
2654
            // ----- Open the destination file in write mode
2655
            if (0 == ($v_dest_file = @fopen($v_header['filename'], 'wb'))) {
2656
                TrFctMessage(__FILE__, __LINE__, 2, 'Error while opening ' . $v_header['filename'] . ' in write binary mode');
2657
2658
                // ----- Change the file status
2659
                $v_header['status'] = 'write_error';
2660
2661
                // ----- Jump to next file
2662
                TrFctMessage(__FILE__, __LINE__, 2, 'Jump to next file');
2663
                if ('tar' === $p_tar_mode) {
2664
                    fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
0 ignored issues
show
Bug introduced by
ftell($v_tar) + ceil($v_...er['size'] / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of fseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2664
                    fseek($v_tar, /** @scrutinizer ignore-type */ ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
2665
                } else {
2666
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
0 ignored issues
show
Bug introduced by
gztell($v_tar) + ceil($v...er['size'] / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of gzseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2666
                    gzseek($v_tar, /** @scrutinizer ignore-type */ gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
2667
                }
2668
            } else {
2669
                TrFctMessage(__FILE__, __LINE__, 2, 'Start extraction of ' . $v_header['filename'] . '');
2670
2671
                // ----- Read data
2672
                $n = floor($v_header['size'] / 512);
2673
                for ($i = 0; $i < $n; ++$i) {
2674
                    TrFctMessage(__FILE__, __LINE__, 3, 'Read complete 512 bytes block number ' . ($i + 1));
2675
                    if ('tar' === $p_tar_mode) {
2676
                        $v_content = fread($v_tar, 512);
2677
                    } else {
2678
                        $v_content = gzread($v_tar, 512);
2679
                    }
2680
                    fwrite($v_dest_file, $v_content, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_dest_file can also be of type false; however, parameter $stream of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2680
                    fwrite(/** @scrutinizer ignore-type */ $v_dest_file, $v_content, 512);
Loading history...
2681
                }
2682
                if (0 != ($v_header['size'] % 512)) {
2683
                    TrFctMessage(__FILE__, __LINE__, 3, 'Read last ' . ($v_header['size'] % 512) . ' bytes in a 512 block');
2684
                    if ('tar' === $p_tar_mode) {
2685
                        $v_content = fread($v_tar, 512);
2686
                    } else {
2687
                        $v_content = gzread($v_tar, 512);
2688
                    }
2689
                    fwrite($v_dest_file, $v_content, $v_header['size'] % 512);
2690
                }
2691
2692
                // ----- Close the destination file
2693
                fclose($v_dest_file);
0 ignored issues
show
Bug introduced by
It seems like $v_dest_file can also be of type false; however, parameter $stream of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2693
                fclose(/** @scrutinizer ignore-type */ $v_dest_file);
Loading history...
2694
2695
                // ----- Change the file mode, mtime
2696
                touch($v_header['filename'], $v_header['mtime']);
2697
                //chmod($v_header['filename'], decoct($v_header['mode']));
2698
            }
2699
2700
            // ----- Check the file size
2701
            clearstatcache();
2702
            if (filesize($v_header['filename']) != $v_header['size']) {
2703
                // ----- Error log
2704
                PclErrorLog(-7, 'Extracted file ' . $v_header['filename'] . " does not have the correct file size '" . filesize($v_filename) . "' ('" . $v_header['size'] . "' expected). Archive may be corrupted.");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $v_filename seems to be never defined.
Loading history...
2705
2706
                // ----- Return
2707
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2708
2709
                return PclErrorCode();
2710
            }
2711
2712
            // ----- Trace
2713
            TrFctMessage(__FILE__, __LINE__, 2, 'Extraction done');
2714
        } else {
2715
            TrFctMessage(__FILE__, __LINE__, 2, 'Extraction of file ' . $v_header['filename'] . ' skipped.');
2716
2717
            // ----- Jump to next file
2718
            TrFctMessage(__FILE__, __LINE__, 2, 'Jump to next file');
2719
            if ('tar' === $p_tar_mode) {
2720
                fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2721
            } else {
2722
                gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
2723
            }
2724
        }
2725
2726
        // ----- Return
2727
        TrFctEnd(__FILE__, __LINE__, $v_result);
2728
2729
        return $v_result;
2730
    }
2731
2732
    // --------------------------------------------------------------------------------
2733
2734
    // --------------------------------------------------------------------------------
2735
    // Function : PclTarHandleDelete()
2736
    // Description :
2737
    // Parameters :
2738
    // Return Values :
2739
    // --------------------------------------------------------------------------------
2740
    /**
2741
     * @param $p_tarname
2742
     * @param $p_file_list
2743
     * @param $p_list_detail
2744
     * @param $p_tar_mode
2745
     *
2746
     * @return int
2747
     */
2748
    function PclTarHandleDelete($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode)
2749
    {
2750
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleDelete', "archive='$p_tarname', list, tar_mode=$p_tar_mode");
2751
        $v_result = 1;
2752
        $v_nb     = 0;
2753
2754
        // ----- Look for regular tar file
2755
        if ('tar' === $p_tar_mode) {
2756
            // ----- Open file
2757
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in binary read mode');
2758
            if (0 == ($v_tar = @fopen($p_tarname, 'rb'))) {
2759
                // ----- Error log
2760
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2761
2762
                // ----- Return
2763
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2764
2765
                return PclErrorCode();
2766
            }
2767
2768
            // ----- Open a temporary file in write mode
2769
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
2770
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
2771
            if (0 == ($v_temp_tar = @fopen($v_temp_tarname, 'wb'))) {
2772
                // ----- Close tar file
2773
                fclose($v_tar);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2773
                fclose(/** @scrutinizer ignore-type */ $v_tar);
Loading history...
2774
2775
                // ----- Error log
2776
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2777
2778
                // ----- Return
2779
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2780
2781
                return PclErrorCode();
2782
            }
2783
        } // ----- Look for compressed tar file
2784
        else {
2785
            // ----- Open the file in read mode
2786
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in gzip binary read mode');
2787
            if (0 == ($v_tar = @gzopen($p_tarname, 'rb'))) {
2788
                // ----- Error log
2789
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2790
2791
                // ----- Return
2792
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2793
2794
                return PclErrorCode();
2795
            }
2796
2797
            // ----- Open a temporary file in write mode
2798
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
2799
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
2800
            if (0 == ($v_temp_tar = @gzopen($v_temp_tarname, 'wb'))) {
2801
                // ----- Close tar file
2802
                gzclose($v_tar);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2802
                gzclose(/** @scrutinizer ignore-type */ $v_tar);
Loading history...
2803
2804
                // ----- Error log
2805
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2806
2807
                // ----- Return
2808
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2809
2810
                return PclErrorCode();
2811
            }
2812
        }
2813
2814
        // ----- Read the blocks
2815
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof($v_tar) : gzeof($v_tar)))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $v_end_of_file is dead and can be removed.
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of feof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2815
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof(/** @scrutinizer ignore-type */ $v_tar) : gzeof($v_tar)))) {
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzeof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2815
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof($v_tar) : gzeof(/** @scrutinizer ignore-type */ $v_tar)))) {
Loading history...
2816
            TrFctMessage(__FILE__, __LINE__, 3, 'Looking for next header ...');
2817
2818
            // ----- Clear cache of file infos
2819
            clearstatcache();
2820
2821
            // ----- Reset delete tag
2822
            $v_delete_file = false;
2823
2824
            // ----- Read the first 512 block header
2825
            if ('tar' === $p_tar_mode) {
2826
                $v_binary_data = fread($v_tar, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2826
                $v_binary_data = fread(/** @scrutinizer ignore-type */ $v_tar, 512);
Loading history...
2827
            } else {
2828
                $v_binary_data = gzread($v_tar, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2828
                $v_binary_data = gzread(/** @scrutinizer ignore-type */ $v_tar, 512);
Loading history...
2829
            }
2830
2831
            // ----- Read the header properties
2832
            if (1 != ($v_result = PclTarHandleReadHeader($v_binary_data, $v_header))) {
2833
                // ----- Close the archive file
2834
                if ('tar' === $p_tar_mode) {
2835
                    fclose($v_tar);
2836
                    fclose($v_temp_tar);
2837
                } else {
2838
                    gzclose($v_tar);
2839
                    gzclose($v_temp_tar);
2840
                }
2841
                @unlink($v_temp_tarname);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

2841
                /** @scrutinizer ignore-unhandled */ @unlink($v_temp_tarname);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2842
2843
                // ----- Return
2844
                TrFctEnd(__FILE__, __LINE__, $v_result);
2845
2846
                return $v_result;
2847
            }
2848
2849
            // ----- Look for empty blocks to skip
2850
            if ('' == $v_header['filename']) {
2851
                TrFctMessage(__FILE__, __LINE__, 2, 'Empty block found. End of archive?');
2852
                continue;
2853
            }
2854
2855
            TrFctMessage(__FILE__, __LINE__, 2, 'Found file ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
2856
2857
            // ----- Look for filenames to delete
2858
            for ($i = 0, $v_delete_file = false; ($i < count($p_file_list)) && (!$v_delete_file); ++$i) {
2859
                // ----- Compare the file names
2860
                //        if ($p_file_list[$i] == $v_header['filename'])
2861
                if (($v_len = strcmp($p_file_list[$i], $v_header['filename'])) <= 0) {
2862
                    if (0 == $v_len) {
2863
                        TrFctMessage(__FILE__, __LINE__, 3, 'Found that ' . $v_header['filename'] . ' need to be deleted');
2864
                        $v_delete_file = true;
2865
                    } else {
2866
                        TrFctMessage(__FILE__, __LINE__, 3, 'Look if ' . $v_header['filename'] . " is a file in $p_file_list[$i]");
2867
                        if ('/' === mb_substr($v_header['filename'], mb_strlen($p_file_list[$i]), 1)) {
2868
                            TrFctMessage(__FILE__, __LINE__, 3, '' . $v_header['filename'] . " is a file in $p_file_list[$i]");
2869
                            $v_delete_file = true;
2870
                        }
2871
                    }
2872
                }
2873
            }
2874
2875
            // ----- Copy files that do not need to be deleted
2876
            if (!$v_delete_file) {
2877
                TrFctMessage(__FILE__, __LINE__, 2, 'Keep file ' . $v_header['filename'] . '');
2878
2879
                // ----- Write the file header
2880
                if ('tar' === $p_tar_mode) {
2881
                    fwrite($v_temp_tar, $v_binary_data, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_temp_tar can also be of type false; however, parameter $stream of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2881
                    fwrite(/** @scrutinizer ignore-type */ $v_temp_tar, $v_binary_data, 512);
Loading history...
2882
                } else {
2883
                    gzputs($v_temp_tar, $v_binary_data, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_temp_tar can also be of type false; however, parameter $stream of gzputs() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2883
                    gzputs(/** @scrutinizer ignore-type */ $v_temp_tar, $v_binary_data, 512);
Loading history...
2884
                }
2885
2886
                // ----- Write the file data
2887
                $n = ceil($v_header['size'] / 512);
2888
                for ($i = 0; $i < $n; ++$i) {
2889
                    TrFctMessage(__FILE__, __LINE__, 3, 'Read complete 512 bytes block number ' . ($i + 1));
2890
                    if ('tar' === $p_tar_mode) {
2891
                        $v_content = fread($v_tar, 512);
2892
                        fwrite($v_temp_tar, $v_content, 512);
2893
                    } else {
2894
                        $v_content = gzread($v_tar, 512);
2895
                        gzwrite($v_temp_tar, $v_content, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_temp_tar can also be of type false; however, parameter $stream of gzwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2895
                        gzwrite(/** @scrutinizer ignore-type */ $v_temp_tar, $v_content, 512);
Loading history...
2896
                    }
2897
                }
2898
2899
                // ----- File name and properties are logged if listing mode or file is extracted
2900
                TrFctMessage(__FILE__, __LINE__, 2, 'Memorize info about file ' . $v_header['filename'] . '');
2901
2902
                // ----- Add the array describing the file into the list
2903
                $p_list_detail[$v_nb]           = $v_header;
2904
                $p_list_detail[$v_nb]['status'] = 'ok';
2905
2906
                // ----- Increment
2907
                ++$v_nb;
2908
            } // ----- Look for file that is to be deleted
2909
            else {
2910
                // ----- Trace
2911
                TrFctMessage(__FILE__, __LINE__, 2, 'Start deletion of ' . $v_header['filename'] . '');
2912
                TrFctMessage(__FILE__, __LINE__, 4, 'Position avant jump [' . ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) . ']');
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gztell() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2912
                TrFctMessage(__FILE__, __LINE__, 4, 'Position avant jump [' . ('tar' === $p_tar_mode ? ftell($v_tar) : gztell(/** @scrutinizer ignore-type */ $v_tar)) . ']');
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of ftell() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2912
                TrFctMessage(__FILE__, __LINE__, 4, 'Position avant jump [' . ('tar' === $p_tar_mode ? ftell(/** @scrutinizer ignore-type */ $v_tar) : gztell($v_tar)) . ']');
Loading history...
2913
2914
                // ----- Jump to next file
2915
                if ('tar' === $p_tar_mode) {
2916
                    fseek($v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
0 ignored issues
show
Bug introduced by
ftell($v_tar) + ceil($v_...er['size'] / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of fseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2916
                    fseek($v_tar, /** @scrutinizer ignore-type */ ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fseek() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2916
                    fseek(/** @scrutinizer ignore-type */ $v_tar, ftell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
2917
                } else {
2918
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
0 ignored issues
show
Bug introduced by
gztell($v_tar) + ceil($v...er['size'] / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of gzseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2918
                    gzseek($v_tar, /** @scrutinizer ignore-type */ gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzseek() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2918
                    gzseek(/** @scrutinizer ignore-type */ $v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
Loading history...
2919
                }
2920
2921
                TrFctMessage(__FILE__, __LINE__, 4, 'Position après jump [' . ('tar' === $p_tar_mode ? ftell($v_tar) : gztell($v_tar)) . ']');
2922
            }
2923
2924
            // ----- Look for end of file
2925
            if ('tar' === $p_tar_mode) {
2926
                $v_end_of_file = feof($v_tar);
2927
            } else {
2928
                $v_end_of_file = gzeof($v_tar);
2929
            }
2930
        }
2931
2932
        // ----- Write the last empty buffer
2933
        PclTarHandleFooter($v_temp_tar, $p_tar_mode);
2934
2935
        // ----- Close the tarfile
2936
        if ('tar' === $p_tar_mode) {
2937
            fclose($v_tar);
2938
            fclose($v_temp_tar);
2939
        } else {
2940
            gzclose($v_tar);
2941
            gzclose($v_temp_tar);
2942
        }
2943
2944
        // ----- Unlink tar file
2945
        if (!@unlink($p_tarname)) {
2946
            // ----- Error log
2947
            PclErrorLog(-11, "Error while deleting archive name $p_tarname");
2948
        }
2949
2950
        // ----- Rename tar file
2951
        if (!@rename($v_temp_tarname, $p_tarname)) {
2952
            // ----- Error log
2953
            PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
2954
2955
            // ----- Return
2956
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
2957
2958
            return PclErrorCode();
2959
        }
2960
2961
        // ----- Return
2962
        TrFctEnd(__FILE__, __LINE__, $v_result);
2963
2964
        return $v_result;
2965
    }
2966
2967
    // --------------------------------------------------------------------------------
2968
2969
    // --------------------------------------------------------------------------------
2970
    // Function : PclTarHandleUpdate()
2971
    // Description :
2972
    // Parameters :
2973
    // Return Values :
2974
    // --------------------------------------------------------------------------------
2975
    /**
2976
     * @param $p_tarname
2977
     * @param $p_file_list
2978
     * @param $p_list_detail
2979
     * @param $p_tar_mode
2980
     * @param $p_add_dir
2981
     * @param $p_remove_dir
2982
     *
2983
     * @return int
2984
     */
2985
    function PclTarHandleUpdate($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode, $p_add_dir, $p_remove_dir)
2986
    {
2987
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleUpdate', "archive='$p_tarname', list, tar_mode=$p_tar_mode");
2988
        $v_result     = 1;
2989
        $v_nb         = 0;
2990
        $v_found_list = [];
2991
2992
        // ----- Look for regular tar file
2993
        if ('tar' === $p_tar_mode) {
2994
            // ----- Open file
2995
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in binary read mode');
2996
            if (0 == ($v_tar = @fopen($p_tarname, 'rb'))) {
2997
                // ----- Error log
2998
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2999
3000
                // ----- Return
3001
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3002
3003
                return PclErrorCode();
3004
            }
3005
3006
            // ----- Open a temporary file in write mode
3007
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
3008
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
3009
            if (0 == ($v_temp_tar = @fopen($v_temp_tarname, 'wb'))) {
3010
                // ----- Close tar file
3011
                fclose($v_tar);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3011
                fclose(/** @scrutinizer ignore-type */ $v_tar);
Loading history...
3012
3013
                // ----- Error log
3014
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
3015
3016
                // ----- Return
3017
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3018
3019
                return PclErrorCode();
3020
            }
3021
        } // ----- Look for compressed tar file
3022
        else {
3023
            // ----- Open the file in read mode
3024
            TrFctMessage(__FILE__, __LINE__, 3, 'Open file in gzip binary read mode');
3025
            if (0 == ($v_tar = @gzopen($p_tarname, 'rb'))) {
3026
                // ----- Error log
3027
                PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
3028
3029
                // ----- Return
3030
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3031
3032
                return PclErrorCode();
3033
            }
3034
3035
            // ----- Open a temporary file in write mode
3036
            $v_temp_tarname = uniqid('pcltar-', true) . '.tmp';
3037
            TrFctMessage(__FILE__, __LINE__, 2, "Creating temporary archive file $v_temp_tarname");
3038
            if (0 == ($v_temp_tar = @gzopen($v_temp_tarname, 'wb'))) {
3039
                // ----- Close tar file
3040
                gzclose($v_tar);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3040
                gzclose(/** @scrutinizer ignore-type */ $v_tar);
Loading history...
3041
3042
                // ----- Error log
3043
                PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
3044
3045
                // ----- Return
3046
                TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3047
3048
                return PclErrorCode();
3049
            }
3050
        }
3051
3052
        // ----- Prepare the list of files
3053
        for ($i = 0, $iMax = count($p_file_list); $i < $iMax; ++$i) {
3054
            // ----- Reset the found list
3055
            $v_found_list[$i] = 0;
3056
3057
            // ----- Calculate the stored filename
3058
            $v_stored_list[$i] = $p_file_list[$i];
3059
            if ('' != $p_remove_dir) {
3060
                if ('/' !== mb_substr($p_file_list[$i], -1)) {
3061
                    $p_remove_dir .= '/';
3062
                }
3063
3064
                if (0 === mb_strpos($p_file_list[$i], $p_remove_dir)) {
3065
                    $v_stored_list[$i] = mb_substr($p_file_list[$i], mb_strlen($p_remove_dir));
3066
                    TrFctMessage(__FILE__, __LINE__, 3, "Remove path '$p_remove_dir' in file '$p_file_list[$i]' = '$v_stored_list[$i]'");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $v_stored_list does not seem to be defined for all execution paths leading up to this point.
Loading history...
3067
                }
3068
            }
3069
            if ('' != $p_add_dir) {
3070
                if ('/' === mb_substr($p_add_dir, -1)) {
3071
                    $v_stored_list[$i] = $p_add_dir . $v_stored_list[$i];
3072
                } else {
3073
                    $v_stored_list[$i] = $p_add_dir . '/' . $v_stored_list[$i];
3074
                }
3075
                TrFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_file_list[$i]' = '$v_stored_list[$i]'");
3076
            }
3077
            $v_stored_list[$i] = PclTarHandlePathReduction($v_stored_list[$i]);
3078
            TrFctMessage(__FILE__, __LINE__, 3, "After reduction '$v_stored_list[$i]'");
3079
        }
3080
3081
        // ----- Update file cache
3082
        clearstatcache();
3083
3084
        // ----- Read the blocks
3085
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof($v_tar) : gzeof($v_tar)))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $v_end_of_file is dead and can be removed.
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzeof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3085
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof($v_tar) : gzeof(/** @scrutinizer ignore-type */ $v_tar)))) {
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of feof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3085
        while (!($v_end_of_file = ('tar' === $p_tar_mode ? feof(/** @scrutinizer ignore-type */ $v_tar) : gzeof($v_tar)))) {
Loading history...
3086
            TrFctMessage(__FILE__, __LINE__, 3, 'Looking for next header ...');
3087
3088
            // ----- Clear cache of file infos
3089
            clearstatcache();
3090
3091
            // ----- Reset current found filename
3092
            $v_current_filename = '';
3093
3094
            // ----- Reset delete tag
3095
            $v_delete_file = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $v_delete_file is dead and can be removed.
Loading history...
3096
3097
            // ----- Read the first 512 block header
3098
            if ('tar' === $p_tar_mode) {
3099
                $v_binary_data = fread($v_tar, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3099
                $v_binary_data = fread(/** @scrutinizer ignore-type */ $v_tar, 512);
Loading history...
3100
            } else {
3101
                $v_binary_data = gzread($v_tar, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3101
                $v_binary_data = gzread(/** @scrutinizer ignore-type */ $v_tar, 512);
Loading history...
3102
            }
3103
3104
            // ----- Read the header properties
3105
            if (1 != ($v_result = PclTarHandleReadHeader($v_binary_data, $v_header))) {
3106
                // ----- Close the archive file
3107
                if ('tar' === $p_tar_mode) {
3108
                    fclose($v_tar);
3109
                    fclose($v_temp_tar);
3110
                } else {
3111
                    gzclose($v_tar);
3112
                    gzclose($v_temp_tar);
3113
                }
3114
                @unlink($v_temp_tarname);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

3114
                /** @scrutinizer ignore-unhandled */ @unlink($v_temp_tarname);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
3115
3116
                // ----- Return
3117
                TrFctEnd(__FILE__, __LINE__, $v_result);
3118
3119
                return $v_result;
3120
            }
3121
3122
            // ----- Look for empty blocks to skip
3123
            if ('' == $v_header['filename']) {
3124
                TrFctMessage(__FILE__, __LINE__, 2, 'Empty block found. End of archive?');
3125
                continue;
3126
            }
3127
3128
            TrFctMessage(__FILE__, __LINE__, 2, 'Found file ' . $v_header['filename'] . ", size '" . $v_header['size'] . "'");
3129
3130
            // ----- Look for filenames to update
3131
            for ($i = 0, $v_update_file = false, $v_found_file = false; ($i < count($v_stored_list)) && (!$v_update_file); ++$i) {
3132
                TrFctMessage(__FILE__, __LINE__, 4, "Compare with file '$v_stored_list[$i]'");
3133
3134
                // ----- Compare the file names
3135
                if ($v_stored_list[$i] == $v_header['filename']) {
3136
                    TrFctMessage(__FILE__, __LINE__, 3, "File '$v_stored_list[$i]' is present in archive");
3137
                    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])));
3138
                    TrFctMessage(__FILE__, __LINE__, 3, 'Archived mtime=' . $v_header['mtime'] . ' ' . date('l dS of F Y h:i:s A', $v_header['mtime']));
3139
3140
                    // ----- Store found informations
3141
                    $v_found_file       = true;
3142
                    $v_current_filename = $p_file_list[$i];
3143
3144
                    // ----- Look if the file need to be updated
3145
                    if (filemtime($p_file_list[$i]) > $v_header['mtime']) {
3146
                        TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' need to be updated");
3147
                        $v_update_file = true;
3148
                    } else {
3149
                        TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' does not need to be updated");
3150
                        $v_update_file = false;
3151
                    }
3152
3153
                    // ----- Flag the name in order not to add the file at the end
3154
                    $v_found_list[$i] = 1;
3155
                } else {
3156
                    TrFctMessage(__FILE__, __LINE__, 4, "File '$p_file_list[$i]' is not " . $v_header['filename'] . '');
3157
                }
3158
            }
3159
3160
            // ----- Copy files that do not need to be updated
3161
            if (!$v_update_file) {
3162
                TrFctMessage(__FILE__, __LINE__, 2, 'Keep file ' . $v_header['filename'] . '');
3163
3164
                // ----- Write the file header
3165
                if ('tar' === $p_tar_mode) {
3166
                    fwrite($v_temp_tar, $v_binary_data, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_temp_tar can also be of type false; however, parameter $stream of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3166
                    fwrite(/** @scrutinizer ignore-type */ $v_temp_tar, $v_binary_data, 512);
Loading history...
3167
                } else {
3168
                    gzputs($v_temp_tar, $v_binary_data, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_temp_tar can also be of type false; however, parameter $stream of gzputs() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3168
                    gzputs(/** @scrutinizer ignore-type */ $v_temp_tar, $v_binary_data, 512);
Loading history...
3169
                }
3170
3171
                // ----- Write the file data
3172
                $n = ceil($v_header['size'] / 512);
3173
                for ($j = 0; $j < $n; ++$j) {
3174
                    TrFctMessage(__FILE__, __LINE__, 3, 'Read complete 512 bytes block number ' . ($j + 1));
3175
                    if ('tar' === $p_tar_mode) {
3176
                        $v_content = fread($v_tar, 512);
3177
                        fwrite($v_temp_tar, $v_content, 512);
3178
                    } else {
3179
                        $v_content = gzread($v_tar, 512);
3180
                        gzwrite($v_temp_tar, $v_content, 512);
0 ignored issues
show
Bug introduced by
It seems like $v_temp_tar can also be of type false; however, parameter $stream of gzwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3180
                        gzwrite(/** @scrutinizer ignore-type */ $v_temp_tar, $v_content, 512);
Loading history...
3181
                    }
3182
                }
3183
3184
                // ----- File name and properties are logged if listing mode or file is extracted
3185
                TrFctMessage(__FILE__, __LINE__, 2, 'Memorize info about file ' . $v_header['filename'] . '');
3186
3187
                // ----- Add the array describing the file into the list
3188
                $p_list_detail[$v_nb]           = $v_header;
3189
                $p_list_detail[$v_nb]['status'] = ($v_found_file ? 'not_updated' : 'ok');
3190
3191
                // ----- Increment
3192
                ++$v_nb;
3193
            } // ----- Look for file that need to be updated
3194
            else {
3195
                // ----- Trace
3196
                TrFctMessage(__FILE__, __LINE__, 2, "Start update of file '$v_current_filename'");
3197
3198
                // ----- Store the old file size
3199
                $v_old_size = $v_header['size'];
3200
3201
                // ----- Add the file
3202
                if (1 != ($v_result = PclTarHandleAddFile($v_temp_tar, $v_current_filename, $p_tar_mode, $v_header, $p_add_dir, $p_remove_dir))) {
3203
                    // ----- Close the tarfile
3204
                    if ('tar' === $p_tar_mode) {
3205
                        fclose($v_tar);
3206
                        fclose($v_temp_tar);
3207
                    } else {
3208
                        gzclose($v_tar);
3209
                        gzclose($v_temp_tar);
3210
                    }
3211
                    @unlink($p_temp_tarname);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $p_temp_tarname does not exist. Did you maybe mean $p_tarname?
Loading history...
3212
3213
                    // ----- Return status
3214
                    TrFctEnd(__FILE__, __LINE__, $v_result);
3215
3216
                    return $v_result;
3217
                }
3218
3219
                // ----- Trace
3220
                TrFctMessage(__FILE__, __LINE__, 2, 'Skip old file ' . $v_header['filename'] . '');
3221
3222
                // ----- Jump to next file
3223
                if ('tar' === $p_tar_mode) {
3224
                    fseek($v_tar, ftell($v_tar) + (ceil($v_old_size / 512) * 512));
0 ignored issues
show
Bug introduced by
ftell($v_tar) + ceil($v_old_size / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of fseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3224
                    fseek($v_tar, /** @scrutinizer ignore-type */ ftell($v_tar) + (ceil($v_old_size / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of fseek() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3224
                    fseek(/** @scrutinizer ignore-type */ $v_tar, ftell($v_tar) + (ceil($v_old_size / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of ftell() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3224
                    fseek($v_tar, ftell(/** @scrutinizer ignore-type */ $v_tar) + (ceil($v_old_size / 512) * 512));
Loading history...
3225
                } else {
3226
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_old_size / 512) * 512));
0 ignored issues
show
Bug introduced by
gztell($v_tar) + ceil($v_old_size / 512) * 512 of type double is incompatible with the type integer expected by parameter $offset of gzseek(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3226
                    gzseek($v_tar, /** @scrutinizer ignore-type */ gztell($v_tar) + (ceil($v_old_size / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gztell() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3226
                    gzseek($v_tar, gztell(/** @scrutinizer ignore-type */ $v_tar) + (ceil($v_old_size / 512) * 512));
Loading history...
Bug introduced by
It seems like $v_tar can also be of type false; however, parameter $stream of gzseek() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3226
                    gzseek(/** @scrutinizer ignore-type */ $v_tar, gztell($v_tar) + (ceil($v_old_size / 512) * 512));
Loading history...
3227
                }
3228
3229
                // ----- Add the array describing the file into the list
3230
                $p_list_detail[$v_nb]           = $v_header;
3231
                $p_list_detail[$v_nb]['status'] = 'updated';
3232
3233
                // ----- Increment
3234
                ++$v_nb;
3235
            }
3236
3237
            // ----- Look for end of file
3238
            if ('tar' === $p_tar_mode) {
3239
                $v_end_of_file = feof($v_tar);
3240
            } else {
3241
                $v_end_of_file = gzeof($v_tar);
3242
            }
3243
        }
3244
3245
        // ----- Look for files that does not exists in the archive and need to be added
3246
        for ($i = 0, $iMax = count($p_file_list); $i < $iMax; ++$i) {
3247
            // ----- Look if file not found in the archive
3248
            if (!$v_found_list[$i]) {
3249
                TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' need to be added");
3250
3251
                // ----- Add the file
3252
                if (1 != ($v_result = PclTarHandleAddFile($v_temp_tar, $p_file_list[$i], $p_tar_mode, $v_header, $p_add_dir, $p_remove_dir))) {
3253
                    // ----- Close the tarfile
3254
                    if ('tar' === $p_tar_mode) {
3255
                        fclose($v_tar);
3256
                        fclose($v_temp_tar);
3257
                    } else {
3258
                        gzclose($v_tar);
3259
                        gzclose($v_temp_tar);
3260
                    }
3261
                    @unlink($p_temp_tarname);
3262
3263
                    // ----- Return status
3264
                    TrFctEnd(__FILE__, __LINE__, $v_result);
3265
3266
                    return $v_result;
3267
                }
3268
3269
                // ----- Add the array describing the file into the list
3270
                $p_list_detail[$v_nb]           = $v_header;
3271
                $p_list_detail[$v_nb]['status'] = 'added';
3272
3273
                // ----- Increment
3274
                ++$v_nb;
3275
            } else {
3276
                TrFctMessage(__FILE__, __LINE__, 3, "File '$p_file_list[$i]' was already updated if needed");
3277
            }
3278
        }
3279
3280
        // ----- Write the last empty buffer
3281
        PclTarHandleFooter($v_temp_tar, $p_tar_mode);
3282
3283
        // ----- Close the tarfile
3284
        if ('tar' === $p_tar_mode) {
3285
            fclose($v_tar);
3286
            fclose($v_temp_tar);
3287
        } else {
3288
            gzclose($v_tar);
3289
            gzclose($v_temp_tar);
3290
        }
3291
3292
        // ----- Unlink tar file
3293
        if (!@unlink($p_tarname)) {
3294
            // ----- Error log
3295
            PclErrorLog(-11, "Error while deleting archive name $p_tarname");
3296
        }
3297
3298
        // ----- Rename tar file
3299
        if (!@rename($v_temp_tarname, $p_tarname)) {
3300
            // ----- Error log
3301
            PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
3302
3303
            // ----- Return
3304
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3305
3306
            return PclErrorCode();
3307
        }
3308
3309
        // ----- Return
3310
        TrFctEnd(__FILE__, __LINE__, $v_result);
3311
3312
        return $v_result;
3313
    }
3314
3315
    // --------------------------------------------------------------------------------
3316
3317
    // --------------------------------------------------------------------------------
3318
    // Function : PclTarHandleReadHeader()
3319
    // Description :
3320
    // Parameters :
3321
    // Return Values :
3322
    // --------------------------------------------------------------------------------
3323
    /**
3324
     * @param $v_binary_data
3325
     * @param $v_header
3326
     *
3327
     * @return int
3328
     */
3329
    function PclTarHandleReadHeader($v_binary_data, &$v_header)
3330
    {
3331
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleReadHeader', '');
3332
        $v_result = 1;
3333
3334
        // ----- Read the 512 bytes header
3335
        /*
3336
    if ($p_tar_mode == "tar")
3337
      $v_binary_data = fread($p_tar, 512);
3338
    else
3339
      $v_binary_data = gzread($p_tar, 512);
3340
    */
3341
3342
        // ----- Look for no more block
3343
        if ('' === $v_binary_data) {
3344
            $v_header['filename'] = '';
3345
            $v_header['status']   = 'empty';
3346
3347
            // ----- Return
3348
            TrFctEnd(__FILE__, __LINE__, $v_result, 'End of archive found');
3349
3350
            return $v_result;
3351
        }
3352
3353
        // ----- Look for invalid block size
3354
        if (512 != mb_strlen($v_binary_data)) {
3355
            $v_header['filename'] = '';
3356
            $v_header['status']   = 'invalid_header';
3357
            TrFctMessage(__FILE__, __LINE__, 2, 'Invalid block size : ' . mb_strlen($v_binary_data));
3358
3359
            // ----- Error log
3360
            PclErrorLog(-10, 'Invalid block size : ' . mb_strlen($v_binary_data));
3361
3362
            // ----- Return
3363
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3364
3365
            return PclErrorCode();
3366
        }
3367
3368
        // ----- Calculate the checksum
3369
        $v_checksum = 0;
3370
        // ..... First part of the header
3371
        for ($i = 0; $i < 148; ++$i) {
3372
            $v_checksum += ord(mb_substr($v_binary_data, $i, 1));
3373
        }
3374
        // ..... Ignore the checksum value and replace it by ' ' (space)
3375
        for ($i = 148; $i < 156; ++$i) {
3376
            $v_checksum += ord(' ');
3377
        }
3378
        // ..... Last part of the header
3379
        for ($i = 156; $i < 512; ++$i) {
3380
            $v_checksum += ord(mb_substr($v_binary_data, $i, 1));
3381
        }
3382
        TrFctMessage(__FILE__, __LINE__, 3, "Calculated checksum : $v_checksum");
3383
3384
        // ----- Extract the values
3385
        TrFctMessage(__FILE__, __LINE__, 2, "Header : '$v_binary_data'");
3386
        $v_data = unpack('a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor', $v_binary_data);
3387
3388
        // ----- Extract the checksum for check
3389
        $v_header['checksum'] = octdec(trim($v_data['checksum']));
3390
        TrFctMessage(__FILE__, __LINE__, 3, 'File checksum : ' . $v_header['checksum'] . '');
3391
        if ($v_header['checksum'] != $v_checksum) {
3392
            TrFctMessage(__FILE__, __LINE__, 2, "File checksum is invalid : $v_checksum calculated, " . $v_header['checksum'] . ' expected');
3393
3394
            $v_header['filename'] = '';
3395
            $v_header['status']   = 'invalid_header';
3396
3397
            // ----- Look for last block (empty block)
3398
            if ((256 == $v_checksum) && (0 == $v_header['checksum'])) {
0 ignored issues
show
introduced by
The condition 256 == $v_checksum is always false.
Loading history...
3399
                $v_header['status'] = 'empty';
3400
                // ----- Return
3401
                TrFctEnd(__FILE__, __LINE__, $v_result, 'End of archive found');
3402
3403
                return $v_result;
3404
            }
3405
3406
            // ----- Error log
3407
            PclErrorLog(-13, "Invalid checksum : $v_checksum calculated, " . $v_header['checksum'] . ' expected');
3408
3409
            // ----- Return
3410
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3411
3412
            return PclErrorCode();
3413
        }
3414
        TrFctMessage(__FILE__, __LINE__, 2, "File checksum is valid ($v_checksum)");
3415
3416
        // ----- Extract the properties
3417
        $v_header['filename'] = trim($v_data['filename']);
3418
        TrFctMessage(__FILE__, __LINE__, 2, 'Name : ' . $v_header['filename'] . '');
3419
        $v_header['mode'] = octdec(trim($v_data['mode']));
3420
        TrFctMessage(__FILE__, __LINE__, 2, "Mode : '" . decoct($v_header['mode']) . "'");
3421
        $v_header['uid'] = octdec(trim($v_data['uid']));
3422
        TrFctMessage(__FILE__, __LINE__, 2, "Uid : '" . $v_header['uid'] . "'");
3423
        $v_header['gid'] = octdec(trim($v_data['gid']));
3424
        TrFctMessage(__FILE__, __LINE__, 2, "Gid : '" . $v_header['gid'] . "'");
3425
        $v_header['size'] = octdec(trim($v_data['size']));
3426
        TrFctMessage(__FILE__, __LINE__, 2, "Size : '" . $v_header['size'] . "'");
3427
        $v_header['mtime'] = octdec(trim($v_data['mtime']));
3428
        TrFctMessage(__FILE__, __LINE__, 2, 'Date : ' . date('l dS of F Y h:i:s A', $v_header['mtime']));
3429
        if ('5' == ($v_header['typeflag'] = $v_data['typeflag'])) {
3430
            $v_header['size'] = 0;
3431
            TrFctMessage(__FILE__, __LINE__, 2, "Size (folder) : '" . $v_header['size'] . "'");
3432
        }
3433
        TrFctMessage(__FILE__, __LINE__, 2, 'File typeflag : ' . $v_header['typeflag'] . '');
3434
        /* ----- All these fields are removed form the header because they do not carry interesting info
3435
    $v_header[link] = trim($v_data[link]);
3436
    TrFctMessage(__FILE__, __LINE__, 2, "Linkname : $v_header[linkname]");
3437
    $v_header[magic] = trim($v_data[magic]);
3438
    TrFctMessage(__FILE__, __LINE__, 2, "Magic : $v_header[magic]");
3439
    $v_header[version] = trim($v_data[version]);
3440
    TrFctMessage(__FILE__, __LINE__, 2, "Version : $v_header[version]");
3441
    $v_header[uname] = trim($v_data[uname]);
3442
    TrFctMessage(__FILE__, __LINE__, 2, "Uname : $v_header[uname]");
3443
    $v_header[gname] = trim($v_data[gname]);
3444
    TrFctMessage(__FILE__, __LINE__, 2, "Gname : $v_header[gname]");
3445
    $v_header[devmajor] = trim($v_data[devmajor]);
3446
    TrFctMessage(__FILE__, __LINE__, 2, "Devmajor : $v_header[devmajor]");
3447
    $v_header[devminor] = trim($v_data[devminor]);
3448
    TrFctMessage(__FILE__, __LINE__, 2, "Devminor : $v_header[devminor]");
3449
    */
3450
3451
        // ----- Set the status field
3452
        $v_header['status'] = 'ok';
3453
3454
        // ----- Return
3455
        TrFctEnd(__FILE__, __LINE__, $v_result);
3456
3457
        return $v_result;
3458
    }
3459
3460
    // --------------------------------------------------------------------------------
3461
3462
    // --------------------------------------------------------------------------------
3463
    // Function : PclTarHandlerDirCheck()
3464
    // Description :
3465
    //   Check if a directory exists, if not it creates it and all the parents directory
3466
    //   which may be useful.
3467
    // Parameters :
3468
    //   $p_dir : Directory path to check (without / at the end).
3469
    // Return Values :
3470
    //    1 : OK
3471
    //   -1 : Unable to create directory
3472
    // --------------------------------------------------------------------------------
3473
    /**
3474
     * @param $p_dir
3475
     *
3476
     * @return int
3477
     */
3478
    function PclTarHandlerDirCheck($p_dir)
3479
    {
3480
        $v_result = 1;
3481
3482
        TrFctStart(__FILE__, __LINE__, 'PclTarHandlerDirCheck', (string)$p_dir);
3483
3484
        // ----- Check the directory availability
3485
        if (('' == $p_dir) || is_dir($p_dir)) {
3486
            TrFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
0 ignored issues
show
Bug introduced by
'''.$p_dir.'' is a directory' of type string is incompatible with the type integer expected by parameter $p_return of TrFctEnd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3486
            TrFctEnd(__FILE__, __LINE__, /** @scrutinizer ignore-type */ "'$p_dir' is a directory");
Loading history...
3487
3488
            return 1;
3489
        }
3490
3491
        // ----- Look for file alone
3492
        /*
3493
    if (!strstr("$p_dir", "/")) {
3494
      TrFctEnd(__FILE__, __LINE__,  "'$p_dir' is a file with no directory");
3495
3496
      return 1;
3497
    }
3498
    */
3499
3500
        // ----- Extract parent directory
3501
        $p_parent_dir = dirname($p_dir);
3502
        TrFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
3503
3504
        // ----- Just a check
3505
        if ($p_parent_dir != $p_dir) {
3506
            // ----- Look for parent directory
3507
            if ('' != $p_parent_dir) {
3508
                if (1 != ($v_result = PclTarHandlerDirCheck($p_parent_dir))) {
3509
                    TrFctEnd(__FILE__, __LINE__, $v_result);
3510
3511
                    return $v_result;
3512
                }
3513
            }
3514
        }
3515
3516
        // ----- Create the directory
3517
        TrFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
3518
        if (!mkdir($p_dir, 0777) && !is_dir($p_dir)) {
3519
            // ----- Error log
3520
            PclErrorLog(-8, "Unable to create directory '$p_dir'");
3521
3522
            // ----- Return
3523
            TrFctEnd(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3524
3525
            return PclErrorCode();
3526
        }
3527
3528
        // ----- Return
3529
        TrFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
3530
3531
        return $v_result;
3532
    }
3533
3534
    // --------------------------------------------------------------------------------
3535
3536
    // --------------------------------------------------------------------------------
3537
    // Function : PclTarHandleExtension()
3538
    // Description :
3539
    // Parameters :
3540
    // Return Values :
3541
    // --------------------------------------------------------------------------------
3542
    /**
3543
     * @param $p_tarname
3544
     *
3545
     * @return string
3546
     */
3547
    function PclTarHandleExtension($p_tarname)
3548
    {
3549
        TrFctStart(__FILE__, __LINE__, 'PclTarHandleExtension', "tar=$p_tarname");
3550
3551
        // ----- Look for file extension
3552
        if (('.tar.gz' === mb_substr($p_tarname, -7)) || ('.tgz' === mb_substr($p_tarname, -4))) {
3553
            TrFctMessage(__FILE__, __LINE__, 2, 'Archive is a gzip tar');
3554
            $v_tar_mode = 'tgz';
3555
        } else {
3556
            if ('.tar' === mb_substr($p_tarname, -4)) {
3557
                TrFctMessage(__FILE__, __LINE__, 2, 'Archive is a tar');
3558
                $v_tar_mode = 'tar';
3559
            } else {
3560
                // ----- Error log
3561
                PclErrorLog(-9, 'Invalid archive extension');
3562
3563
                TrFctMessage(__FILE__, __LINE__, PclErrorCode(), PclErrorString());
3564
3565
                $v_tar_mode = '';
3566
            }
3567
        }
3568
3569
        // ----- Return
3570
        TrFctEnd(__FILE__, __LINE__, $v_tar_mode);
0 ignored issues
show
Bug introduced by
$v_tar_mode of type string is incompatible with the type integer expected by parameter $p_return of TrFctEnd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3570
        TrFctEnd(__FILE__, __LINE__, /** @scrutinizer ignore-type */ $v_tar_mode);
Loading history...
3571
3572
        return $v_tar_mode;
3573
    }
3574
3575
    // --------------------------------------------------------------------------------
3576
3577
    // --------------------------------------------------------------------------------
3578
    // Function : PclTarHandlePathReduction()
3579
    // Description :
3580
    // Parameters :
3581
    // Return Values :
3582
    // --------------------------------------------------------------------------------
3583
    /**
3584
     * @param $p_dir
3585
     *
3586
     * @return string
3587
     */
3588
    function PclTarHandlePathReduction($p_dir)
3589
    {
3590
        TrFctStart(__FILE__, __LINE__, 'PclTarHandlePathReduction', "dir='$p_dir'");
3591
        $v_result = '';
3592
3593
        // ----- Look for not empty path
3594
        if ('' != $p_dir) {
3595
            // ----- Explode path by directory names
3596
            $v_list = explode('/', $p_dir);
3597
3598
            // ----- Study directories from last to first
3599
            for ($i = count($v_list) - 1; $i >= 0; --$i) {
3600
                // ----- Look for current path
3601
                if ('.' === $v_list[$i]) {
3602
                    // ----- Ignore this directory
3603
                    // Should be the first $i=0, but no check is done
3604
                } else {
3605
                    if ('..' === $v_list[$i]) {
3606
                        // ----- Ignore it and ignore the $i-1
3607
                        --$i;
3608
                    } else {
3609
                        if ((0 != $i) && ('' == $v_list[$i]) && ($i != (count($v_list) - 1))) {
3610
                            // ----- Ignore only the double '//' in path,
3611
                            // but not the first and last '/'
3612
                        } else {
3613
                            $v_result = $v_list[$i] . ($i != (count($v_list) - 1) ? '/' . $v_result : '');
3614
                        }
3615
                    }
3616
                }
3617
            }
3618
        }
3619
3620
        // ----- Return
3621
        TrFctEnd(__FILE__, __LINE__, $v_result);
0 ignored issues
show
Bug introduced by
$v_result of type string is incompatible with the type integer expected by parameter $p_return of TrFctEnd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3621
        TrFctEnd(__FILE__, __LINE__, /** @scrutinizer ignore-type */ $v_result);
Loading history...
3622
3623
        return $v_result;
3624
    }
3625
3626
    // --------------------------------------------------------------------------------
3627
3628
    // ----- End of double include look
3629
}
3630