[ Index ]
 

Code source de Joomla 1.0.13

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/administrator/includes/pcl/ -> pcltar.lib.php (source)

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


Généré le : Wed Nov 21 14:43:32 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics