[ Index ]

PHP Cross Reference of Joomla 1.5.26 DE

title

Body

[close]

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

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


Generated: Wed Mar 28 15:54:07 2012 Cross-referenced by PHPXref 0.7.1