Issues (733)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

class/pcltar.lib.php (10 issues)

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)) {
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;
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;
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))) {
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...
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))) {
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...
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))) {
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))) {
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;
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))
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);
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);
881
882
            // ----- Read the following blocks but not the last one
883
            if (!gzeof($p_tar)) {
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);
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);
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);
993
994
                // ----- Read the following blocks but not the last one
995
                if (!feof($p_tar_add)) {
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);
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);
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);
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);
1249
1250
            // ----- Read the following blocks but not the last one
1251
            if (!gzeof($p_tar)) {
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);
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
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)))) {
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);
1972
            } else {
1973
                $v_binary_data = gzread($v_tar, 512);
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);
1981
                } else {
1982
                    gzclose($v_tar);
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));
2151
                        } else {
2152
                            gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
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);
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 = '/';
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;
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);
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);
2375
        } else {
2376
            gzclose($v_tar);
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;
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)))) {
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;
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));
2491
                } else {
2492
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
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 = '/';
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;
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));
2665
                } else {
2666
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
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);
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);
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);
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);
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)))) {
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);
2827
            } else {
2828
                $v_binary_data = gzread($v_tar, 512);
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);
2882
                } else {
2883
                    gzputs($v_temp_tar, $v_binary_data, 512);
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);
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)) . ']');
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));
2917
                } else {
2918
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_header['size'] / 512) * 512));
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);
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);
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)))) {
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;
3096
3097
            // ----- Read the first 512 block header
3098
            if ('tar' === $p_tar_mode) {
3099
                $v_binary_data = fread($v_tar, 512);
3100
            } else {
3101
                $v_binary_data = gzread($v_tar, 512);
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);
3167
                } else {
3168
                    gzputs($v_temp_tar, $v_binary_data, 512);
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);
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));
3225
                } else {
3226
                    gzseek($v_tar, gztell($v_tar) + (ceil($v_old_size / 512) * 512));
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'])) {
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");
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);
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);
3622
3623
        return $v_result;
3624
    }
3625
3626
    // --------------------------------------------------------------------------------
3627
3628
    // ----- End of double include look
3629
}
3630