Changeset 23600


Ignore:
Timestamp:
2014/08/22 18:31:39 (6 years ago)
Author:
kimoto
Message:

#2609 モジュールのバグfix

XML_Util 1.2.3
Mobile_Detect 2.8.3
Cache_Lite 1.7.16
Archive_Tar 1.3.12

Location:
branches/version-2_13-dev/data/module
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/version-2_13-dev/data/module/Archive/Tar.php

    r22964 r23600  
    4545define('ARCHIVE_TAR_END_BLOCK', pack("a512", '')); 
    4646 
     47if (!function_exists('gzopen') && function_exists('gzopen64')) { 
     48    function gzopen($filename, $mode, $use_include_path = 0) 
     49    { 
     50        gzopen64($filename, $mode, $use_include_path); 
     51    } 
     52} 
     53 
     54if (!function_exists('gztell') && function_exists('gztell64')) { 
     55    function gztell($zp) 
     56    { 
     57        gztell64($zp); 
     58    } 
     59} 
     60 
     61if (!function_exists('gzseek') && function_exists('gzseek64')) { 
     62    function gzseek($zp, $offset, $whence = SEEK_SET) 
     63    { 
     64        gzseek64($zp, $offset, $whence); 
     65    } 
     66} 
     67 
    4768/** 
    48 * Creates a (compressed) Tar archive 
    49 * 
    50 * @package Archive_Tar 
    51 * @author  Vincent Blavet <vincent@phpconcept.net> 
    52 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License 
    53 * @version $Revision$ 
    54 */ 
     69 * Creates a (compressed) Tar archive 
     70 * 
     71 * @package Archive_Tar 
     72 * @author  Vincent Blavet <vincent@phpconcept.net> 
     73 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License 
     74 * @version $Revision$ 
     75 */ 
    5576class Archive_Tar extends PEAR 
    5677{ 
    5778    /** 
    58     * @var string Name of the Tar 
    59     */ 
    60     var $_tarname=''; 
     79     * @var string Name of the Tar 
     80     */ 
     81    var $_tarname = ''; 
    6182 
    6283    /** 
    63     * @var boolean if true, the Tar file will be gzipped 
    64     */ 
    65     var $_compress=false; 
     84     * @var boolean if true, the Tar file will be gzipped 
     85     */ 
     86    var $_compress = false; 
    6687 
    6788    /** 
    68     * @var string Type of compression : 'none', 'gz' or 'bz2' 
    69     */ 
    70     var $_compress_type='none'; 
     89     * @var string Type of compression : 'none', 'gz', 'bz2' or 'lzma2' 
     90     */ 
     91    var $_compress_type = 'none'; 
    7192 
    7293    /** 
    73     * @var string Explode separator 
    74     */ 
    75     var $_separator=' '; 
     94     * @var string Explode separator 
     95     */ 
     96    var $_separator = ' '; 
    7697 
    7798    /** 
    78     * @var file descriptor 
    79     */ 
    80     var $_file=0; 
     99     * @var file descriptor 
     100     */ 
     101    var $_file = 0; 
    81102 
    82103    /** 
    83     * @var string Local Tar name of a remote Tar (http:// or ftp://) 
    84     */ 
    85     var $_temp_tarname=''; 
     104     * @var string Local Tar name of a remote Tar (http:// or ftp://) 
     105     */ 
     106    var $_temp_tarname = ''; 
    86107 
    87108    /** 
    88     * @var string regular expression for ignoring files or directories 
    89     */ 
    90     var $_ignore_regexp=''; 
     109     * @var string regular expression for ignoring files or directories 
     110     */ 
     111    var $_ignore_regexp = ''; 
    91112 
    92113    /** 
    93114     * @var object PEAR_Error object 
    94115     */ 
    95     var $error_object=null;  
     116    var $error_object = null; 
    96117 
    97118    // {{{ constructor 
    98119    /** 
    99     * Archive_Tar Class constructor. This flavour of the constructor only 
    100     * declare a new Archive_Tar object, identifying it by the name of the 
    101     * tar file. 
    102     * If the compress argument is set the tar will be read or created as a 
    103     * gzip or bz2 compressed TAR file. 
    104     * 
    105     * @param string $p_tarname The name of the tar archive to create 
    106     * @param string $p_compress can be null, 'gz' or 'bz2'. This 
    107     *               parameter indicates if gzip or bz2 compression 
    108     *               is required.  For compatibility reason the 
    109     *               boolean value 'true' means 'gz'. 
    110     * 
    111     * @access public 
    112     */ 
     120     * Archive_Tar Class constructor. This flavour of the constructor only 
     121     * declare a new Archive_Tar object, identifying it by the name of the 
     122     * tar file. 
     123     * If the compress argument is set the tar will be read or created as a 
     124     * gzip or bz2 compressed TAR file. 
     125     * 
     126     * @param string $p_tarname The name of the tar archive to create 
     127     * @param string $p_compress can be null, 'gz', 'bz2' or 'lzma2'. This 
     128     *               parameter indicates if gzip, bz2 or lzma2 compression 
     129     *               is required.  For compatibility reason the 
     130     *               boolean value 'true' means 'gz'. 
     131     * 
     132     * @access public 
     133     */ 
    113134    function Archive_Tar($p_tarname, $p_compress = null) 
    114135    { 
    115         $this->PEAR(); 
     136        if (version_compare(PHP_VERSION, '5.0.0', '<')) { 
     137            $this->PEAR(); 
     138        } 
    116139        $this->_compress = false; 
    117140        $this->_compress_type = 'none'; 
     
    129152                        $this->_compress = true; 
    130153                        $this->_compress_type = 'bz2'; 
     154                    } elseif (file_get_contents($p_tarname, false, null, 1, 4) == '7zXZ') { 
     155                        $this->_compress = true; 
     156                        $this->_compress_type = 'lzma2'; 
    131157                    } 
    132158                } 
     
    138164                    $this->_compress_type = 'gz'; 
    139165                } elseif ((substr($p_tarname, -3) == 'bz2') || 
    140                           (substr($p_tarname, -2) == 'bz')) { 
     166                    (substr($p_tarname, -2) == 'bz') 
     167                ) { 
    141168                    $this->_compress = true; 
    142169                    $this->_compress_type = 'bz2'; 
     170                } else { 
     171                    if (substr($p_tarname, -2) == 'xz') { 
     172                        $this->_compress = true; 
     173                        $this->_compress_type = 'lzma2'; 
     174                    } 
    143175                } 
    144176            } 
     
    147179                $this->_compress = true; 
    148180                $this->_compress_type = 'gz'; 
    149             } else if ($p_compress == 'bz2') { 
    150                 $this->_compress = true; 
    151                 $this->_compress_type = 'bz2'; 
    152181            } else { 
    153                 $this->_error("Unsupported compression type '$p_compress'\n". 
    154                     "Supported types are 'gz' and 'bz2'.\n"); 
    155                 return false; 
     182                if ($p_compress == 'bz2') { 
     183                    $this->_compress = true; 
     184                    $this->_compress_type = 'bz2'; 
     185                } else { 
     186                    if ($p_compress == 'lzma2') { 
     187                        $this->_compress = true; 
     188                        $this->_compress_type = 'lzma2'; 
     189                    } else { 
     190                        $this->_error( 
     191                            "Unsupported compression type '$p_compress'\n" . 
     192                            "Supported types are 'gz', 'bz2' and 'lzma2'.\n" 
     193                        ); 
     194                        return false; 
     195                    } 
     196                } 
    156197            } 
    157198        } 
    158199        $this->_tarname = $p_tarname; 
    159         if ($this->_compress) { // assert zlib or bz2 extension support 
    160             if ($this->_compress_type == 'gz') 
     200        if ($this->_compress) { // assert zlib or bz2 or xz extension support 
     201            if ($this->_compress_type == 'gz') { 
    161202                $extname = 'zlib'; 
    162             else if ($this->_compress_type == 'bz2') 
    163                 $extname = 'bz2'; 
     203            } else { 
     204                if ($this->_compress_type == 'bz2') { 
     205                    $extname = 'bz2'; 
     206                } else { 
     207                    if ($this->_compress_type == 'lzma2') { 
     208                        $extname = 'xz'; 
     209                    } 
     210                } 
     211            } 
    164212 
    165213            if (!extension_loaded($extname)) { 
     
    167215            } 
    168216            if (!extension_loaded($extname)) { 
    169                 $this->_error("The extension '$extname' couldn't be found.\n". 
    170                     "Please make sure your version of PHP was built ". 
    171                     "with '$extname' support.\n"); 
     217                $this->_error( 
     218                    "The extension '$extname' couldn't be found.\n" . 
     219                    "Please make sure your version of PHP was built " . 
     220                    "with '$extname' support.\n" 
     221                ); 
    172222                return false; 
    173223            } 
    174224        } 
    175225    } 
     226 
    176227    // }}} 
    177228 
     
    181232        $this->_close(); 
    182233        // ----- Look for a local copy to delete 
    183         if ($this->_temp_tarname != '') 
     234        if ($this->_temp_tarname != '') { 
    184235            @unlink($this->_temp_tarname); 
     236        } 
    185237        $this->_PEAR(); 
    186238    } 
     239 
     240    // }}} 
     241 
     242    // {{{ PHP5-compatible destructor 
     243    function __destruct() 
     244    { 
     245        $this->_Archive_Tar(); 
     246    } 
     247 
    187248    // }}} 
    188249 
    189250    // {{{ create() 
    190251    /** 
    191     * This method creates the archive file and add the files / directories 
    192     * that are listed in $p_filelist. 
    193     * If a file with the same name exist and is writable, it is replaced 
    194     * by the new tar. 
    195     * The method return false and a PEAR error text. 
    196     * The $p_filelist parameter can be an array of string, each string 
    197     * representing a filename or a directory name with their path if 
    198     * needed. It can also be a single string with names separated by a 
    199     * single blank. 
    200     * For each directory added in the archive, the files and 
    201     * sub-directories are also added. 
    202     * See also createModify() method for more details. 
    203     * 
    204     * @param array $p_filelist An array of filenames and directory names, or a 
    205     *              single string with names separated by a single 
    206     *              blank space. 
    207     * 
    208     * @return true on success, false on error. 
    209     * @see    createModify() 
    210     * @access public 
    211     */ 
     252     * This method creates the archive file and add the files / directories 
     253     * that are listed in $p_filelist. 
     254     * If a file with the same name exist and is writable, it is replaced 
     255     * by the new tar. 
     256     * The method return false and a PEAR error text. 
     257     * The $p_filelist parameter can be an array of string, each string 
     258     * representing a filename or a directory name with their path if 
     259     * needed. It can also be a single string with names separated by a 
     260     * single blank. 
     261     * For each directory added in the archive, the files and 
     262     * sub-directories are also added. 
     263     * See also createModify() method for more details. 
     264     * 
     265     * @param array $p_filelist An array of filenames and directory names, or a 
     266     *              single string with names separated by a single 
     267     *              blank space. 
     268     * 
     269     * @return true on success, false on error. 
     270     * @see    createModify() 
     271     * @access public 
     272     */ 
    212273    function create($p_filelist) 
    213274    { 
    214275        return $this->createModify($p_filelist, '', ''); 
    215276    } 
     277 
    216278    // }}} 
    217279 
    218280    // {{{ add() 
    219281    /** 
    220     * This method add the files / directories that are listed in $p_filelist in 
    221     * the archive. If the archive does not exist it is created. 
    222     * The method return false and a PEAR error text. 
    223     * The files and directories listed are only added at the end of the archive, 
    224     * even if a file with the same name is already archived. 
    225     * See also createModify() method for more details. 
    226     * 
    227     * @param array $p_filelist An array of filenames and directory names, or a 
    228     *              single string with names separated by a single 
    229     *              blank space. 
    230     * 
    231     * @return true on success, false on error. 
    232     * @see    createModify() 
    233     * @access public 
    234     */ 
     282     * This method add the files / directories that are listed in $p_filelist in 
     283     * the archive. If the archive does not exist it is created. 
     284     * The method return false and a PEAR error text. 
     285     * The files and directories listed are only added at the end of the archive, 
     286     * even if a file with the same name is already archived. 
     287     * See also createModify() method for more details. 
     288     * 
     289     * @param array $p_filelist An array of filenames and directory names, or a 
     290     *              single string with names separated by a single 
     291     *              blank space. 
     292     * 
     293     * @return true on success, false on error. 
     294     * @see    createModify() 
     295     * @access public 
     296     */ 
    235297    function add($p_filelist) 
    236298    { 
    237299        return $this->addModify($p_filelist, '', ''); 
    238300    } 
     301 
    239302    // }}} 
    240303 
    241304    // {{{ extract() 
    242     function extract($p_path='', $p_preserve=false) 
     305    function extract($p_path = '', $p_preserve = false) 
    243306    { 
    244307        return $this->extractModify($p_path, '', $p_preserve); 
    245308    } 
     309 
    246310    // }}} 
    247311 
     
    261325        return $v_list_detail; 
    262326    } 
     327 
    263328    // }}} 
    264329 
    265330    // {{{ createModify() 
    266331    /** 
    267     * This method creates the archive file and add the files / directories 
    268     * that are listed in $p_filelist. 
    269     * If the file already exists and is writable, it is replaced by the 
    270     * new tar. It is a create and not an add. If the file exists and is 
    271     * read-only or is a directory it is not replaced. The method return 
    272     * false and a PEAR error text. 
    273     * The $p_filelist parameter can be an array of string, each string 
    274     * representing a filename or a directory name with their path if 
    275     * needed. It can also be a single string with names separated by a 
    276     * single blank. 
    277     * The path indicated in $p_remove_dir will be removed from the 
    278     * memorized path of each file / directory listed when this path 
    279     * exists. By default nothing is removed (empty path '') 
    280     * The path indicated in $p_add_dir will be added at the beginning of 
    281     * the memorized path of each file / directory listed. However it can 
    282     * be set to empty ''. The adding of a path is done after the removing 
    283     * of path. 
    284     * The path add/remove ability enables the user to prepare an archive 
    285     * for extraction in a different path than the origin files are. 
    286     * See also addModify() method for file adding properties. 
    287     * 
    288     * @param array  $p_filelist  An array of filenames and directory names, 
    289     *                             or a single string with names separated by 
    290     *                             a single blank space. 
    291     * @param string $p_add_dir    A string which contains a path to be added 
    292     *                             to the memorized path of each element in 
    293     *                             the list. 
    294     * @param string $p_remove_dir A string which contains a path to be 
    295     *                             removed from the memorized path of each 
    296     *                             element in the list, when relevant. 
    297     * 
    298     * @return boolean true on success, false on error. 
    299     * @access public 
    300     * @see addModify() 
    301     */ 
    302     function createModify($p_filelist, $p_add_dir, $p_remove_dir='') 
     332     * This method creates the archive file and add the files / directories 
     333     * that are listed in $p_filelist. 
     334     * If the file already exists and is writable, it is replaced by the 
     335     * new tar. It is a create and not an add. If the file exists and is 
     336     * read-only or is a directory it is not replaced. The method return 
     337     * false and a PEAR error text. 
     338     * The $p_filelist parameter can be an array of string, each string 
     339     * representing a filename or a directory name with their path if 
     340     * needed. It can also be a single string with names separated by a 
     341     * single blank. 
     342     * The path indicated in $p_remove_dir will be removed from the 
     343     * memorized path of each file / directory listed when this path 
     344     * exists. By default nothing is removed (empty path '') 
     345     * The path indicated in $p_add_dir will be added at the beginning of 
     346     * the memorized path of each file / directory listed. However it can 
     347     * be set to empty ''. The adding of a path is done after the removing 
     348     * of path. 
     349     * The path add/remove ability enables the user to prepare an archive 
     350     * for extraction in a different path than the origin files are. 
     351     * See also addModify() method for file adding properties. 
     352     * 
     353     * @param array $p_filelist An array of filenames and directory names, 
     354     *                             or a single string with names separated by 
     355     *                             a single blank space. 
     356     * @param string $p_add_dir A string which contains a path to be added 
     357     *                             to the memorized path of each element in 
     358     *                             the list. 
     359     * @param string $p_remove_dir A string which contains a path to be 
     360     *                             removed from the memorized path of each 
     361     *                             element in the list, when relevant. 
     362     * 
     363     * @return boolean true on success, false on error. 
     364     * @access public 
     365     * @see addModify() 
     366     */ 
     367    function createModify($p_filelist, $p_add_dir, $p_remove_dir = '') 
    303368    { 
    304369        $v_result = true; 
    305370 
    306         if (!$this->_openWrite()) 
     371        if (!$this->_openWrite()) { 
    307372            return false; 
     373        } 
    308374 
    309375        if ($p_filelist != '') { 
    310             if (is_array($p_filelist)) 
     376            if (is_array($p_filelist)) { 
    311377                $v_list = $p_filelist; 
    312             elseif (is_string($p_filelist)) 
     378            } elseif (is_string($p_filelist)) { 
    313379                $v_list = explode($this->_separator, $p_filelist); 
    314             else { 
     380            } else { 
    315381                $this->_cleanFile(); 
    316382                $this->_error('Invalid file list'); 
     
    324390            $this->_writeFooter(); 
    325391            $this->_close(); 
    326         } else 
     392        } else { 
    327393            $this->_cleanFile(); 
     394        } 
    328395 
    329396        return $v_result; 
    330397    } 
     398 
    331399    // }}} 
    332400 
    333401    // {{{ addModify() 
    334402    /** 
    335     * This method add the files / directories listed in $p_filelist at the 
    336     * end of the existing archive. If the archive does not yet exists it 
    337     * is created. 
    338     * The $p_filelist parameter can be an array of string, each string 
    339     * representing a filename or a directory name with their path if 
    340     * needed. It can also be a single string with names separated by a 
    341     * single blank. 
    342     * The path indicated in $p_remove_dir will be removed from the 
    343     * memorized path of each file / directory listed when this path 
    344     * exists. By default nothing is removed (empty path '') 
    345     * The path indicated in $p_add_dir will be added at the beginning of 
    346     * the memorized path of each file / directory listed. However it can 
    347     * be set to empty ''. The adding of a path is done after the removing 
    348     * of path. 
    349     * The path add/remove ability enables the user to prepare an archive 
    350     * for extraction in a different path than the origin files are. 
    351     * If a file/dir is already in the archive it will only be added at the 
    352     * end of the archive. There is no update of the existing archived 
    353     * file/dir. However while extracting the archive, the last file will 
    354     * replace the first one. This results in a none optimization of the 
    355     * archive size. 
    356     * If a file/dir does not exist the file/dir is ignored. However an 
    357     * error text is send to PEAR error. 
    358     * If a file/dir is not readable the file/dir is ignored. However an 
    359     * error text is send to PEAR error. 
    360     * 
    361     * @param array  $p_filelist  An array of filenames and directory 
    362     *                             names, or a single string with names 
    363     *                             separated by a single blank space. 
    364     * @param string $p_add_dir    A string which contains a path to be 
    365     *                             added to the memorized path of each 
    366     *                             element in the list. 
    367     * @param string $p_remove_dir A string which contains a path to be 
    368     *                             removed from the memorized path of 
    369     *                             each element in the list, when 
    370     *                             relevant. 
    371     * 
    372     * @return true on success, false on error. 
    373     * @access public 
    374     */ 
    375     function addModify($p_filelist, $p_add_dir, $p_remove_dir='') 
     403     * This method add the files / directories listed in $p_filelist at the 
     404     * end of the existing archive. If the archive does not yet exists it 
     405     * is created. 
     406     * The $p_filelist parameter can be an array of string, each string 
     407     * representing a filename or a directory name with their path if 
     408     * needed. It can also be a single string with names separated by a 
     409     * single blank. 
     410     * The path indicated in $p_remove_dir will be removed from the 
     411     * memorized path of each file / directory listed when this path 
     412     * exists. By default nothing is removed (empty path '') 
     413     * The path indicated in $p_add_dir will be added at the beginning of 
     414     * the memorized path of each file / directory listed. However it can 
     415     * be set to empty ''. The adding of a path is done after the removing 
     416     * of path. 
     417     * The path add/remove ability enables the user to prepare an archive 
     418     * for extraction in a different path than the origin files are. 
     419     * If a file/dir is already in the archive it will only be added at the 
     420     * end of the archive. There is no update of the existing archived 
     421     * file/dir. However while extracting the archive, the last file will 
     422     * replace the first one. This results in a none optimization of the 
     423     * archive size. 
     424     * If a file/dir does not exist the file/dir is ignored. However an 
     425     * error text is send to PEAR error. 
     426     * If a file/dir is not readable the file/dir is ignored. However an 
     427     * error text is send to PEAR error. 
     428     * 
     429     * @param array $p_filelist An array of filenames and directory 
     430     *                             names, or a single string with names 
     431     *                             separated by a single blank space. 
     432     * @param string $p_add_dir A string which contains a path to be 
     433     *                             added to the memorized path of each 
     434     *                             element in the list. 
     435     * @param string $p_remove_dir A string which contains a path to be 
     436     *                             removed from the memorized path of 
     437     *                             each element in the list, when 
     438     *                             relevant. 
     439     * 
     440     * @return true on success, false on error. 
     441     * @access public 
     442     */ 
     443    function addModify($p_filelist, $p_add_dir, $p_remove_dir = '') 
    376444    { 
    377445        $v_result = true; 
    378446 
    379         if (!$this->_isArchive()) 
    380             $v_result = $this->createModify($p_filelist, $p_add_dir, 
    381                                             $p_remove_dir); 
    382         else { 
    383             if (is_array($p_filelist)) 
     447        if (!$this->_isArchive()) { 
     448            $v_result = $this->createModify( 
     449                $p_filelist, 
     450                $p_add_dir, 
     451                $p_remove_dir 
     452            ); 
     453        } else { 
     454            if (is_array($p_filelist)) { 
    384455                $v_list = $p_filelist; 
    385             elseif (is_string($p_filelist)) 
     456            } elseif (is_string($p_filelist)) { 
    386457                $v_list = explode($this->_separator, $p_filelist); 
    387             else { 
     458            } else { 
    388459                $this->_error('Invalid file list'); 
    389460                return false; 
     
    395466        return $v_result; 
    396467    } 
     468 
    397469    // }}} 
    398470 
    399471    // {{{ addString() 
    400472    /** 
    401     * This method add a single string as a file at the 
    402     * end of the existing archive. If the archive does not yet exists it 
    403     * is created. 
    404     * 
    405     * @param string $p_filename A string which contains the full 
    406     *                           filename path that will be associated 
    407     *                           with the string. 
    408     * @param string $p_string   The content of the file added in 
    409     *                           the archive. 
    410     * @param int    $p_datetime A custom date/time (unix timestamp) 
    411     *                           for the file (optional). 
    412     * 
    413     * @return true on success, false on error. 
    414     * @access public 
    415     */ 
    416     function addString($p_filename, $p_string, $p_datetime = false) 
    417     { 
     473     * This method add a single string as a file at the 
     474     * end of the existing archive. If the archive does not yet exists it 
     475     * is created. 
     476     * 
     477     * @param string $p_filename A string which contains the full 
     478     *                           filename path that will be associated 
     479     *                           with the string. 
     480     * @param string $p_string The content of the file added in 
     481     *                           the archive. 
     482     * @param int $p_datetime A custom date/time (unix timestamp) 
     483     *                           for the file (optional). 
     484     * @param array $p_params An array of optional params: 
     485     *                               stamp => the datetime (replaces 
     486     *                                   datetime above if it exists) 
     487     *                               mode => the permissions on the 
     488     *                                   file (600 by default) 
     489     *                               type => is this a link?  See the 
     490     *                                   tar specification for details. 
     491     *                                   (default = regular file) 
     492     *                               uid => the user ID of the file 
     493     *                                   (default = 0 = root) 
     494     *                               gid => the group ID of the file 
     495     *                                   (default = 0 = root) 
     496     * 
     497     * @return true on success, false on error. 
     498     * @access public 
     499     */ 
     500    function addString($p_filename, $p_string, $p_datetime = false, $p_params = array()) 
     501    { 
     502        $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time()); 
     503        $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600; 
     504        $p_type = @$p_params["type"] ? $p_params["type"] : ""; 
     505        $p_uid = @$p_params["uid"] ? $p_params["uid"] : ""; 
     506        $p_gid = @$p_params["gid"] ? $p_params["gid"] : ""; 
    418507        $v_result = true; 
    419508 
     
    425514        } 
    426515 
    427         if (!$this->_openAppend()) 
     516        if (!$this->_openAppend()) { 
    428517            return false; 
     518        } 
    429519 
    430520        // Need to check the get back to the temporary file ? .... 
    431         $v_result = $this->_addString($p_filename, $p_string, $p_datetime); 
     521        $v_result = $this->_addString($p_filename, $p_string, $p_datetime, $p_params); 
    432522 
    433523        $this->_writeFooter(); 
     
    437527        return $v_result; 
    438528    } 
     529 
    439530    // }}} 
    440531 
    441532    // {{{ extractModify() 
    442533    /** 
    443     * This method extract all the content of the archive in the directory 
    444     * indicated by $p_path. When relevant the memorized path of the 
    445     * files/dir can be modified by removing the $p_remove_path path at the 
    446     * beginning of the file/dir path. 
    447     * While extracting a file, if the directory path does not exists it is 
    448     * created. 
    449     * While extracting a file, if the file already exists it is replaced 
    450     * without looking for last modification date. 
    451     * While extracting a file, if the file already exists and is write 
    452     * protected, the extraction is aborted. 
    453     * While extracting a file, if a directory with the same name already 
    454     * exists, the extraction is aborted. 
    455     * While extracting a directory, if a file with the same name already 
    456     * exists, the extraction is aborted. 
    457     * While extracting a file/directory if the destination directory exist 
    458     * and is write protected, or does not exist but can not be created, 
    459     * the extraction is aborted. 
    460     * If after extraction an extracted file does not show the correct 
    461     * stored file size, the extraction is aborted. 
    462     * When the extraction is aborted, a PEAR error text is set and false 
    463     * is returned. However the result can be a partial extraction that may 
    464     * need to be manually cleaned. 
    465     * 
    466     * @param string  $p_path        The path of the directory where the 
    467     *                               files/dir need to by extracted. 
    468     * @param string $p_remove_path Part of the memorized path that can be 
    469     *                               removed if present at the beginning of 
    470     *                               the file/dir path. 
    471     * @param boolean $p_preserve    Preserve user/group ownership of files 
    472     * 
    473     * @return boolean true on success, false on error. 
    474     * @access public 
    475     * @see    extractList() 
    476     */ 
    477     function extractModify($p_path, $p_remove_path, $p_preserve=false) 
     534     * This method extract all the content of the archive in the directory 
     535     * indicated by $p_path. When relevant the memorized path of the 
     536     * files/dir can be modified by removing the $p_remove_path path at the 
     537     * beginning of the file/dir path. 
     538     * While extracting a file, if the directory path does not exists it is 
     539     * created. 
     540     * While extracting a file, if the file already exists it is replaced 
     541     * without looking for last modification date. 
     542     * While extracting a file, if the file already exists and is write 
     543     * protected, the extraction is aborted. 
     544     * While extracting a file, if a directory with the same name already 
     545     * exists, the extraction is aborted. 
     546     * While extracting a directory, if a file with the same name already 
     547     * exists, the extraction is aborted. 
     548     * While extracting a file/directory if the destination directory exist 
     549     * and is write protected, or does not exist but can not be created, 
     550     * the extraction is aborted. 
     551     * If after extraction an extracted file does not show the correct 
     552     * stored file size, the extraction is aborted. 
     553     * When the extraction is aborted, a PEAR error text is set and false 
     554     * is returned. However the result can be a partial extraction that may 
     555     * need to be manually cleaned. 
     556     * 
     557     * @param string $p_path The path of the directory where the 
     558     *                               files/dir need to by extracted. 
     559     * @param string $p_remove_path Part of the memorized path that can be 
     560     *                               removed if present at the beginning of 
     561     *                               the file/dir path. 
     562     * @param boolean $p_preserve Preserve user/group ownership of files 
     563     * 
     564     * @return boolean true on success, false on error. 
     565     * @access public 
     566     * @see    extractList() 
     567     */ 
     568    function extractModify($p_path, $p_remove_path, $p_preserve = false) 
    478569    { 
    479570        $v_result = true; 
     
    481572 
    482573        if ($v_result = $this->_openRead()) { 
    483             $v_result = $this->_extractList($p_path, $v_list_detail, 
    484                 "complete", 0, $p_remove_path, $p_preserve); 
     574            $v_result = $this->_extractList( 
     575                $p_path, 
     576                $v_list_detail, 
     577                "complete", 
     578                0, 
     579                $p_remove_path, 
     580                $p_preserve 
     581            ); 
    485582            $this->_close(); 
    486583        } 
     
    488585        return $v_result; 
    489586    } 
     587 
    490588    // }}} 
    491589 
    492590    // {{{ extractInString() 
    493591    /** 
    494     * This method extract from the archive one file identified by $p_filename. 
    495     * The return value is a string with the file content, or NULL on error. 
    496     * 
    497     * @param string $p_filename The path of the file to extract in a string. 
    498     * 
    499     * @return a string with the file content or NULL. 
    500     * @access public 
    501     */ 
     592     * This method extract from the archive one file identified by $p_filename. 
     593     * The return value is a string with the file content, or NULL on error. 
     594     * 
     595     * @param string $p_filename The path of the file to extract in a string. 
     596     * 
     597     * @return a string with the file content or NULL. 
     598     * @access public 
     599     */ 
    502600    function extractInString($p_filename) 
    503601    { 
     
    511609        return $v_result; 
    512610    } 
     611 
    513612    // }}} 
    514613 
    515614    // {{{ extractList() 
    516615    /** 
    517     * This method extract from the archive only the files indicated in the 
    518     * $p_filelist. These files are extracted in the current directory or 
    519     * in the directory indicated by the optional $p_path parameter. 
    520     * If indicated the $p_remove_path can be used in the same way as it is 
    521     * used in extractModify() method. 
    522     * 
    523     * @param array   $p_filelist    An array of filenames and directory names, 
    524     *                               or a single string with names separated 
    525     *                               by a single blank space. 
    526     * @param string  $p_path        The path of the directory where the 
    527     *                               files/dir need to by extracted. 
    528     * @param string $p_remove_path Part of the memorized path that can be 
    529     *                               removed if present at the beginning of 
    530     *                               the file/dir path. 
    531     * @param boolean $p_preserve    Preserve user/group ownership of files 
    532     * 
    533     * @return true on success, false on error. 
    534     * @access public 
    535     * @see    extractModify() 
    536     */ 
    537     function extractList($p_filelist, $p_path='', $p_remove_path='', $p_preserve=false) 
     616     * This method extract from the archive only the files indicated in the 
     617     * $p_filelist. These files are extracted in the current directory or 
     618     * in the directory indicated by the optional $p_path parameter. 
     619     * If indicated the $p_remove_path can be used in the same way as it is 
     620     * used in extractModify() method. 
     621     * 
     622     * @param array $p_filelist An array of filenames and directory names, 
     623     *                               or a single string with names separated 
     624     *                               by a single blank space. 
     625     * @param string $p_path The path of the directory where the 
     626     *                               files/dir need to by extracted. 
     627     * @param string $p_remove_path Part of the memorized path that can be 
     628     *                               removed if present at the beginning of 
     629     *                               the file/dir path. 
     630     * @param boolean $p_preserve Preserve user/group ownership of files 
     631     * 
     632     * @return true on success, false on error. 
     633     * @access public 
     634     * @see    extractModify() 
     635     */ 
     636    function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false) 
    538637    { 
    539638        $v_result = true; 
    540639        $v_list_detail = array(); 
    541640 
    542         if (is_array($p_filelist)) 
     641        if (is_array($p_filelist)) { 
    543642            $v_list = $p_filelist; 
    544         elseif (is_string($p_filelist)) 
     643        } elseif (is_string($p_filelist)) { 
    545644            $v_list = explode($this->_separator, $p_filelist); 
    546         else { 
     645        } else { 
    547646            $this->_error('Invalid string list'); 
    548647            return false; 
     
    550649 
    551650        if ($v_result = $this->_openRead()) { 
    552             $v_result = $this->_extractList($p_path, $v_list_detail, "partial", 
    553                 $v_list, $p_remove_path, $p_preserve); 
     651            $v_result = $this->_extractList( 
     652                $p_path, 
     653                $v_list_detail, 
     654                "partial", 
     655                $v_list, 
     656                $p_remove_path, 
     657                $p_preserve 
     658            ); 
    554659            $this->_close(); 
    555660        } 
     
    557662        return $v_result; 
    558663    } 
     664 
    559665    // }}} 
    560666 
    561667    // {{{ setAttribute() 
    562668    /** 
    563     * This method set specific attributes of the archive. It uses a variable 
    564     * list of parameters, in the format attribute code + attribute values : 
    565     * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ','); 
    566     * 
    567     * @param mixed $argv variable list of attributes and values 
    568     * 
    569     * @return true on success, false on error. 
    570     * @access public 
    571     */ 
     669     * This method set specific attributes of the archive. It uses a variable 
     670     * list of parameters, in the format attribute code + attribute values : 
     671     * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ','); 
     672     * 
     673     * @param mixed $argv variable list of attributes and values 
     674     * 
     675     * @return true on success, false on error. 
     676     * @access public 
     677     */ 
    572678    function setAttribute() 
    573679    { 
     
    580686 
    581687        // ----- Get the arguments 
    582         $v_att_list = &func_get_args(); 
     688        $v_att_list = & func_get_args(); 
    583689 
    584690        // ----- Read the attributes 
    585         $i=0; 
    586         while ($i<$v_size) { 
     691        $i = 0; 
     692        while ($i < $v_size) { 
    587693 
    588694            // ----- Look for next option 
     
    591697                case ARCHIVE_TAR_ATT_SEPARATOR : 
    592698                    // ----- Check the number of parameters 
    593                     if (($i+1) >= $v_size) { 
    594                         $this->_error('Invalid number of parameters for ' 
    595                                       .'attribute ARCHIVE_TAR_ATT_SEPARATOR'); 
     699                    if (($i + 1) >= $v_size) { 
     700                        $this->_error( 
     701                            'Invalid number of parameters for ' 
     702                            . 'attribute ARCHIVE_TAR_ATT_SEPARATOR' 
     703                        ); 
    596704                        return false; 
    597705                    } 
    598706 
    599707                    // ----- Get the value 
    600                     $this->_separator = $v_att_list[$i+1]; 
     708                    $this->_separator = $v_att_list[$i + 1]; 
    601709                    $i++; 
    602                 break; 
     710                    break; 
    603711 
    604712                default : 
    605                     $this->_error('Unknow attribute code '.$v_att_list[$i].''); 
     713                    $this->_error('Unknow attribute code ' . $v_att_list[$i] . ''); 
    606714                    return false; 
    607715            } 
     
    613721        return $v_result; 
    614722    } 
     723 
    615724    // }}} 
    616725 
    617726    // {{{ setIgnoreRegexp() 
    618727    /** 
    619     * This method sets the regular expression for ignoring files and directories 
    620     * at import, for example: 
    621     * $arch->setIgnoreRegexp("#CVS|\.svn#"); 
    622     * 
    623     * @param string $regexp regular expression defining which files or directories to ignore 
    624     * 
    625     * @access public 
    626     */ 
     728     * This method sets the regular expression for ignoring files and directories 
     729     * at import, for example: 
     730     * $arch->setIgnoreRegexp("#CVS|\.svn#"); 
     731     * 
     732     * @param string $regexp regular expression defining which files or directories to ignore 
     733     * 
     734     * @access public 
     735     */ 
    627736    function setIgnoreRegexp($regexp) 
    628737    { 
    629         $this->_ignore_regexp = $regexp; 
    630     } 
     738        $this->_ignore_regexp = $regexp; 
     739    } 
     740 
    631741    // }}} 
    632742 
    633743    // {{{ setIgnoreList() 
    634744    /** 
    635     * This method sets the regular expression for ignoring all files and directories 
    636     * matching the filenames in the array list at import, for example: 
    637     * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool')); 
    638     * 
    639     * @param array $list a list of file or directory names to ignore 
    640     * 
    641     * @access public 
    642     */ 
     745     * This method sets the regular expression for ignoring all files and directories 
     746     * matching the filenames in the array list at import, for example: 
     747     * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool')); 
     748     * 
     749     * @param array $list a list of file or directory names to ignore 
     750     * 
     751     * @access public 
     752     */ 
    643753    function setIgnoreList($list) 
    644754    { 
    645         $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list); 
    646         $regexp = '#/'.join('$|/', $list).'#'; 
    647         $this->setIgnoreRegexp($regexp); 
    648     } 
     755        $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list); 
     756        $regexp = '#/' . join('$|/', $list) . '#'; 
     757        $this->setIgnoreRegexp($regexp); 
     758    } 
     759 
    649760    // }}} 
    650761 
     
    652763    function _error($p_message) 
    653764    { 
    654         $this->error_object = &$this->raiseError($p_message);  
    655     } 
     765        $this->error_object = & $this->raiseError($p_message); 
     766    } 
     767 
    656768    // }}} 
    657769 
     
    659771    function _warning($p_message) 
    660772    { 
    661         $this->error_object = &$this->raiseError($p_message);  
    662     } 
     773        $this->error_object = & $this->raiseError($p_message); 
     774    } 
     775 
    663776    // }}} 
    664777 
    665778    // {{{ _isArchive() 
    666     function _isArchive($p_filename=null) 
     779    function _isArchive($p_filename = null) 
    667780    { 
    668781        if ($p_filename == null) { 
     
    672785        return @is_file($p_filename) && !@is_link($p_filename); 
    673786    } 
     787 
    674788    // }}} 
    675789 
     
    677791    function _openWrite() 
    678792    { 
    679         if ($this->_compress_type == 'gz' && function_exists('gzopen')) 
     793        if ($this->_compress_type == 'gz' && function_exists('gzopen')) { 
    680794            $this->_file = @gzopen($this->_tarname, "wb9"); 
    681         else if ($this->_compress_type == 'bz2' && function_exists('bzopen')) 
    682             $this->_file = @bzopen($this->_tarname, "w"); 
    683         else if ($this->_compress_type == 'none') 
    684             $this->_file = @fopen($this->_tarname, "wb"); 
    685         else { 
    686             $this->_error('Unknown or missing compression type (' 
    687                           .$this->_compress_type.')'); 
     795        } else { 
     796            if ($this->_compress_type == 'bz2' && function_exists('bzopen')) { 
     797                $this->_file = @bzopen($this->_tarname, "w"); 
     798            } else { 
     799                if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) { 
     800                    $this->_file = @xzopen($this->_tarname, 'w'); 
     801                } else { 
     802                    if ($this->_compress_type == 'none') { 
     803                        $this->_file = @fopen($this->_tarname, "wb"); 
     804                    } else { 
     805                        $this->_error( 
     806                            'Unknown or missing compression type (' 
     807                            . $this->_compress_type . ')' 
     808                        ); 
     809                        return false; 
     810                    } 
     811                } 
     812            } 
     813        } 
     814 
     815        if ($this->_file == 0) { 
     816            $this->_error( 
     817                'Unable to open in write mode \'' 
     818                . $this->_tarname . '\'' 
     819            ); 
    688820            return false; 
    689821        } 
    690822 
    691         if ($this->_file == 0) { 
    692             $this->_error('Unable to open in write mode \'' 
    693                           .$this->_tarname.'\''); 
    694             return false; 
    695         } 
    696  
    697823        return true; 
    698824    } 
     825 
    699826    // }}} 
    700827 
     
    704831        if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') { 
    705832 
    706           // ----- Look if a local copy need to be done 
    707           if ($this->_temp_tarname == '') { 
    708               $this->_temp_tarname = uniqid('tar').'.tmp'; 
    709               if (!$v_file_from = @fopen($this->_tarname, 'rb')) { 
    710                 $this->_error('Unable to open in read mode \'' 
    711                               .$this->_tarname.'\''); 
    712                 $this->_temp_tarname = ''; 
    713                 return false; 
    714               } 
    715               if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { 
    716                 $this->_error('Unable to open in write mode \'' 
    717                               .$this->_temp_tarname.'\''); 
    718                 $this->_temp_tarname = ''; 
    719                 return false; 
    720               } 
    721               while ($v_data = @fread($v_file_from, 1024)) 
    722                   @fwrite($v_file_to, $v_data); 
    723               @fclose($v_file_from); 
    724               @fclose($v_file_to); 
    725           } 
    726  
    727           // ----- File to open if the local copy 
    728           $v_filename = $this->_temp_tarname; 
    729  
    730         } else 
    731           // ----- File to open if the normal Tar file 
    732           $v_filename = $this->_tarname; 
    733  
    734         if ($this->_compress_type == 'gz' && function_exists('gzopen')) 
     833            // ----- Look if a local copy need to be done 
     834            if ($this->_temp_tarname == '') { 
     835                $this->_temp_tarname = uniqid('tar') . '.tmp'; 
     836                if (!$v_file_from = @fopen($this->_tarname, 'rb')) { 
     837                    $this->_error( 
     838                        'Unable to open in read mode \'' 
     839                        . $this->_tarname . '\'' 
     840                    ); 
     841                    $this->_temp_tarname = ''; 
     842                    return false; 
     843                } 
     844                if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { 
     845                    $this->_error( 
     846                        'Unable to open in write mode \'' 
     847                        . $this->_temp_tarname . '\'' 
     848                    ); 
     849                    $this->_temp_tarname = ''; 
     850                    return false; 
     851                } 
     852                while ($v_data = @fread($v_file_from, 1024)) { 
     853                    @fwrite($v_file_to, $v_data); 
     854                } 
     855                @fclose($v_file_from); 
     856                @fclose($v_file_to); 
     857            } 
     858 
     859            // ----- File to open if the local copy 
     860            $v_filename = $this->_temp_tarname; 
     861 
     862        } else // ----- File to open if the normal Tar file 
     863        { 
     864            $v_filename = $this->_tarname; 
     865        } 
     866 
     867        if ($this->_compress_type == 'gz' && function_exists('gzopen')) { 
    735868            $this->_file = @gzopen($v_filename, "rb"); 
    736         else if ($this->_compress_type == 'bz2' && function_exists('bzopen')) 
    737             $this->_file = @bzopen($v_filename, "r"); 
    738         else if ($this->_compress_type == 'none') 
    739             $this->_file = @fopen($v_filename, "rb"); 
    740         else { 
    741             $this->_error('Unknown or missing compression type (' 
    742                           .$this->_compress_type.')'); 
     869        } else { 
     870            if ($this->_compress_type == 'bz2' && function_exists('bzopen')) { 
     871                $this->_file = @bzopen($v_filename, "r"); 
     872            } else { 
     873                if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) { 
     874                    $this->_file = @xzopen($v_filename, "r"); 
     875                } else { 
     876                    if ($this->_compress_type == 'none') { 
     877                        $this->_file = @fopen($v_filename, "rb"); 
     878                    } else { 
     879                        $this->_error( 
     880                            'Unknown or missing compression type (' 
     881                            . $this->_compress_type . ')' 
     882                        ); 
     883                        return false; 
     884                    } 
     885                } 
     886            } 
     887        } 
     888 
     889        if ($this->_file == 0) { 
     890            $this->_error('Unable to open in read mode \'' . $v_filename . '\''); 
    743891            return false; 
    744892        } 
    745893 
    746         if ($this->_file == 0) { 
    747             $this->_error('Unable to open in read mode \''.$v_filename.'\''); 
    748             return false; 
    749         } 
    750  
    751894        return true; 
    752895    } 
     896 
    753897    // }}} 
    754898 
     
    756900    function _openReadWrite() 
    757901    { 
    758         if ($this->_compress_type == 'gz') 
     902        if ($this->_compress_type == 'gz') { 
    759903            $this->_file = @gzopen($this->_tarname, "r+b"); 
    760         else if ($this->_compress_type == 'bz2') { 
    761             $this->_error('Unable to open bz2 in read/write mode \'' 
    762                           .$this->_tarname.'\' (limitation of bz2 extension)'); 
     904        } else { 
     905            if ($this->_compress_type == 'bz2') { 
     906                $this->_error( 
     907                    'Unable to open bz2 in read/write mode \'' 
     908                    . $this->_tarname . '\' (limitation of bz2 extension)' 
     909                ); 
     910                return false; 
     911            } else { 
     912                if ($this->_compress_type == 'lzma2') { 
     913                    $this->_error( 
     914                        'Unable to open lzma2 in read/write mode \'' 
     915                        . $this->_tarname . '\' (limitation of lzma2 extension)' 
     916                    ); 
     917                    return false; 
     918                } else { 
     919                    if ($this->_compress_type == 'none') { 
     920                        $this->_file = @fopen($this->_tarname, "r+b"); 
     921                    } else { 
     922                        $this->_error( 
     923                            'Unknown or missing compression type (' 
     924                            . $this->_compress_type . ')' 
     925                        ); 
     926                        return false; 
     927                    } 
     928                } 
     929            } 
     930        } 
     931 
     932        if ($this->_file == 0) { 
     933            $this->_error( 
     934                'Unable to open in read/write mode \'' 
     935                . $this->_tarname . '\'' 
     936            ); 
    763937            return false; 
    764         } else if ($this->_compress_type == 'none') 
    765             $this->_file = @fopen($this->_tarname, "r+b"); 
    766         else { 
    767             $this->_error('Unknown or missing compression type (' 
    768                           .$this->_compress_type.')'); 
    769             return false; 
    770         } 
    771  
    772         if ($this->_file == 0) { 
    773             $this->_error('Unable to open in read/write mode \'' 
    774                           .$this->_tarname.'\''); 
    775             return false; 
    776938        } 
    777939 
    778940        return true; 
    779941    } 
     942 
    780943    // }}} 
    781944 
     
    785948        //if (isset($this->_file)) { 
    786949        if (is_resource($this->_file)) { 
    787             if ($this->_compress_type == 'gz') 
     950            if ($this->_compress_type == 'gz') { 
    788951                @gzclose($this->_file); 
    789             else if ($this->_compress_type == 'bz2') 
    790                 @bzclose($this->_file); 
    791             else if ($this->_compress_type == 'none') 
    792                 @fclose($this->_file); 
    793             else 
    794                 $this->_error('Unknown or missing compression type (' 
    795                               .$this->_compress_type.')'); 
     952            } else { 
     953                if ($this->_compress_type == 'bz2') { 
     954                    @bzclose($this->_file); 
     955                } else { 
     956                    if ($this->_compress_type == 'lzma2') { 
     957                        @xzclose($this->_file); 
     958                    } else { 
     959                        if ($this->_compress_type == 'none') { 
     960                            @fclose($this->_file); 
     961                        } else { 
     962                            $this->_error( 
     963                                'Unknown or missing compression type (' 
     964                                . $this->_compress_type . ')' 
     965                            ); 
     966                        } 
     967                    } 
     968                } 
     969            } 
    796970 
    797971            $this->_file = 0; 
     
    807981        return true; 
    808982    } 
     983 
    809984    // }}} 
    810985 
     
    8271002        return true; 
    8281003    } 
     1004 
    8291005    // }}} 
    8301006 
    8311007    // {{{ _writeBlock() 
    832     function _writeBlock($p_binary_data, $p_len=null) 
    833     { 
    834       if (is_resource($this->_file)) { 
    835           if ($p_len === null) { 
    836               if ($this->_compress_type == 'gz') 
    837                   @gzputs($this->_file, $p_binary_data); 
    838               else if ($this->_compress_type == 'bz2') 
    839                   @bzwrite($this->_file, $p_binary_data); 
    840               else if ($this->_compress_type == 'none') 
    841                   @fputs($this->_file, $p_binary_data); 
    842               else 
    843                   $this->_error('Unknown or missing compression type (' 
    844                                 .$this->_compress_type.')'); 
    845           } else { 
    846               if ($this->_compress_type == 'gz') 
    847                   @gzputs($this->_file, $p_binary_data, $p_len); 
    848               else if ($this->_compress_type == 'bz2') 
    849                   @bzwrite($this->_file, $p_binary_data, $p_len); 
    850               else if ($this->_compress_type == 'none') 
    851                   @fputs($this->_file, $p_binary_data, $p_len); 
    852               else 
    853                   $this->_error('Unknown or missing compression type (' 
    854                                 .$this->_compress_type.')'); 
    855  
    856           } 
    857       } 
    858       return true; 
    859     } 
     1008    function _writeBlock($p_binary_data, $p_len = null) 
     1009    { 
     1010        if (is_resource($this->_file)) { 
     1011            if ($p_len === null) { 
     1012                if ($this->_compress_type == 'gz') { 
     1013                    @gzputs($this->_file, $p_binary_data); 
     1014                } else { 
     1015                    if ($this->_compress_type == 'bz2') { 
     1016                        @bzwrite($this->_file, $p_binary_data); 
     1017                    } else { 
     1018                        if ($this->_compress_type == 'lzma2') { 
     1019                            @xzwrite($this->_file, $p_binary_data); 
     1020                        } else { 
     1021                            if ($this->_compress_type == 'none') { 
     1022                                @fputs($this->_file, $p_binary_data); 
     1023                            } else { 
     1024                                $this->_error( 
     1025                                    'Unknown or missing compression type (' 
     1026                                    . $this->_compress_type . ')' 
     1027                                ); 
     1028                            } 
     1029                        } 
     1030                    } 
     1031                } 
     1032            } else { 
     1033                if ($this->_compress_type == 'gz') { 
     1034                    @gzputs($this->_file, $p_binary_data, $p_len); 
     1035                } else { 
     1036                    if ($this->_compress_type == 'bz2') { 
     1037                        @bzwrite($this->_file, $p_binary_data, $p_len); 
     1038                    } else { 
     1039                        if ($this->_compress_type == 'lzma2') { 
     1040                            @xzwrite($this->_file, $p_binary_data, $p_len); 
     1041                        } else { 
     1042                            if ($this->_compress_type == 'none') { 
     1043                                @fputs($this->_file, $p_binary_data, $p_len); 
     1044                            } else { 
     1045                                $this->_error( 
     1046                                    'Unknown or missing compression type (' 
     1047                                    . $this->_compress_type . ')' 
     1048                                ); 
     1049                            } 
     1050                        } 
     1051                    } 
     1052                } 
     1053 
     1054            } 
     1055        } 
     1056        return true; 
     1057    } 
     1058 
    8601059    // }}} 
    8611060 
     
    8631062    function _readBlock() 
    8641063    { 
    865       $v_block = null; 
    866       if (is_resource($this->_file)) { 
    867           if ($this->_compress_type == 'gz') 
    868               $v_block = @gzread($this->_file, 512); 
    869           else if ($this->_compress_type == 'bz2') 
    870               $v_block = @bzread($this->_file, 512); 
    871           else if ($this->_compress_type == 'none') 
    872               $v_block = @fread($this->_file, 512); 
    873           else 
    874               $this->_error('Unknown or missing compression type (' 
    875                             .$this->_compress_type.')'); 
    876       } 
    877       return $v_block; 
    878     } 
     1064        $v_block = null; 
     1065        if (is_resource($this->_file)) { 
     1066            if ($this->_compress_type == 'gz') { 
     1067                $v_block = @gzread($this->_file, 512); 
     1068            } else { 
     1069                if ($this->_compress_type == 'bz2') { 
     1070                    $v_block = @bzread($this->_file, 512); 
     1071                } else { 
     1072                    if ($this->_compress_type == 'lzma2') { 
     1073                        $v_block = @xzread($this->_file, 512); 
     1074                    } else { 
     1075                        if ($this->_compress_type == 'none') { 
     1076                            $v_block = @fread($this->_file, 512); 
     1077                        } else { 
     1078                            $this->_error( 
     1079                                'Unknown or missing compression type (' 
     1080                                . $this->_compress_type . ')' 
     1081                            ); 
     1082                        } 
     1083                    } 
     1084                } 
     1085            } 
     1086        } 
     1087        return $v_block; 
     1088    } 
     1089 
    8791090    // }}} 
    8801091 
    8811092    // {{{ _jumpBlock() 
    882     function _jumpBlock($p_len=null) 
    883     { 
    884       if (is_resource($this->_file)) { 
    885           if ($p_len === null) 
    886               $p_len = 1; 
    887  
    888           if ($this->_compress_type == 'gz') { 
    889               @gzseek($this->_file, gztell($this->_file)+($p_len*512)); 
    890           } 
    891           else if ($this->_compress_type == 'bz2') { 
    892               // ----- Replace missing bztell() and bzseek() 
    893               for ($i=0; $i<$p_len; $i++) 
    894                   $this->_readBlock(); 
    895           } else if ($this->_compress_type == 'none') 
    896               @fseek($this->_file, $p_len*512, SEEK_CUR); 
    897           else 
    898               $this->_error('Unknown or missing compression type (' 
    899                             .$this->_compress_type.')'); 
    900  
    901       } 
    902       return true; 
    903     } 
     1093    function _jumpBlock($p_len = null) 
     1094    { 
     1095        if (is_resource($this->_file)) { 
     1096            if ($p_len === null) { 
     1097                $p_len = 1; 
     1098            } 
     1099 
     1100            if ($this->_compress_type == 'gz') { 
     1101                @gzseek($this->_file, gztell($this->_file) + ($p_len * 512)); 
     1102            } else { 
     1103                if ($this->_compress_type == 'bz2') { 
     1104                    // ----- Replace missing bztell() and bzseek() 
     1105                    for ($i = 0; $i < $p_len; $i++) { 
     1106                        $this->_readBlock(); 
     1107                    } 
     1108                } else { 
     1109                    if ($this->_compress_type == 'lzma2') { 
     1110                        // ----- Replace missing xztell() and xzseek() 
     1111                        for ($i = 0; $i < $p_len; $i++) { 
     1112                            $this->_readBlock(); 
     1113                        } 
     1114                    } else { 
     1115                        if ($this->_compress_type == 'none') { 
     1116                            @fseek($this->_file, $p_len * 512, SEEK_CUR); 
     1117                        } else { 
     1118                            $this->_error( 
     1119                                'Unknown or missing compression type (' 
     1120                                . $this->_compress_type . ')' 
     1121                            ); 
     1122                        } 
     1123                    } 
     1124                } 
     1125            } 
     1126 
     1127        } 
     1128        return true; 
     1129    } 
     1130 
    9041131    // }}} 
    9051132 
     
    9071134    function _writeFooter() 
    9081135    { 
    909       if (is_resource($this->_file)) { 
    910           // ----- Write the last 0 filled block for end of archive 
    911           $v_binary_data = pack('a1024', ''); 
    912           $this->_writeBlock($v_binary_data); 
    913       } 
    914       return true; 
    915     } 
     1136        if (is_resource($this->_file)) { 
     1137            // ----- Write the last 0 filled block for end of archive 
     1138            $v_binary_data = pack('a1024', ''); 
     1139            $this->_writeBlock($v_binary_data); 
     1140        } 
     1141        return true; 
     1142    } 
     1143 
    9161144    // }}} 
    9171145 
     
    9191147    function _addList($p_list, $p_add_dir, $p_remove_dir) 
    9201148    { 
    921       $v_result=true; 
    922       $v_header = array(); 
    923  
    924       // ----- Remove potential windows directory separator 
    925       $p_add_dir = $this->_translateWinPath($p_add_dir); 
    926       $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); 
    927  
    928       if (!$this->_file) { 
    929           $this->_error('Invalid file descriptor'); 
    930           return false; 
    931       } 
    932  
    933       if (sizeof($p_list) == 0) 
    934           return true; 
    935  
    936       foreach ($p_list as $v_filename) { 
    937           if (!$v_result) { 
    938               break; 
    939           } 
    940  
    941         // ----- Skip the current tar name 
    942         if ($v_filename == $this->_tarname) 
    943             continue; 
    944  
    945         if ($v_filename == '') 
    946             continue; 
    947  
    948         // ----- ignore files and directories matching the ignore regular expression 
    949         if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/'.$v_filename)) { 
    950             $this->_warning("File '$v_filename' ignored"); 
    951             continue; 
    952         } 
    953  
    954         if (!file_exists($v_filename) && !is_link($v_filename)) { 
    955             $this->_warning("File '$v_filename' does not exist"); 
    956             continue; 
    957         } 
    958  
    959         // ----- Add the file or directory header 
    960         if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) 
     1149        $v_result = true; 
     1150        $v_header = array(); 
     1151 
     1152        // ----- Remove potential windows directory separator 
     1153        $p_add_dir = $this->_translateWinPath($p_add_dir); 
     1154        $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); 
     1155 
     1156        if (!$this->_file) { 
     1157            $this->_error('Invalid file descriptor'); 
    9611158            return false; 
    962  
    963         if (@is_dir($v_filename) && !@is_link($v_filename)) { 
    964             if (!($p_hdir = opendir($v_filename))) { 
    965                 $this->_warning("Directory '$v_filename' can not be read"); 
     1159        } 
     1160 
     1161        if (sizeof($p_list) == 0) { 
     1162            return true; 
     1163        } 
     1164 
     1165        foreach ($p_list as $v_filename) { 
     1166            if (!$v_result) { 
     1167                break; 
     1168            } 
     1169 
     1170            // ----- Skip the current tar name 
     1171            if ($v_filename == $this->_tarname) { 
    9661172                continue; 
    9671173            } 
    968             while (false !== ($p_hitem = readdir($p_hdir))) { 
    969                 if (($p_hitem != '.') && ($p_hitem != '..')) { 
    970                     if ($v_filename != ".") 
    971                         $p_temp_list[0] = $v_filename.'/'.$p_hitem; 
    972                     else 
    973                         $p_temp_list[0] = $p_hitem; 
    974  
    975                     $v_result = $this->_addList($p_temp_list, 
    976                                                 $p_add_dir, 
    977                                                 $p_remove_dir); 
    978                 } 
    979             } 
    980  
    981             unset($p_temp_list); 
    982             unset($p_hdir); 
    983             unset($p_hitem); 
    984         } 
    985       } 
    986  
    987       return $v_result; 
    988     } 
     1174 
     1175            if ($v_filename == '') { 
     1176                continue; 
     1177            } 
     1178 
     1179            // ----- ignore files and directories matching the ignore regular expression 
     1180            if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/' . $v_filename)) { 
     1181                $this->_warning("File '$v_filename' ignored"); 
     1182                continue; 
     1183            } 
     1184 
     1185            if (!file_exists($v_filename) && !is_link($v_filename)) { 
     1186                $this->_warning("File '$v_filename' does not exist"); 
     1187                continue; 
     1188            } 
     1189 
     1190            // ----- Add the file or directory header 
     1191            if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) { 
     1192                return false; 
     1193            } 
     1194 
     1195            if (@is_dir($v_filename) && !@is_link($v_filename)) { 
     1196                if (!($p_hdir = opendir($v_filename))) { 
     1197                    $this->_warning("Directory '$v_filename' can not be read"); 
     1198                    continue; 
     1199                } 
     1200                while (false !== ($p_hitem = readdir($p_hdir))) { 
     1201                    if (($p_hitem != '.') && ($p_hitem != '..')) { 
     1202                        if ($v_filename != ".") { 
     1203                            $p_temp_list[0] = $v_filename . '/' . $p_hitem; 
     1204                        } else { 
     1205                            $p_temp_list[0] = $p_hitem; 
     1206                        } 
     1207 
     1208                        $v_result = $this->_addList( 
     1209                            $p_temp_list, 
     1210                            $p_add_dir, 
     1211                            $p_remove_dir 
     1212                        ); 
     1213                    } 
     1214                } 
     1215 
     1216                unset($p_temp_list); 
     1217                unset($p_hdir); 
     1218                unset($p_hitem); 
     1219            } 
     1220        } 
     1221 
     1222        return $v_result; 
     1223    } 
     1224 
    9891225    // }}} 
    9901226 
    9911227    // {{{ _addFile() 
    992     function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir) 
    993     { 
    994       if (!$this->_file) { 
    995           $this->_error('Invalid file descriptor'); 
    996           return false; 
    997       } 
    998  
    999       if ($p_filename == '') { 
    1000           $this->_error('Invalid file name'); 
    1001           return false; 
    1002       } 
    1003  
    1004       // ----- Calculate the stored filename 
    1005       $p_filename = $this->_translateWinPath($p_filename, false);; 
    1006       $v_stored_filename = $p_filename; 
    1007       if (strcmp($p_filename, $p_remove_dir) == 0) { 
    1008           return true; 
    1009       } 
    1010       if ($p_remove_dir != '') { 
    1011           if (substr($p_remove_dir, -1) != '/') 
    1012               $p_remove_dir .= '/'; 
    1013  
    1014           if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) 
    1015               $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); 
    1016       } 
    1017       $v_stored_filename = $this->_translateWinPath($v_stored_filename); 
    1018       if ($p_add_dir != '') { 
    1019           if (substr($p_add_dir, -1) == '/') 
    1020               $v_stored_filename = $p_add_dir.$v_stored_filename; 
    1021           else 
    1022               $v_stored_filename = $p_add_dir.'/'.$v_stored_filename; 
    1023       } 
    1024  
    1025       $v_stored_filename = $this->_pathReduction($v_stored_filename); 
    1026  
    1027       if ($this->_isArchive($p_filename)) { 
    1028           if (($v_file = @fopen($p_filename, "rb")) == 0) { 
    1029               $this->_warning("Unable to open file '".$p_filename 
    1030                               ."' in binary read mode"); 
    1031               return true; 
    1032           } 
    1033  
    1034           if (!$this->_writeHeader($p_filename, $v_stored_filename)) 
    1035               return false; 
    1036  
    1037           while (($v_buffer = fread($v_file, 512)) != '') { 
    1038               $v_binary_data = pack("a512", "$v_buffer"); 
    1039               $this->_writeBlock($v_binary_data); 
    1040           } 
    1041  
    1042           fclose($v_file); 
    1043  
    1044       } else { 
    1045           // ----- Only header for dir 
    1046           if (!$this->_writeHeader($p_filename, $v_stored_filename)) 
    1047               return false; 
    1048       } 
    1049  
    1050       return true; 
    1051     } 
     1228    function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null) 
     1229    { 
     1230        if (!$this->_file) { 
     1231            $this->_error('Invalid file descriptor'); 
     1232            return false; 
     1233        } 
     1234 
     1235        if ($p_filename == '') { 
     1236            $this->_error('Invalid file name'); 
     1237            return false; 
     1238        } 
     1239 
     1240        if (is_null($v_stored_filename)) { 
     1241            // ----- Calculate the stored filename 
     1242            $p_filename = $this->_translateWinPath($p_filename, false);; 
     1243            $v_stored_filename = $p_filename; 
     1244 
     1245            if (strcmp($p_filename, $p_remove_dir) == 0) { 
     1246                return true; 
     1247            } 
     1248 
     1249            if ($p_remove_dir != '') { 
     1250                if (substr($p_remove_dir, -1) != '/') { 
     1251                    $p_remove_dir .= '/'; 
     1252                } 
     1253 
     1254                if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) { 
     1255                    $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); 
     1256                } 
     1257            } 
     1258 
     1259            $v_stored_filename = $this->_translateWinPath($v_stored_filename); 
     1260            if ($p_add_dir != '') { 
     1261                if (substr($p_add_dir, -1) == '/') { 
     1262                    $v_stored_filename = $p_add_dir . $v_stored_filename; 
     1263                } else { 
     1264                    $v_stored_filename = $p_add_dir . '/' . $v_stored_filename; 
     1265                } 
     1266            } 
     1267 
     1268            $v_stored_filename = $this->_pathReduction($v_stored_filename); 
     1269        } 
     1270 
     1271        if ($this->_isArchive($p_filename)) { 
     1272            if (($v_file = @fopen($p_filename, "rb")) == 0) { 
     1273                $this->_warning( 
     1274                    "Unable to open file '" . $p_filename 
     1275                    . "' in binary read mode" 
     1276                ); 
     1277                return true; 
     1278            } 
     1279 
     1280            if (!$this->_writeHeader($p_filename, $v_stored_filename)) { 
     1281                return false; 
     1282            } 
     1283 
     1284            while (($v_buffer = fread($v_file, 512)) != '') { 
     1285                $v_binary_data = pack("a512", "$v_buffer"); 
     1286                $this->_writeBlock($v_binary_data); 
     1287            } 
     1288 
     1289            fclose($v_file); 
     1290 
     1291        } else { 
     1292            // ----- Only header for dir 
     1293            if (!$this->_writeHeader($p_filename, $v_stored_filename)) { 
     1294                return false; 
     1295            } 
     1296        } 
     1297 
     1298        return true; 
     1299    } 
     1300 
    10521301    // }}} 
    10531302 
    10541303    // {{{ _addString() 
    1055     function _addString($p_filename, $p_string, $p_datetime = false) 
    1056     { 
    1057       if (!$this->_file) { 
    1058           $this->_error('Invalid file descriptor'); 
    1059           return false; 
    1060       } 
    1061  
    1062       if ($p_filename == '') { 
    1063           $this->_error('Invalid file name'); 
    1064           return false; 
    1065       } 
    1066  
    1067       // ----- Calculate the stored filename 
    1068       $p_filename = $this->_translateWinPath($p_filename, false);; 
    1069        
    1070       // ----- If datetime is not specified, set current time 
    1071       if ($p_datetime === false) { 
    1072           $p_datetime = time(); 
    1073       } 
    1074  
    1075       if (!$this->_writeHeaderBlock($p_filename, strlen($p_string), 
    1076                                     $p_datetime, 384, "", 0, 0)) 
    1077           return false; 
    1078  
    1079       $i=0; 
    1080       while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') { 
    1081           $v_binary_data = pack("a512", $v_buffer); 
    1082           $this->_writeBlock($v_binary_data); 
    1083       } 
    1084  
    1085       return true; 
    1086     } 
     1304    function _addString($p_filename, $p_string, $p_datetime = false, $p_params = array()) 
     1305    { 
     1306        $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time()); 
     1307        $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600; 
     1308        $p_type = @$p_params["type"] ? $p_params["type"] : ""; 
     1309        $p_uid = @$p_params["uid"] ? $p_params["uid"] : 0; 
     1310        $p_gid = @$p_params["gid"] ? $p_params["gid"] : 0; 
     1311        if (!$this->_file) { 
     1312            $this->_error('Invalid file descriptor'); 
     1313            return false; 
     1314        } 
     1315 
     1316        if ($p_filename == '') { 
     1317            $this->_error('Invalid file name'); 
     1318            return false; 
     1319        } 
     1320 
     1321        // ----- Calculate the stored filename 
     1322        $p_filename = $this->_translateWinPath($p_filename, false);; 
     1323 
     1324        // ----- If datetime is not specified, set current time 
     1325        if ($p_datetime === false) { 
     1326            $p_datetime = time(); 
     1327        } 
     1328 
     1329        if (!$this->_writeHeaderBlock( 
     1330            $p_filename, 
     1331            strlen($p_string), 
     1332            $p_stamp, 
     1333            $p_mode, 
     1334            $p_type, 
     1335            $p_uid, 
     1336            $p_gid 
     1337        ) 
     1338        ) { 
     1339            return false; 
     1340        } 
     1341 
     1342        $i = 0; 
     1343        while (($v_buffer = substr($p_string, (($i++) * 512), 512)) != '') { 
     1344            $v_binary_data = pack("a512", $v_buffer); 
     1345            $this->_writeBlock($v_binary_data); 
     1346        } 
     1347 
     1348        return true; 
     1349    } 
     1350 
    10871351    // }}} 
    10881352 
     
    10901354    function _writeHeader($p_filename, $p_stored_filename) 
    10911355    { 
    1092         if ($p_stored_filename == '') 
     1356        if ($p_stored_filename == '') { 
    10931357            $p_stored_filename = $p_filename; 
     1358        } 
    10941359        $v_reduce_filename = $this->_pathReduction($p_stored_filename); 
    10951360 
    10961361        if (strlen($v_reduce_filename) > 99) { 
    1097           if (!$this->_writeLongHeader($v_reduce_filename)) 
    1098             return false; 
     1362            if (!$this->_writeLongHeader($v_reduce_filename)) { 
     1363                return false; 
     1364            } 
    10991365        } 
    11001366 
     
    11091375 
    11101376        if (@is_link($p_filename)) { 
    1111           $v_typeflag = '2'; 
    1112           $v_linkname = readlink($p_filename); 
    1113           $v_size = sprintf("%011s", DecOct(0)); 
     1377            $v_typeflag = '2'; 
     1378            $v_linkname = readlink($p_filename); 
     1379            $v_size = sprintf("%011s", DecOct(0)); 
    11141380        } elseif (@is_dir($p_filename)) { 
    1115           $v_typeflag = "5"; 
    1116           $v_size = sprintf("%011s", DecOct(0)); 
     1381            $v_typeflag = "5"; 
     1382            $v_size = sprintf("%011s", DecOct(0)); 
    11171383        } else { 
    1118           $v_typeflag = '0'; 
    1119           clearstatcache(); 
    1120           $v_size = sprintf("%011s", DecOct($v_info['size'])); 
     1384            $v_typeflag = '0'; 
     1385            clearstatcache(); 
     1386            $v_size = sprintf("%011s", DecOct($v_info['size'])); 
    11211387        } 
    11221388 
     
    11241390 
    11251391        $v_version = ' '; 
    1126          
    1127         if (function_exists('posix_getpwuid')) 
    1128         { 
    1129           $userinfo = posix_getpwuid($v_info[4]); 
    1130           $groupinfo = posix_getgrgid($v_info[5]); 
    1131            
    1132           $v_uname = $userinfo['name']; 
    1133           $v_gname = $groupinfo['name']; 
    1134         } 
    1135         else 
    1136         { 
    1137           $v_uname = ''; 
    1138           $v_gname = ''; 
     1392 
     1393        if (function_exists('posix_getpwuid')) { 
     1394            $userinfo = posix_getpwuid($v_info[4]); 
     1395            $groupinfo = posix_getgrgid($v_info[5]); 
     1396 
     1397            $v_uname = $userinfo['name']; 
     1398            $v_gname = $groupinfo['name']; 
     1399        } else { 
     1400            $v_uname = ''; 
     1401            $v_gname = ''; 
    11391402        } 
    11401403 
     
    11451408        $v_prefix = ''; 
    11461409 
    1147         $v_binary_data_first = pack("a100a8a8a8a12a12", 
    1148                                     $v_reduce_filename, $v_perms, $v_uid, 
    1149                                     $v_gid, $v_size, $v_mtime); 
    1150         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", 
    1151                                    $v_typeflag, $v_linkname, $v_magic, 
    1152                                    $v_version, $v_uname, $v_gname, 
    1153                                    $v_devmajor, $v_devminor, $v_prefix, ''); 
     1410        $v_binary_data_first = pack( 
     1411            "a100a8a8a8a12a12", 
     1412            $v_reduce_filename, 
     1413            $v_perms, 
     1414            $v_uid, 
     1415            $v_gid, 
     1416            $v_size, 
     1417            $v_mtime 
     1418        ); 
     1419        $v_binary_data_last = pack( 
     1420            "a1a100a6a2a32a32a8a8a155a12", 
     1421            $v_typeflag, 
     1422            $v_linkname, 
     1423            $v_magic, 
     1424            $v_version, 
     1425            $v_uname, 
     1426            $v_gname, 
     1427            $v_devmajor, 
     1428            $v_devminor, 
     1429            $v_prefix, 
     1430            '' 
     1431        ); 
    11541432 
    11551433        // ----- Calculate the checksum 
    11561434        $v_checksum = 0; 
    11571435        // ..... First part of the header 
    1158         for ($i=0; $i<148; $i++) 
    1159             $v_checksum += ord(substr($v_binary_data_first,$i,1)); 
     1436        for ($i = 0; $i < 148; $i++) { 
     1437            $v_checksum += ord(substr($v_binary_data_first, $i, 1)); 
     1438        } 
    11601439        // ..... Ignore the checksum value and replace it by ' ' (space) 
    1161         for ($i=148; $i<156; $i++) 
     1440        for ($i = 148; $i < 156; $i++) { 
    11621441            $v_checksum += ord(' '); 
     1442        } 
    11631443        // ..... Last part of the header 
    1164         for ($i=156, $j=0; $i<512; $i++, $j++) 
    1165             $v_checksum += ord(substr($v_binary_data_last,$j,1)); 
     1444        for ($i = 156, $j = 0; $i < 512; $i++, $j++) { 
     1445            $v_checksum += ord(substr($v_binary_data_last, $j, 1)); 
     1446        } 
    11661447 
    11671448        // ----- Write the first 148 bytes of the header in the archive 
     
    11781459        return true; 
    11791460    } 
     1461 
    11801462    // }}} 
    11811463 
    11821464    // {{{ _writeHeaderBlock() 
    1183     function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0, 
    1184                                $p_type='', $p_uid=0, $p_gid=0) 
    1185     { 
     1465    function _writeHeaderBlock( 
     1466        $p_filename, 
     1467        $p_size, 
     1468        $p_mtime = 0, 
     1469        $p_perms = 0, 
     1470        $p_type = '', 
     1471        $p_uid = 0, 
     1472        $p_gid = 0 
     1473    ) { 
    11861474        $p_filename = $this->_pathReduction($p_filename); 
    11871475 
    11881476        if (strlen($p_filename) > 99) { 
    1189           if (!$this->_writeLongHeader($p_filename)) 
    1190             return false; 
     1477            if (!$this->_writeLongHeader($p_filename)) { 
     1478                return false; 
     1479            } 
    11911480        } 
    11921481 
    11931482        if ($p_type == "5") { 
    1194           $v_size = sprintf("%011s", DecOct(0)); 
     1483            $v_size = sprintf("%011s", DecOct(0)); 
    11951484        } else { 
    1196           $v_size = sprintf("%011s", DecOct($p_size)); 
     1485            $v_size = sprintf("%011s", DecOct($p_size)); 
    11971486        } 
    11981487 
     
    12091498        $v_version = ' '; 
    12101499 
    1211         if (function_exists('posix_getpwuid')) 
    1212         { 
    1213           $userinfo = posix_getpwuid($p_uid); 
    1214           $groupinfo = posix_getgrgid($p_gid); 
    1215            
    1216           $v_uname = $userinfo['name']; 
    1217           $v_gname = $groupinfo['name']; 
    1218         } 
    1219         else 
    1220         { 
    1221           $v_uname = ''; 
    1222           $v_gname = ''; 
    1223         } 
    1224          
     1500        if (function_exists('posix_getpwuid')) { 
     1501            $userinfo = posix_getpwuid($p_uid); 
     1502            $groupinfo = posix_getgrgid($p_gid); 
     1503 
     1504            $v_uname = $userinfo['name']; 
     1505            $v_gname = $groupinfo['name']; 
     1506        } else { 
     1507            $v_uname = ''; 
     1508            $v_gname = ''; 
     1509        } 
     1510 
    12251511        $v_devmajor = ''; 
    12261512 
     
    12291515        $v_prefix = ''; 
    12301516 
    1231         $v_binary_data_first = pack("a100a8a8a8a12A12", 
    1232                                     $p_filename, $v_perms, $v_uid, $v_gid, 
    1233                                     $v_size, $v_mtime); 
    1234         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", 
    1235                                    $p_type, $v_linkname, $v_magic, 
    1236                                    $v_version, $v_uname, $v_gname, 
    1237                                    $v_devmajor, $v_devminor, $v_prefix, ''); 
     1517        $v_binary_data_first = pack( 
     1518            "a100a8a8a8a12A12", 
     1519            $p_filename, 
     1520            $v_perms, 
     1521            $v_uid, 
     1522            $v_gid, 
     1523            $v_size, 
     1524            $v_mtime 
     1525        ); 
     1526        $v_binary_data_last = pack( 
     1527            "a1a100a6a2a32a32a8a8a155a12", 
     1528            $p_type, 
     1529            $v_linkname, 
     1530            $v_magic, 
     1531            $v_version, 
     1532            $v_uname, 
     1533            $v_gname, 
     1534            $v_devmajor, 
     1535            $v_devminor, 
     1536            $v_prefix, 
     1537            '' 
     1538        ); 
    12381539 
    12391540        // ----- Calculate the checksum 
    12401541        $v_checksum = 0; 
    12411542        // ..... First part of the header 
    1242         for ($i=0; $i<148; $i++) 
    1243             $v_checksum += ord(substr($v_binary_data_first,$i,1)); 
     1543        for ($i = 0; $i < 148; $i++) { 
     1544            $v_checksum += ord(substr($v_binary_data_first, $i, 1)); 
     1545        } 
    12441546        // ..... Ignore the checksum value and replace it by ' ' (space) 
    1245         for ($i=148; $i<156; $i++) 
     1547        for ($i = 148; $i < 156; $i++) { 
    12461548            $v_checksum += ord(' '); 
     1549        } 
    12471550        // ..... Last part of the header 
    1248         for ($i=156, $j=0; $i<512; $i++, $j++) 
    1249             $v_checksum += ord(substr($v_binary_data_last,$j,1)); 
     1551        for ($i = 156, $j = 0; $i < 512; $i++, $j++) { 
     1552            $v_checksum += ord(substr($v_binary_data_last, $j, 1)); 
     1553        } 
    12501554 
    12511555        // ----- Write the first 148 bytes of the header in the archive 
     
    12621566        return true; 
    12631567    } 
     1568 
    12641569    // }}} 
    12651570 
     
    12871592        $v_prefix = ''; 
    12881593 
    1289         $v_binary_data_first = pack("a100a8a8a8a12a12", 
    1290                                     '././@LongLink', 0, 0, 0, $v_size, 0); 
    1291         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", 
    1292                                    $v_typeflag, $v_linkname, $v_magic, 
    1293                                    $v_version, $v_uname, $v_gname, 
    1294                                    $v_devmajor, $v_devminor, $v_prefix, ''); 
     1594        $v_binary_data_first = pack( 
     1595            "a100a8a8a8a12a12", 
     1596            '././@LongLink', 
     1597            0, 
     1598            0, 
     1599            0, 
     1600            $v_size, 
     1601            0 
     1602        ); 
     1603        $v_binary_data_last = pack( 
     1604            "a1a100a6a2a32a32a8a8a155a12", 
     1605            $v_typeflag, 
     1606            $v_linkname, 
     1607            $v_magic, 
     1608            $v_version, 
     1609            $v_uname, 
     1610            $v_gname, 
     1611            $v_devmajor, 
     1612            $v_devminor, 
     1613            $v_prefix, 
     1614            '' 
     1615        ); 
    12951616 
    12961617        // ----- Calculate the checksum 
    12971618        $v_checksum = 0; 
    12981619        // ..... First part of the header 
    1299         for ($i=0; $i<148; $i++) 
    1300             $v_checksum += ord(substr($v_binary_data_first,$i,1)); 
     1620        for ($i = 0; $i < 148; $i++) { 
     1621            $v_checksum += ord(substr($v_binary_data_first, $i, 1)); 
     1622        } 
    13011623        // ..... Ignore the checksum value and replace it by ' ' (space) 
    1302         for ($i=148; $i<156; $i++) 
     1624        for ($i = 148; $i < 156; $i++) { 
    13031625            $v_checksum += ord(' '); 
     1626        } 
    13041627        // ..... Last part of the header 
    1305         for ($i=156, $j=0; $i<512; $i++, $j++) 
    1306             $v_checksum += ord(substr($v_binary_data_last,$j,1)); 
     1628        for ($i = 156, $j = 0; $i < 512; $i++, $j++) { 
     1629            $v_checksum += ord(substr($v_binary_data_last, $j, 1)); 
     1630        } 
    13071631 
    13081632        // ----- Write the first 148 bytes of the header in the archive 
     
    13181642 
    13191643        // ----- Write the filename as content of the block 
    1320         $i=0; 
    1321         while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') { 
     1644        $i = 0; 
     1645        while (($v_buffer = substr($p_filename, (($i++) * 512), 512)) != '') { 
    13221646            $v_binary_data = pack("a512", "$v_buffer"); 
    13231647            $this->_writeBlock($v_binary_data); 
     
    13261650        return true; 
    13271651    } 
     1652 
    13281653    // }}} 
    13291654 
     
    13311656    function _readHeader($v_binary_data, &$v_header) 
    13321657    { 
    1333         if (strlen($v_binary_data)==0) { 
     1658        if (strlen($v_binary_data) == 0) { 
    13341659            $v_header['filename'] = ''; 
    13351660            return true; 
     
    13381663        if (strlen($v_binary_data) != 512) { 
    13391664            $v_header['filename'] = ''; 
    1340             $this->_error('Invalid block size : '.strlen($v_binary_data)); 
     1665            $this->_error('Invalid block size : ' . strlen($v_binary_data)); 
    13411666            return false; 
    13421667        } 
     
    13481673        $v_checksum = 0; 
    13491674        // ..... First part of the header 
    1350         for ($i=0; $i<148; $i++) 
    1351             $v_checksum+=ord(substr($v_binary_data,$i,1)); 
     1675        for ($i = 0; $i < 148; $i++) { 
     1676            $v_checksum += ord(substr($v_binary_data, $i, 1)); 
     1677        } 
    13521678        // ..... Ignore the checksum value and replace it by ' ' (space) 
    1353         for ($i=148; $i<156; $i++) 
     1679        for ($i = 148; $i < 156; $i++) { 
    13541680            $v_checksum += ord(' '); 
     1681        } 
    13551682        // ..... Last part of the header 
    1356         for ($i=156; $i<512; $i++) 
    1357            $v_checksum+=ord(substr($v_binary_data,$i,1)); 
    1358  
    1359         if (version_compare(PHP_VERSION,"5.5.0-dev")<0) { 
     1683        for ($i = 156; $i < 512; $i++) { 
     1684            $v_checksum += ord(substr($v_binary_data, $i, 1)); 
     1685        } 
     1686 
     1687        if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) { 
    13601688            $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" . 
    1361                    "a8checksum/a1typeflag/a100link/a6magic/a2version/" . 
    1362                    "a32uname/a32gname/a8devmajor/a8devminor/a131prefix"; 
     1689                "a8checksum/a1typeflag/a100link/a6magic/a2version/" . 
     1690                "a32uname/a32gname/a8devmajor/a8devminor/a131prefix"; 
    13631691        } else { 
    13641692            $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" . 
    1365                    "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" . 
    1366                    "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix"; 
     1693                "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" . 
     1694                "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix"; 
    13671695        } 
    13681696        $v_data = unpack($fmt, $v_binary_data); 
     
    13781706 
    13791707            // ----- Look for last block (empty block) 
    1380             if (($v_checksum == 256) && ($v_header['checksum'] == 0)) 
     1708            if (($v_checksum == 256) && ($v_header['checksum'] == 0)) { 
    13811709                return true; 
    1382  
    1383             $this->_error('Invalid checksum for file "'.$v_data['filename'] 
    1384                           .'" : '.$v_checksum.' calculated, ' 
    1385                           .$v_header['checksum'].' expected'); 
     1710            } 
     1711 
     1712            $this->_error( 
     1713                'Invalid checksum for file "' . $v_data['filename'] 
     1714                . '" : ' . $v_checksum . ' calculated, ' 
     1715                . $v_header['checksum'] . ' expected' 
     1716            ); 
    13861717            return false; 
    13871718        } 
     
    13901721        $v_header['filename'] = $v_data['filename']; 
    13911722        if ($this->_maliciousFilename($v_header['filename'])) { 
    1392             $this->_error('Malicious .tar detected, file "' . $v_header['filename'] . 
    1393                 '" will not install in desired directory tree'); 
     1723            $this->_error( 
     1724                'Malicious .tar detected, file "' . $v_header['filename'] . 
     1725                '" will not install in desired directory tree' 
     1726            ); 
    13941727            return false; 
    13951728        } 
     
    14001733        $v_header['mtime'] = OctDec(trim($v_data['mtime'])); 
    14011734        if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { 
    1402           $v_header['size'] = 0; 
     1735            $v_header['size'] = 0; 
    14031736        } 
    14041737        $v_header['link'] = trim($v_data['link']); 
     
    14151748        return true; 
    14161749    } 
     1750 
    14171751    // }}} 
    14181752 
     
    14361770        return false; 
    14371771    } 
     1772 
    14381773    // }}} 
    14391774 
     
    14411776    function _readLongHeader(&$v_header) 
    14421777    { 
    1443       $v_filename = ''; 
    1444       $n = floor($v_header['size']/512); 
    1445       for ($i=0; $i<$n; $i++) { 
    1446         $v_content = $this->_readBlock(); 
    1447         $v_filename .= $v_content; 
    1448       } 
    1449       if (($v_header['size'] % 512) != 0) { 
    1450         $v_content = $this->_readBlock(); 
    1451         $v_filename .= trim($v_content); 
    1452       } 
    1453  
    1454       // ----- Read the next header 
    1455       $v_binary_data = $this->_readBlock(); 
    1456  
    1457       if (!$this->_readHeader($v_binary_data, $v_header)) 
    1458         return false; 
    1459  
    1460       $v_filename = trim($v_filename); 
    1461       $v_header['filename'] = $v_filename; 
     1778        $v_filename = ''; 
     1779        $n = floor($v_header['size'] / 512); 
     1780        for ($i = 0; $i < $n; $i++) { 
     1781            $v_content = $this->_readBlock(); 
     1782            $v_filename .= $v_content; 
     1783        } 
     1784        if (($v_header['size'] % 512) != 0) { 
     1785            $v_content = $this->_readBlock(); 
     1786            $v_filename .= trim($v_content); 
     1787        } 
     1788 
     1789        // ----- Read the next header 
     1790        $v_binary_data = $this->_readBlock(); 
     1791 
     1792        if (!$this->_readHeader($v_binary_data, $v_header)) { 
     1793            return false; 
     1794        } 
     1795 
     1796        $v_filename = trim($v_filename); 
     1797        $v_header['filename'] = $v_filename; 
    14621798        if ($this->_maliciousFilename($v_filename)) { 
    1463             $this->_error('Malicious .tar detected, file "' . $v_filename . 
    1464                 '" will not install in desired directory tree'); 
     1799            $this->_error( 
     1800                'Malicious .tar detected, file "' . $v_filename . 
     1801                '" will not install in desired directory tree' 
     1802            ); 
    14651803            return false; 
    1466       } 
    1467  
    1468       return true; 
    1469     } 
     1804        } 
     1805 
     1806        return true; 
     1807    } 
     1808 
    14701809    // }}} 
    14711810 
    14721811    // {{{ _extractInString() 
    14731812    /** 
    1474     * This method extract from the archive one file identified by $p_filename. 
    1475     * The return value is a string with the file content, or null on error. 
    1476     * 
    1477     * @param string $p_filename The path of the file to extract in a string. 
    1478     * 
    1479     * @return a string with the file content or null. 
    1480     * @access private 
    1481     */ 
     1813     * This method extract from the archive one file identified by $p_filename. 
     1814     * The return value is a string with the file content, or null on error. 
     1815     * 
     1816     * @param string $p_filename The path of the file to extract in a string. 
     1817     * 
     1818     * @return a string with the file content or null. 
     1819     * @access private 
     1820     */ 
    14821821    function _extractInString($p_filename) 
    14831822    { 
    14841823        $v_result_str = ""; 
    14851824 
    1486         While (strlen($v_binary_data = $this->_readBlock()) != 0) 
    1487         { 
    1488           if (!$this->_readHeader($v_binary_data, $v_header)) 
    1489             return null; 
    1490  
    1491           if ($v_header['filename'] == '') 
    1492             continue; 
    1493  
    1494           // ----- Look for long filename 
    1495           if ($v_header['typeflag'] == 'L') { 
    1496             if (!$this->_readLongHeader($v_header)) 
    1497               return null; 
    1498           } 
    1499  
    1500           if ($v_header['filename'] == $p_filename) { 
    1501               if ($v_header['typeflag'] == "5") { 
    1502                   $this->_error('Unable to extract in string a directory ' 
    1503                                 .'entry {'.$v_header['filename'].'}'); 
    1504                   return null; 
    1505               } else { 
    1506                   $n = floor($v_header['size']/512); 
    1507                   for ($i=0; $i<$n; $i++) { 
    1508                       $v_result_str .= $this->_readBlock(); 
    1509                   } 
    1510                   if (($v_header['size'] % 512) != 0) { 
    1511                       $v_content = $this->_readBlock(); 
    1512                       $v_result_str .= substr($v_content, 0, 
    1513                                               ($v_header['size'] % 512)); 
    1514                   } 
    1515                   return $v_result_str; 
    1516               } 
    1517           } else { 
    1518               $this->_jumpBlock(ceil(($v_header['size']/512))); 
    1519           } 
     1825        While (strlen($v_binary_data = $this->_readBlock()) != 0) { 
     1826            if (!$this->_readHeader($v_binary_data, $v_header)) { 
     1827                return null; 
     1828            } 
     1829 
     1830            if ($v_header['filename'] == '') { 
     1831                continue; 
     1832            } 
     1833 
     1834            // ----- Look for long filename 
     1835            if ($v_header['typeflag'] == 'L') { 
     1836                if (!$this->_readLongHeader($v_header)) { 
     1837                    return null; 
     1838                } 
     1839            } 
     1840 
     1841            if ($v_header['filename'] == $p_filename) { 
     1842                if ($v_header['typeflag'] == "5") { 
     1843                    $this->_error( 
     1844                        'Unable to extract in string a directory ' 
     1845                        . 'entry {' . $v_header['filename'] . '}' 
     1846                    ); 
     1847                    return null; 
     1848                } else { 
     1849                    $n = floor($v_header['size'] / 512); 
     1850                    for ($i = 0; $i < $n; $i++) { 
     1851                        $v_result_str .= $this->_readBlock(); 
     1852                    } 
     1853                    if (($v_header['size'] % 512) != 0) { 
     1854                        $v_content = $this->_readBlock(); 
     1855                        $v_result_str .= substr( 
     1856                            $v_content, 
     1857                            0, 
     1858                            ($v_header['size'] % 512) 
     1859                        ); 
     1860                    } 
     1861                    return $v_result_str; 
     1862                } 
     1863            } else { 
     1864                $this->_jumpBlock(ceil(($v_header['size'] / 512))); 
     1865            } 
    15201866        } 
    15211867 
    15221868        return null; 
    15231869    } 
     1870 
    15241871    // }}} 
    15251872 
    15261873    // {{{ _extractList() 
    1527     function _extractList($p_path, &$p_list_detail, $p_mode, 
    1528                           $p_file_list, $p_remove_path, $p_preserve=false) 
    1529     { 
    1530     $v_result=true; 
    1531     $v_nb = 0; 
    1532     $v_extract_all = true; 
    1533     $v_listing = false; 
    1534  
    1535     $p_path = $this->_translateWinPath($p_path, false); 
    1536     if ($p_path == '' || (substr($p_path, 0, 1) != '/' 
    1537         && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) { 
    1538       $p_path = "./".$p_path; 
    1539     } 
    1540     $p_remove_path = $this->_translateWinPath($p_remove_path); 
    1541  
    1542     // ----- Look for path to remove format (should end by /) 
    1543     if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) 
    1544       $p_remove_path .= '/'; 
    1545     $p_remove_path_size = strlen($p_remove_path); 
    1546  
    1547     switch ($p_mode) { 
    1548       case "complete" : 
     1874    function _extractList( 
     1875        $p_path, 
     1876        &$p_list_detail, 
     1877        $p_mode, 
     1878        $p_file_list, 
     1879        $p_remove_path, 
     1880        $p_preserve = false 
     1881    ) { 
     1882        $v_result = true; 
     1883        $v_nb = 0; 
    15491884        $v_extract_all = true; 
    15501885        $v_listing = false; 
    1551       break; 
    1552       case "partial" : 
    1553           $v_extract_all = false; 
    1554           $v_listing = false; 
    1555       break; 
    1556       case "list" : 
    1557           $v_extract_all = false; 
    1558           $v_listing = true; 
    1559       break; 
    1560       default : 
    1561         $this->_error('Invalid extract mode ('.$p_mode.')'); 
    1562         return false; 
    1563     } 
    1564  
    1565     clearstatcache(); 
    1566  
    1567     while (strlen($v_binary_data = $this->_readBlock()) != 0) 
    1568     { 
    1569       $v_extract_file = FALSE; 
    1570       $v_extraction_stopped = 0; 
    1571  
    1572       if (!$this->_readHeader($v_binary_data, $v_header)) 
    1573         return false; 
    1574  
    1575       if ($v_header['filename'] == '') { 
    1576         continue; 
    1577       } 
    1578  
    1579       // ----- Look for long filename 
    1580       if ($v_header['typeflag'] == 'L') { 
    1581         if (!$this->_readLongHeader($v_header)) 
    1582           return false; 
    1583       } 
    1584  
    1585       if ((!$v_extract_all) && (is_array($p_file_list))) { 
    1586         // ----- By default no unzip if the file is not found 
    1587         $v_extract_file = false; 
    1588  
    1589         for ($i=0; $i<sizeof($p_file_list); $i++) { 
    1590           // ----- Look if it is a directory 
    1591           if (substr($p_file_list[$i], -1) == '/') { 
    1592             // ----- Look if the directory is in the filename path 
    1593             if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) 
    1594                 && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) 
    1595                     == $p_file_list[$i])) { 
    1596               $v_extract_file = true; 
    1597               break; 
    1598             } 
    1599           } 
    1600  
    1601           // ----- It is a file, so compare the file names 
    1602           elseif ($p_file_list[$i] == $v_header['filename']) { 
    1603             $v_extract_file = true; 
    1604             break; 
    1605           } 
    1606         } 
    1607       } else { 
    1608         $v_extract_file = true; 
    1609       } 
    1610  
    1611       // ----- Look if this file need to be extracted 
    1612       if (($v_extract_file) && (!$v_listing)) 
    1613       { 
    1614         if (($p_remove_path != '') 
    1615             && (substr($v_header['filename'].'/', 0, $p_remove_path_size) 
    1616                 == $p_remove_path)) { 
    1617           $v_header['filename'] = substr($v_header['filename'], 
    1618                                          $p_remove_path_size); 
    1619           if( $v_header['filename'] == '' ){ 
    1620             continue; 
    1621           } 
    1622         } 
    1623         if (($p_path != './') && ($p_path != '/')) { 
    1624           while (substr($p_path, -1) == '/') 
    1625             $p_path = substr($p_path, 0, strlen($p_path)-1); 
    1626  
    1627           if (substr($v_header['filename'], 0, 1) == '/') 
    1628               $v_header['filename'] = $p_path.$v_header['filename']; 
    1629           else 
    1630             $v_header['filename'] = $p_path.'/'.$v_header['filename']; 
    1631         } 
    1632         if (file_exists($v_header['filename'])) { 
    1633           if (   (@is_dir($v_header['filename'])) 
    1634               && ($v_header['typeflag'] == '')) { 
    1635             $this->_error('File '.$v_header['filename'] 
    1636                           .' already exists as a directory'); 
    1637             return false; 
    1638           } 
    1639           if (   ($this->_isArchive($v_header['filename'])) 
    1640               && ($v_header['typeflag'] == "5")) { 
    1641             $this->_error('Directory '.$v_header['filename'] 
    1642                           .' already exists as a file'); 
    1643             return false; 
    1644           } 
    1645           if (!is_writeable($v_header['filename'])) { 
    1646             $this->_error('File '.$v_header['filename'] 
    1647                           .' already exists and is write protected'); 
    1648             return false; 
    1649           } 
    1650           if (filemtime($v_header['filename']) > $v_header['mtime']) { 
    1651             // To be completed : An error or silent no replace ? 
    1652           } 
    1653         } 
    1654  
    1655         // ----- Check the directory availability and create it if necessary 
    1656         elseif (($v_result 
    1657                  = $this->_dirCheck(($v_header['typeflag'] == "5" 
    1658                                     ?$v_header['filename'] 
    1659                                     :dirname($v_header['filename'])))) != 1) { 
    1660             $this->_error('Unable to create path for '.$v_header['filename']); 
    1661             return false; 
    1662         } 
    1663  
    1664         if ($v_extract_file) { 
    1665           if ($v_header['typeflag'] == "5") { 
    1666             if (!@file_exists($v_header['filename'])) { 
    1667                 if (!@mkdir($v_header['filename'], 0777)) { 
    1668                     $this->_error('Unable to create directory {' 
    1669                                   .$v_header['filename'].'}'); 
     1886 
     1887        $p_path = $this->_translateWinPath($p_path, false); 
     1888        if ($p_path == '' || (substr($p_path, 0, 1) != '/' 
     1889                && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':')) 
     1890        ) { 
     1891            $p_path = "./" . $p_path; 
     1892        } 
     1893        $p_remove_path = $this->_translateWinPath($p_remove_path); 
     1894 
     1895        // ----- Look for path to remove format (should end by /) 
     1896        if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) { 
     1897            $p_remove_path .= '/'; 
     1898        } 
     1899        $p_remove_path_size = strlen($p_remove_path); 
     1900 
     1901        switch ($p_mode) { 
     1902            case "complete" : 
     1903                $v_extract_all = true; 
     1904                $v_listing = false; 
     1905                break; 
     1906            case "partial" : 
     1907                $v_extract_all = false; 
     1908                $v_listing = false; 
     1909                break; 
     1910            case "list" : 
     1911                $v_extract_all = false; 
     1912                $v_listing = true; 
     1913                break; 
     1914            default : 
     1915                $this->_error('Invalid extract mode (' . $p_mode . ')'); 
     1916                return false; 
     1917        } 
     1918 
     1919        clearstatcache(); 
     1920 
     1921        while (strlen($v_binary_data = $this->_readBlock()) != 0) { 
     1922            $v_extract_file = false; 
     1923            $v_extraction_stopped = 0; 
     1924 
     1925            if (!$this->_readHeader($v_binary_data, $v_header)) { 
     1926                return false; 
     1927            } 
     1928 
     1929            if ($v_header['filename'] == '') { 
     1930                continue; 
     1931            } 
     1932 
     1933            // ----- Look for long filename 
     1934            if ($v_header['typeflag'] == 'L') { 
     1935                if (!$this->_readLongHeader($v_header)) { 
    16701936                    return false; 
    16711937                } 
    16721938            } 
    1673           } elseif ($v_header['typeflag'] == "2") { 
    1674               if (@file_exists($v_header['filename'])) { 
    1675                   @unlink($v_header['filename']); 
    1676               } 
    1677               if (!@symlink($v_header['link'], $v_header['filename'])) { 
    1678                   $this->_error('Unable to extract symbolic link {' 
    1679                                 .$v_header['filename'].'}'); 
    1680                   return false; 
    1681               } 
    1682           } else { 
    1683               if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { 
    1684                   $this->_error('Error while opening {'.$v_header['filename'] 
    1685                                 .'} in write binary mode'); 
    1686                   return false; 
    1687               } else { 
    1688                   $n = floor($v_header['size']/512); 
    1689                   for ($i=0; $i<$n; $i++) { 
    1690                       $v_content = $this->_readBlock(); 
    1691                       fwrite($v_dest_file, $v_content, 512); 
    1692                   } 
    1693             if (($v_header['size'] % 512) != 0) { 
    1694               $v_content = $this->_readBlock(); 
    1695               fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); 
    1696             } 
    1697  
    1698             @fclose($v_dest_file); 
    1699              
    1700             if ($p_preserve) { 
    1701                 @chown($v_header['filename'], $v_header['uid']); 
    1702                 @chgrp($v_header['filename'], $v_header['gid']); 
    1703             } 
    1704  
    1705             // ----- Change the file mode, mtime 
    1706             @touch($v_header['filename'], $v_header['mtime']); 
    1707             if ($v_header['mode'] & 0111) { 
    1708                 // make file executable, obey umask 
    1709                 $mode = fileperms($v_header['filename']) | (~umask() & 0111); 
    1710                 @chmod($v_header['filename'], $mode); 
    1711             } 
    1712           } 
    1713  
    1714           // ----- Check the file size 
    1715           clearstatcache(); 
    1716           if (!is_file($v_header['filename'])) { 
    1717               $this->_error('Extracted file '.$v_header['filename'] 
    1718                             .'does not exist. Archive may be corrupted.'); 
    1719               return false; 
    1720           } 
    1721            
    1722           $filesize = filesize($v_header['filename']); 
    1723           if ($filesize != $v_header['size']) { 
    1724               $this->_error('Extracted file '.$v_header['filename'] 
    1725                             .' does not have the correct file size \'' 
    1726                             .$filesize 
    1727                             .'\' ('.$v_header['size'] 
    1728                             .' expected). Archive may be corrupted.'); 
    1729               return false; 
    1730           } 
    1731           } 
    1732         } else { 
    1733           $this->_jumpBlock(ceil(($v_header['size']/512))); 
    1734         } 
    1735       } else { 
    1736           $this->_jumpBlock(ceil(($v_header['size']/512))); 
    1737       } 
    1738  
    1739       /* TBC : Seems to be unused ... 
    1740       if ($this->_compress) 
    1741         $v_end_of_file = @gzeof($this->_file); 
    1742       else 
    1743         $v_end_of_file = @feof($this->_file); 
    1744         */ 
    1745  
    1746       if ($v_listing || $v_extract_file || $v_extraction_stopped) { 
    1747         // ----- Log extracted files 
    1748         if (($v_file_dir = dirname($v_header['filename'])) 
    1749             == $v_header['filename']) 
    1750           $v_file_dir = ''; 
    1751         if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) 
    1752           $v_file_dir = '/'; 
    1753  
    1754         $p_list_detail[$v_nb++] = $v_header; 
    1755         if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) { 
    1756             return true; 
    1757         } 
    1758       } 
    1759     } 
     1939 
     1940            // ignore extended / pax headers 
     1941            if ($v_header['typeflag'] == 'x' || $v_header['typeflag'] == 'g') { 
     1942                $this->_jumpBlock(ceil(($v_header['size'] / 512))); 
     1943                continue; 
     1944            } 
     1945 
     1946            if ((!$v_extract_all) && (is_array($p_file_list))) { 
     1947                // ----- By default no unzip if the file is not found 
     1948                $v_extract_file = false; 
     1949 
     1950                for ($i = 0; $i < sizeof($p_file_list); $i++) { 
     1951                    // ----- Look if it is a directory 
     1952                    if (substr($p_file_list[$i], -1) == '/') { 
     1953                        // ----- Look if the directory is in the filename path 
     1954                        if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) 
     1955                            && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) 
     1956                                == $p_file_list[$i]) 
     1957                        ) { 
     1958                            $v_extract_file = true; 
     1959                            break; 
     1960                        } 
     1961                    } // ----- It is a file, so compare the file names 
     1962                    elseif ($p_file_list[$i] == $v_header['filename']) { 
     1963                        $v_extract_file = true; 
     1964                        break; 
     1965                    } 
     1966                } 
     1967            } else { 
     1968                $v_extract_file = true; 
     1969            } 
     1970 
     1971            // ----- Look if this file need to be extracted 
     1972            if (($v_extract_file) && (!$v_listing)) { 
     1973                if (($p_remove_path != '') 
     1974                    && (substr($v_header['filename'] . '/', 0, $p_remove_path_size) 
     1975                        == $p_remove_path) 
     1976                ) { 
     1977                    $v_header['filename'] = substr( 
     1978                        $v_header['filename'], 
     1979                        $p_remove_path_size 
     1980                    ); 
     1981                    if ($v_header['filename'] == '') { 
     1982                        continue; 
     1983                    } 
     1984                } 
     1985                if (($p_path != './') && ($p_path != '/')) { 
     1986                    while (substr($p_path, -1) == '/') { 
     1987                        $p_path = substr($p_path, 0, strlen($p_path) - 1); 
     1988                    } 
     1989 
     1990                    if (substr($v_header['filename'], 0, 1) == '/') { 
     1991                        $v_header['filename'] = $p_path . $v_header['filename']; 
     1992                    } else { 
     1993                        $v_header['filename'] = $p_path . '/' . $v_header['filename']; 
     1994                    } 
     1995                } 
     1996                if (file_exists($v_header['filename'])) { 
     1997                    if ((@is_dir($v_header['filename'])) 
     1998                        && ($v_header['typeflag'] == '') 
     1999                    ) { 
     2000                        $this->_error( 
     2001                            'File ' . $v_header['filename'] 
     2002                            . ' already exists as a directory' 
     2003                        ); 
     2004                        return false; 
     2005                    } 
     2006                    if (($this->_isArchive($v_header['filename'])) 
     2007                        && ($v_header['typeflag'] == "5") 
     2008                    ) { 
     2009                        $this->_error( 
     2010                            'Directory ' . $v_header['filename'] 
     2011                            . ' already exists as a file' 
     2012                        ); 
     2013                        return false; 
     2014                    } 
     2015                    if (!is_writeable($v_header['filename'])) { 
     2016                        $this->_error( 
     2017                            'File ' . $v_header['filename'] 
     2018                            . ' already exists and is write protected' 
     2019                        ); 
     2020                        return false; 
     2021                    } 
     2022                    if (filemtime($v_header['filename']) > $v_header['mtime']) { 
     2023                        // To be completed : An error or silent no replace ? 
     2024                    } 
     2025                } // ----- Check the directory availability and create it if necessary 
     2026                elseif (($v_result 
     2027                        = $this->_dirCheck( 
     2028                        ($v_header['typeflag'] == "5" 
     2029                            ? $v_header['filename'] 
     2030                            : dirname($v_header['filename'])) 
     2031                    )) != 1 
     2032                ) { 
     2033                    $this->_error('Unable to create path for ' . $v_header['filename']); 
     2034                    return false; 
     2035                } 
     2036 
     2037                if ($v_extract_file) { 
     2038                    if ($v_header['typeflag'] == "5") { 
     2039                        if (!@file_exists($v_header['filename'])) { 
     2040                            if (!@mkdir($v_header['filename'], 0777)) { 
     2041                                $this->_error( 
     2042                                    'Unable to create directory {' 
     2043                                    . $v_header['filename'] . '}' 
     2044                                ); 
     2045                                return false; 
     2046                            } 
     2047                        } 
     2048                    } elseif ($v_header['typeflag'] == "2") { 
     2049                        if (@file_exists($v_header['filename'])) { 
     2050                            @unlink($v_header['filename']); 
     2051                        } 
     2052                        if (!@symlink($v_header['link'], $v_header['filename'])) { 
     2053                            $this->_error( 
     2054                                'Unable to extract symbolic link {' 
     2055                                . $v_header['filename'] . '}' 
     2056                            ); 
     2057                            return false; 
     2058                        } 
     2059                    } else { 
     2060                        if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { 
     2061                            $this->_error( 
     2062                                'Error while opening {' . $v_header['filename'] 
     2063                                . '} in write binary mode' 
     2064                            ); 
     2065                            return false; 
     2066                        } else { 
     2067                            $n = floor($v_header['size'] / 512); 
     2068                            for ($i = 0; $i < $n; $i++) { 
     2069                                $v_content = $this->_readBlock(); 
     2070                                fwrite($v_dest_file, $v_content, 512); 
     2071                            } 
     2072                            if (($v_header['size'] % 512) != 0) { 
     2073                                $v_content = $this->_readBlock(); 
     2074                                fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); 
     2075                            } 
     2076 
     2077                            @fclose($v_dest_file); 
     2078 
     2079                            if ($p_preserve) { 
     2080                                @chown($v_header['filename'], $v_header['uid']); 
     2081                                @chgrp($v_header['filename'], $v_header['gid']); 
     2082                            } 
     2083 
     2084                            // ----- Change the file mode, mtime 
     2085                            @touch($v_header['filename'], $v_header['mtime']); 
     2086                            if ($v_header['mode'] & 0111) { 
     2087                                // make file executable, obey umask 
     2088                                $mode = fileperms($v_header['filename']) | (~umask() & 0111); 
     2089                                @chmod($v_header['filename'], $mode); 
     2090                            } 
     2091                        } 
     2092 
     2093                        // ----- Check the file size 
     2094                        clearstatcache(); 
     2095                        if (!is_file($v_header['filename'])) { 
     2096                            $this->_error( 
     2097                                'Extracted file ' . $v_header['filename'] 
     2098                                . 'does not exist. Archive may be corrupted.' 
     2099                            ); 
     2100                            return false; 
     2101                        } 
     2102 
     2103                        $filesize = filesize($v_header['filename']); 
     2104                        if ($filesize != $v_header['size']) { 
     2105                            $this->_error( 
     2106                                'Extracted file ' . $v_header['filename'] 
     2107                                . ' does not have the correct file size \'' 
     2108                                . $filesize 
     2109                                . '\' (' . $v_header['size'] 
     2110                                . ' expected). Archive may be corrupted.' 
     2111                            ); 
     2112                            return false; 
     2113                        } 
     2114                    } 
     2115                } else { 
     2116                    $this->_jumpBlock(ceil(($v_header['size'] / 512))); 
     2117                } 
     2118            } else { 
     2119                $this->_jumpBlock(ceil(($v_header['size'] / 512))); 
     2120            } 
     2121 
     2122            /* TBC : Seems to be unused ... 
     2123            if ($this->_compress) 
     2124              $v_end_of_file = @gzeof($this->_file); 
     2125            else 
     2126              $v_end_of_file = @feof($this->_file); 
     2127              */ 
     2128 
     2129            if ($v_listing || $v_extract_file || $v_extraction_stopped) { 
     2130                // ----- Log extracted files 
     2131                if (($v_file_dir = dirname($v_header['filename'])) 
     2132                    == $v_header['filename'] 
     2133                ) { 
     2134                    $v_file_dir = ''; 
     2135                } 
     2136                if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) { 
     2137                    $v_file_dir = '/'; 
     2138                } 
     2139 
     2140                $p_list_detail[$v_nb++] = $v_header; 
     2141                if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) { 
     2142                    return true; 
     2143                } 
     2144            } 
     2145        } 
    17602146 
    17612147        return true; 
    17622148    } 
     2149 
    17632150    // }}} 
    17642151 
     
    17662153    function _openAppend() 
    17672154    { 
    1768         if (filesize($this->_tarname) == 0) 
    1769           return $this->_openWrite(); 
     2155        if (filesize($this->_tarname) == 0) { 
     2156            return $this->_openWrite(); 
     2157        } 
    17702158 
    17712159        if ($this->_compress) { 
    17722160            $this->_close(); 
    17732161 
    1774             if (!@rename($this->_tarname, $this->_tarname.".tmp")) { 
    1775                 $this->_error('Error while renaming \''.$this->_tarname 
    1776                               .'\' to temporary file \''.$this->_tarname 
    1777                               .'.tmp\''); 
     2162            if (!@rename($this->_tarname, $this->_tarname . ".tmp")) { 
     2163                $this->_error( 
     2164                    'Error while renaming \'' . $this->_tarname 
     2165                    . '\' to temporary file \'' . $this->_tarname 
     2166                    . '.tmp\'' 
     2167                ); 
    17782168                return false; 
    17792169            } 
    17802170 
    1781             if ($this->_compress_type == 'gz') 
    1782                 $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb"); 
    1783             elseif ($this->_compress_type == 'bz2') 
    1784                 $v_temp_tar = @bzopen($this->_tarname.".tmp", "r"); 
     2171            if ($this->_compress_type == 'gz') { 
     2172                $v_temp_tar = @gzopen($this->_tarname . ".tmp", "rb"); 
     2173            } elseif ($this->_compress_type == 'bz2') { 
     2174                $v_temp_tar = @bzopen($this->_tarname . ".tmp", "r"); 
     2175            } elseif ($this->_compress_type == 'lzma2') { 
     2176                $v_temp_tar = @xzopen($this->_tarname . ".tmp", "r"); 
     2177            } 
     2178 
    17852179 
    17862180            if ($v_temp_tar == 0) { 
    1787                 $this->_error('Unable to open file \''.$this->_tarname 
    1788                               .'.tmp\' in binary read mode'); 
    1789                 @rename($this->_tarname.".tmp", $this->_tarname); 
     2181                $this->_error( 
     2182                    'Unable to open file \'' . $this->_tarname 
     2183                    . '.tmp\' in binary read mode' 
     2184                ); 
     2185                @rename($this->_tarname . ".tmp", $this->_tarname); 
    17902186                return false; 
    17912187            } 
    17922188 
    17932189            if (!$this->_openWrite()) { 
    1794                 @rename($this->_tarname.".tmp", $this->_tarname); 
     2190                @rename($this->_tarname . ".tmp", $this->_tarname); 
    17952191                return false; 
    17962192            } 
     
    17982194            if ($this->_compress_type == 'gz') { 
    17992195                $end_blocks = 0; 
    1800                  
     2196 
    18012197                while (!@gzeof($v_temp_tar)) { 
    18022198                    $v_buffer = @gzread($v_temp_tar, 512); 
     
    18172213 
    18182214                @gzclose($v_temp_tar); 
    1819             } 
    1820             elseif ($this->_compress_type == 'bz2') { 
     2215            } elseif ($this->_compress_type == 'bz2') { 
    18212216                $end_blocks = 0; 
    1822                  
     2217 
    18232218                while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) { 
    18242219                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { 
     
    18382233 
    18392234                @bzclose($v_temp_tar); 
    1840             } 
    1841  
    1842             if (!@unlink($this->_tarname.".tmp")) { 
    1843                 $this->_error('Error while deleting temporary file \'' 
    1844                               .$this->_tarname.'.tmp\''); 
     2235            } elseif ($this->_compress_type == 'lzma2') { 
     2236                $end_blocks = 0; 
     2237 
     2238                while (strlen($v_buffer = @xzread($v_temp_tar, 512)) > 0) { 
     2239                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { 
     2240                        $end_blocks++; 
     2241                        // do not copy end blocks, we will re-make them 
     2242                        // after appending 
     2243                        continue; 
     2244                    } elseif ($end_blocks > 0) { 
     2245                        for ($i = 0; $i < $end_blocks; $i++) { 
     2246                            $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); 
     2247                        } 
     2248                        $end_blocks = 0; 
     2249                    } 
     2250                    $v_binary_data = pack("a512", $v_buffer); 
     2251                    $this->_writeBlock($v_binary_data); 
     2252                } 
     2253 
     2254                @xzclose($v_temp_tar); 
     2255            } 
     2256 
     2257            if (!@unlink($this->_tarname . ".tmp")) { 
     2258                $this->_error( 
     2259                    'Error while deleting temporary file \'' 
     2260                    . $this->_tarname . '.tmp\'' 
     2261                ); 
    18452262            } 
    18462263 
    18472264        } else { 
    18482265            // ----- For not compressed tar, just add files before the last 
    1849             //       one or two 512 bytes block 
    1850             if (!$this->_openReadWrite()) 
    1851                return false; 
     2266            //       one or two 512 bytes block 
     2267            if (!$this->_openReadWrite()) { 
     2268                return false; 
     2269            } 
    18522270 
    18532271            clearstatcache(); 
     
    18602278            if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { 
    18612279                fseek($this->_file, $v_size - 1024); 
    1862             } 
    1863             elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { 
     2280            } elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { 
    18642281                fseek($this->_file, $v_size - 512); 
    18652282            } 
     
    18682285        return true; 
    18692286    } 
     2287 
    18702288    // }}} 
    18712289 
    18722290    // {{{ _append() 
    1873     function _append($p_filelist, $p_add_dir='', $p_remove_dir='') 
    1874     { 
    1875         if (!$this->_openAppend()) 
     2291    function _append($p_filelist, $p_add_dir = '', $p_remove_dir = '') 
     2292    { 
     2293        if (!$this->_openAppend()) { 
    18762294            return false; 
    1877  
    1878         if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) 
    1879            $this->_writeFooter(); 
     2295        } 
     2296 
     2297        if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) { 
     2298            $this->_writeFooter(); 
     2299        } 
    18802300 
    18812301        $this->_close(); 
     
    18832303        return true; 
    18842304    } 
     2305 
    18852306    // }}} 
    18862307 
     
    18982319    { 
    18992320        clearstatcache(); 
    1900         if ((@is_dir($p_dir)) || ($p_dir == '')) 
     2321        if ((@is_dir($p_dir)) || ($p_dir == '')) { 
    19012322            return true; 
     2323        } 
    19022324 
    19032325        $p_parent_dir = dirname($p_dir); 
     
    19052327        if (($p_parent_dir != $p_dir) && 
    19062328            ($p_parent_dir != '') && 
    1907             (!$this->_dirCheck($p_parent_dir))) 
    1908              return false; 
     2329            (!$this->_dirCheck($p_parent_dir)) 
     2330        ) { 
     2331            return false; 
     2332        } 
    19092333 
    19102334        if (!@mkdir($p_dir, 0777)) { 
     
    19412365 
    19422366            // ----- Study directories from last to first 
    1943             for ($i=sizeof($v_list)-1; $i>=0; $i--) { 
     2367            for ($i = sizeof($v_list) - 1; $i >= 0; $i--) { 
    19442368                // ----- Look for current path 
    19452369                if ($v_list[$i] == ".") { 
    19462370                    // ----- Ignore this directory 
    19472371                    // Should be the first $i=0, but no check is done 
    1948                 } 
    1949                 else if ($v_list[$i] == "..") { 
    1950                     // ----- Ignore it and ignore the $i-1 
    1951                     $i--; 
    1952                 } 
    1953                 else if (   ($v_list[$i] == '') 
    1954                          && ($i!=(sizeof($v_list)-1)) 
    1955                          && ($i!=0)) { 
    1956                     // ----- Ignore only the double '//' in path, 
    1957                     // but not the first and last / 
    19582372                } else { 
    1959                     $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/' 
    1960                                 .$v_result:''); 
    1961                 } 
    1962             } 
    1963         } 
    1964          
     2373                    if ($v_list[$i] == "..") { 
     2374                        // ----- Ignore it and ignore the $i-1 
     2375                        $i--; 
     2376                    } else { 
     2377                        if (($v_list[$i] == '') 
     2378                            && ($i != (sizeof($v_list) - 1)) 
     2379                            && ($i != 0) 
     2380                        ) { 
     2381                            // ----- Ignore only the double '//' in path, 
     2382                            // but not the first and last / 
     2383                        } else { 
     2384                            $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? '/' 
     2385                                    . $v_result : ''); 
     2386                        } 
     2387                    } 
     2388                } 
     2389            } 
     2390        } 
     2391 
    19652392        if (defined('OS_WINDOWS') && OS_WINDOWS) { 
    19662393            $v_result = strtr($v_result, '\\', '/'); 
    19672394        } 
    1968          
     2395 
    19692396        return $v_result; 
    19702397    } 
     
    19732400 
    19742401    // {{{ _translateWinPath() 
    1975     function _translateWinPath($p_path, $p_remove_disk_letter=true) 
    1976     { 
    1977       if (defined('OS_WINDOWS') && OS_WINDOWS) { 
    1978           // ----- Look for potential disk letter 
    1979           if (   ($p_remove_disk_letter) 
    1980               && (($v_position = strpos($p_path, ':')) != false)) { 
    1981               $p_path = substr($p_path, $v_position+1); 
    1982           } 
    1983           // ----- Change potential windows directory separator 
    1984           if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { 
    1985               $p_path = strtr($p_path, '\\', '/'); 
    1986           } 
    1987       } 
    1988       return $p_path; 
     2402    function _translateWinPath($p_path, $p_remove_disk_letter = true) 
     2403    { 
     2404        if (defined('OS_WINDOWS') && OS_WINDOWS) { 
     2405            // ----- Look for potential disk letter 
     2406            if (($p_remove_disk_letter) 
     2407                && (($v_position = strpos($p_path, ':')) != false) 
     2408            ) { 
     2409                $p_path = substr($p_path, $v_position + 1); 
     2410            } 
     2411            // ----- Change potential windows directory separator 
     2412            if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) { 
     2413                $p_path = strtr($p_path, '\\', '/'); 
     2414            } 
     2415        } 
     2416        return $p_path; 
    19892417    } 
    19902418    // }}} 
    19912419 
    19922420} 
     2421 
    19932422?> 
  • branches/version-2_13-dev/data/module/Cache/Lite.php

    r22587 r23600  
    248248     */ 
    249249    var $_errorHandlingAPIBreak = false; 
     250     
     251    var $_hashedDirectoryGroup = NULL; 
     252     
     253    var $_cacheFileMode = NULL; 
     254     
     255    var $_cacheFileGroup = NULL; 
    250256     
    251257    // --- Public methods --- 
     
    273279    *     'hashedDirectoryUmask' => umask for hashed directory structure (int), 
    274280    *     'errorHandlingAPIBreak' => API break for better error handling ? (boolean) 
     281    *     'hashedDirectoryGroup' => group of hashed directory structure (int | string) (see function chgrp) 
     282    *     'cacheFileMode' => filesystem mode of newly created cache files (int) 
     283    *     'cacheFileGroup' => group of newly created cache files (int | string) (see function chgrp) 
    275284    * ); 
    276285    *  
     
    307316    function setOption($name, $value)  
    308317    { 
    309         $availableOptions = array('errorHandlingAPIBreak', 'hashedDirectoryUmask', 'hashedDirectoryLevel', 'automaticCleaningFactor', 'automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode'); 
     318        $availableOptions = array('errorHandlingAPIBreak', 'hashedDirectoryUmask', 'hashedDirectoryLevel', 'automaticCleaningFactor', 'automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode', 'hashedDirectoryGroup', 'cacheFileMode', 'cacheFileGroup'); 
    310319        if (in_array($name, $availableOptions)) { 
    311320            $property = '_'.$name; 
     
    666675        return $result; 
    667676    } 
    668        
     677 
     678    /** 
     679    * Touch the cache file while are recreating it to avoid 
     680    * launch this task more then once when necessary 
     681    * When the cache recreated and Added in Cache Memory 
     682    * @return void 
     683    * @access private 
     684    */ 
     685    function _touchCacheFile(){ 
     686        if (file_exists($this->_file)) { 
     687            @touch($this->_file); 
     688        } 
     689    } 
    669690    /** 
    670691    * Add some date in the memory caching array 
     
    675696    function _memoryCacheAdd($data) 
    676697    { 
     698        $this->_touchCacheFile(); 
    677699        $this->_memoryCachingArray[$this->_file] = $data; 
    678700        if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) { 
     
    776798                $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/'; 
    777799                if (!(@is_dir($root))) { 
    778                     @mkdir($root, $this->_hashedDirectoryUmask); 
     800                    if (@mkdir($root)) 
     801                    { 
     802                        @chmod($root, $this->_hashedDirectoryUmask); 
     803                        if (! is_null($this->_hashedDirectoryGroup)) 
     804                            @chgrp($root, $this->_hashedDirectoryGroup); 
     805                    } 
    779806                } 
    780807            } 
    781808        } 
     809        // if both _cacheFileMode and _cacheFileGroup is null, then we don't need to call 
     810        // file_exists (see below: if ($is_newfile) ...) 
     811        $is_newfile = (! is_null($this->_cacheFileMode) || !is_null($this->_cacheFileGroup))  
     812            && ! @file_exists($this->_file); 
    782813        $fp = @fopen($this->_file, "wb"); 
    783814        if ($fp) { 
    784815            if ($this->_fileLocking) @flock($fp, LOCK_EX); 
     816            if ($is_newfile) 
     817            { 
     818                if (! is_null($this->_cacheFileMode)) 
     819                    @chmod($this->_file, $this->_cacheFileMode); 
     820                if (! is_null($this->_cacheFileGroup)) 
     821                    @chgrp($this->_file, $this->_cacheFileGroup); 
     822            } 
    785823            if ($this->_readControl) { 
    786824                @fwrite($fp, $this->_hash($data, $this->_readControlType), 32); 
  • branches/version-2_13-dev/data/module/Mobile/Detect.php

    • Property svn:executable set to *
    r23354 r23600  
    11<?php 
    22/** 
    3  * Mobile Detect Library 
    4  * ===================== 
     3 * Little piece of PHP to make Mobile_Detect auto-loadable in PSR-0 compatible PHP autoloaders like 
     4 * the Symfony Universal ClassLoader by Fabien Potencier. Since PSR-0 handles an underscore in 
     5 * classnames (on the filesystem) as a slash, "Mobile_Detect.php" autoloaders will try to convert 
     6 * the classname and path to "Mobile\Detect.php". This script will ensure autoloading with: 
     7 *  - Namespace:       Detection 
     8 *  - Classname:       MobileDetect 
     9 *  - Namespased:      \Detection\MobileDetect 
     10 *  - Autoload path:   ./namespaced 
     11 *  - Converted path:  ./namespaced/Detection/MobileDetect.php 
    512 * 
    6  * Motto: "Every business should have a mobile detection script to detect mobile readers" 
     13 * Don't forget to use MobileDetect (instead of Mobile_Detect) as class in code when autoloading. 
    714 * 
    8  * Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets). 
    9  * It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment. 
    10  * 
    11  * @author      Current authors: Serban Ghita <serbanghita@gmail.com>, Nick Ilyin <nick.ilyin@gmail.com> 
    12  *              Original author: Victor Stanciu <vic.stanciu@gmail.com> 
    13  * 
    14  * @license     Code and contributions have 'MIT License' 
    15  *              More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt 
    16  * 
    17  * @link        Homepage:     http://mobiledetect.net 
    18  *              GitHub Repo:  https://github.com/serbanghita/Mobile-Detect 
    19  *              Google Code:  http://code.google.com/p/php-mobile-detect/ 
    20  *              README:       https://github.com/serbanghita/Mobile-Detect/blob/master/README.md 
    21  *              HOWTO:        https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples 
    22  * 
    23  * @version     2.7.8 
     15 * Thanks to @WietseWind. 
     16 * For details please check: https://github.com/serbanghita/Mobile-Detect/pull/120 
    2417 */ 
    2518 
    26 class Mobile_Detect 
    27 { 
    28     /** 
    29      * Mobile detection type. 
    30      * 
    31      * @deprecated since version 2.6.9 
    32      */ 
    33     const DETECTION_TYPE_MOBILE     = 'mobile'; 
     19namespace Detection; 
     20require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'Mobile_Detect.php'; 
    3421 
    35     /** 
    36      * Extended detection type. 
    37      * 
    38      * @deprecated since version 2.6.9 
    39      */ 
    40     const DETECTION_TYPE_EXTENDED   = 'extended'; 
    41  
    42     /** 
    43      * A frequently used regular expression to extract version #s. 
    44      * 
    45      * @deprecated since version 2.6.9 
    46      */ 
    47     const VER                       = '([\w._\+]+)'; 
    48  
    49     /** 
    50      * Top-level device. 
    51      */ 
    52     const MOBILE_GRADE_A            = 'A'; 
    53  
    54     /** 
    55      * Mid-level device. 
    56      */ 
    57     const MOBILE_GRADE_B            = 'B'; 
    58  
    59     /** 
    60      * Low-level device. 
    61      */ 
    62     const MOBILE_GRADE_C            = 'C'; 
    63  
    64     /** 
    65      * Stores the version number of the current release. 
    66      */ 
    67     const VERSION                   = '2.7.8'; 
    68  
    69     /** 
    70      * A type for the version() method indicating a string return value. 
    71      */ 
    72     const VERSION_TYPE_STRING       = 'text'; 
    73  
    74     /** 
    75      * A type for the version() method indicating a float return value. 
    76      */ 
    77     const VERSION_TYPE_FLOAT        = 'float'; 
    78  
    79     /** 
    80      * The User-Agent HTTP header is stored in here. 
    81      * @var string 
    82      */ 
    83     protected $userAgent = null; 
    84  
    85     /** 
    86      * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE. 
    87      * @var array 
    88      */ 
    89     protected $httpHeaders = array(); 
    90  
    91     /** 
    92      * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED. 
    93      * 
    94      * @deprecated since version 2.6.9 
    95      * 
    96      * @var string 
    97      */ 
    98     protected $detectionType = self::DETECTION_TYPE_MOBILE; 
    99  
    100     /** 
    101      * HTTP headers that trigger the 'isMobile' detection 
    102      * to be true. 
    103      * 
    104      * @var array 
    105      */ 
    106     protected static $mobileHeaders = array( 
    107  
    108             'HTTP_ACCEPT'                  => array('matches' => array( 
    109                                                                         // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/ 
    110                                                                         'application/x-obml2d', 
    111                                                                         // BlackBerry devices. 
    112                                                                         'application/vnd.rim.html', 
    113                                                                         'text/vnd.wap.wml', 
    114                                                                         'application/vnd.wap.xhtml+xml' 
    115                                             )), 
    116             'HTTP_X_WAP_PROFILE'           => null, 
    117             'HTTP_X_WAP_CLIENTID'          => null, 
    118             'HTTP_WAP_CONNECTION'          => null, 
    119             'HTTP_PROFILE'                 => null, 
    120             // Reported by Opera on Nokia devices (eg. C3). 
    121             'HTTP_X_OPERAMINI_PHONE_UA'    => null, 
    122             'HTTP_X_NOKIA_IPADDRESS'       => null, 
    123             'HTTP_X_NOKIA_GATEWAY_ID'      => null, 
    124             'HTTP_X_ORANGE_ID'             => null, 
    125             'HTTP_X_VODAFONE_3GPDPCONTEXT' => null, 
    126             'HTTP_X_HUAWEI_USERID'         => null, 
    127             // Reported by Windows Smartphones. 
    128             'HTTP_UA_OS'                   => null, 
    129             // Reported by Verizon, Vodafone proxy system. 
    130             'HTTP_X_MOBILE_GATEWAY'        => null, 
    131             // Seend this on HTC Sensation. @ref: SensationXE_Beats_Z715e. 
    132             'HTTP_X_ATT_DEVICEID'          => null, 
    133             // Seen this on a HTC. 
    134             'HTTP_UA_CPU'                  => array('matches' => array('ARM')), 
    135     ); 
    136  
    137     /** 
    138      * List of mobile devices (phones). 
    139      * 
    140      * @var array 
    141      */ 
    142     protected static $phoneDevices = array( 
    143         'iPhone'        => '\biPhone.*Mobile|\biPod', // |\biTunes 
    144         'BlackBerry'    => 'BlackBerry|\bBB10\b|rim[0-9]+', 
    145         'HTC'           => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m', 
    146         'Nexus'         => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile', 
    147         // @todo: Is 'Dell Streak' a tablet or a phone? ;) 
    148         'Dell'          => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b', 
    149         'Motorola'      => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925', 
    150         'Samsung'       => 'Samsung|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262', 
    151         'LG'            => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802)', 
    152         'Sony'          => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i', 
    153         'Asus'          => 'Asus.*Galaxy|PadFone.*Mobile', 
    154         // @ref: http://www.micromaxinfo.com/mobiles/smartphones 
    155         // Added because the codes might conflict with Acer Tablets. 
    156         'Micromax'      => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b', 
    157         'Palm'          => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; @todo - complete the regex. 
    158         'Vertu'         => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;) 
    159         // @ref: http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH) 
    160         // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android. 
    161         'Pantech'       => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790', 
    162         // @ref: http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones. 
    163         'Fly'           => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250', 
    164         // Added simvalley mobile just for fun. They have some interesting devices. 
    165         // @ref: http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html 
    166         'SimValley'     => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b', 
    167         // @Tapatalk is a mobile app; @ref: http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039 
    168         'GenericPhone'  => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser' 
    169     ); 
    170  
    171     /** 
    172      * List of tablet devices. 
    173      * 
    174      * @var array 
    175      */ 
    176     protected static $tabletDevices = array( 
    177         'iPad'              => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic. 
    178         'NexusTablet'       => '^.*Android.*Nexus(((?:(?!Mobile))|(?:(\s(7|10).+))).)*$', 
    179         'SamsungTablet'     => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-I9205|GT-P5200|GT-P5210|SM-T311|SM-T310|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500', 
    180         // @reference: http://www.labnol.org/software/kindle-user-agent-string/20378/ 
    181         'Kindle'            => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE)\b', 
    182         // Only the Surface tablets with Windows RT are considered mobile. 
    183         // @ref: http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx 
    184         'SurfaceTablet'     => 'Windows NT [0-9.]+; ARM;', 
    185         // @ref: http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT 
    186         'HPTablet'          => 'HP Slate 7|HP ElitePad 900|hp-tablet|EliteBook.*Touch', 
    187         // @note: watch out for PadFone, see #132 
    188         'AsusTablet'        => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|TX201LA', 
    189         'BlackBerryTablet'  => 'PlayBook|RIM Tablet', 
    190         'HTCtablet'         => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200', 
    191         'MotorolaTablet'    => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617', 
    192         'NookTablet'        => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2', 
    193         // @ref: http://www.acer.ro/ac/ro/RO/content/drivers 
    194         // @ref: http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer) 
    195         // @ref: http://us.acer.com/ac/en/US/content/group/tablets 
    196         // @note: Can conflict with Micromax and Motorola phones codes. 
    197         'AcerTablet'        => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810)\b|W3-810|\bA3-A10\b', 
    198         // @ref: http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/ 
    199         // @ref: http://us.toshiba.com/tablets/tablet-finder 
    200         // @ref: http://www.toshiba.co.jp/regza/tablet/ 
    201         'ToshibaTablet'     => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO', 
    202         // @ref: http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html 
    203         'LGTablet'          => '\bL-06C|LG-V900|LG-V500|LG-V909\b', 
    204         'FujitsuTablet'     => 'Android.*\b(F-01D|F-05E|F-10D|M532|Q572)\b', 
    205         // Prestigio Tablets http://www.prestigio.com/support 
    206         'PrestigioTablet'   => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD', 
    207         // @ref: http://support.lenovo.com/en_GB/downloads/default.page?# 
    208         'LenovoTablet'      => 'IdeaTab|S2110|S6000|K3011|A3000|A1000|A2107|A2109|A1107|ThinkPad([ ]+)?Tablet', 
    209         // @ref: http://www.yarvik.com/en/matrix/tablets/ 
    210         'YarvikTablet'      => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b', 
    211         'MedionTablet'      => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB', 
    212         'ArnovaTablet'      => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT', 
    213         // http://www.intenso.de/kategorie_en.php?kategorie=33 
    214         // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate 
    215         'IntensoTablet'     => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab', 
    216         // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/ 
    217         'IRUTablet'         => 'M702pro', 
    218         'MegafonTablet'     => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b', 
    219         // @ref: http://www.e-boda.ro/tablete-pc.html 
    220         'EbodaTablet'       => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)', 
    221         // @ref: http://www.allview.ro/produse/droseries/lista-tablete-pc/ 
    222         'AllViewTablet'           => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)', 
    223         // @reference: http://wiki.archosfans.com/index.php?title=Main_Page 
    224         'ArchosTablet'      => '\b(101G9|80G9|A101IT)\b|Qilive 97R|ARCHOS 101G10', 
    225         // @ref: http://www.ainol.com/plugin.php?identifier=ainol&module=product 
    226         'AinolTablet'       => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark', 
    227         // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER 
    228         // @ref: Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser 
    229         // @ref: http://www.sony.jp/support/tablet/ 
    230         'SonyTablet'        => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201', 
    231         // @ref: db + http://www.cube-tablet.com/buy-products.html 
    232         'CubeTablet'        => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT', 
    233         // @ref: http://www.cobyusa.com/?p=pcat&pcat_id=3001 
    234         'CobyTablet'        => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010', 
    235         // @ref: http://www.match.net.cn/products.asp 
    236         'MIDTablet'         => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733', 
    237         // @ref: http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets) 
    238         // @ref: http://www.imp3.net/14/show.php?itemid=20454 
    239         'SMiTTablet'        => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)', 
    240         // @ref: http://www.rock-chips.com/index.php?do=prod&pid=2 
    241         'RockChipTablet'    => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A', 
    242         // @ref: http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/ 
    243         'FlyTablet'         => 'IQ310|Fly Vision', 
    244         // @ref: http://www.bqreaders.com/gb/tablets-prices-sale.html 
    245         'bqTablet'          => 'bq.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant)|Maxwell.*Lite|Maxwell.*Plus', 
    246         // @ref: http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290 
    247         // @ref: http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets) 
    248         'HuaweiTablet'      => 'MediaPad|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim', 
    249         // Nec or Medias Tab 
    250         'NecTablet'         => '\bN-06D|\bN-08D', 
    251         // Pantech Tablets: http://www.pantechusa.com/phones/ 
    252         'PantechTablet'     => 'Pantech.*P4100', 
    253         // Broncho Tablets: http://www.broncho.cn/ (hard to find) 
    254         'BronchoTablet'     => 'Broncho.*(N701|N708|N802|a710)', 
    255         // @ref: http://versusuk.com/support.html 
    256         'VersusTablet'      => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b', 
    257         // @ref: http://www.zync.in/index.php/our-products/tablet-phablets 
    258         'ZyncTablet'        => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900', 
    259         // @ref: http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/ 
    260         'PositivoTablet'    => 'TB07STA|TB10STA|TB07FTA|TB10FTA', 
    261         // @ref: https://www.nabitablet.com/ 
    262         'NabiTablet'        => 'Android.*\bNabi', 
    263         'KoboTablet'        => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build', 
    264         // French Danew Tablets http://www.danew.com/produits-tablette.php 
    265         'DanewTablet'       => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b', 
    266         // Texet Tablets and Readers http://www.texet.ru/tablet/ 
    267         'TexetTablet'       => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE', 
    268         // @note: Avoid detecting 'PLAYSTATION 3' as mobile. 
    269         'PlaystationTablet' => 'Playstation.*(Portable|Vita)', 
    270         // @ref: http://www.trekstor.de/surftabs.html 
    271         'TrekstorTablet'    => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2', 
    272         // @ref: http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets 
    273         'PyleAudioTablet'   => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b', 
    274         // @ref: http://www.advandigital.com/index.php?link=content-product&jns=JP001 
    275         'AdvanTablet'       => 'Android.* \b(S5G|S5K|T5B|T3E|T3C|T3B|T1J|T1F|S5D|T2A|T1H|E1C|T1i|S5E|T1-E|S5F|E1-B|T2Ci|T1-B|T1-D|T5-A|O1-A|E1-A|T1-A|T3A|S5|T4i)\b ', 
    276         // @ref: http://www.danytech.com/category/tablet-pc 
    277         'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1', 
    278         // @ref: http://www.galapad.net/product.html 
    279         'GalapadTablet'     => 'Android.*\bG1\b', 
    280         // @ref: http://www.micromaxinfo.com/tablet/funbook 
    281         'MicromaxTablet'    => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b', 
    282         // http://www.karbonnmobiles.com/products_tablet.php 
    283         'KarbonnTablet'     => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b', 
    284         // @ref: http://www.myallfine.com/Products.asp 
    285         'AllFineTablet'     => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide', 
    286         // @ref: http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr= 
    287         'PROSCANTablet'     => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b', 
    288         // @ref: http://www.yonesnav.com/products/products.php 
    289         'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026', 
    290         // @ref: http://www.cjshowroom.com/eproducts.aspx?classcode=004001001 
    291         // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html) 
    292         'ChangJiaTablet'    => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503', 
    293         // @ref: http://www.gloryunion.cn/products.asp 
    294         // @ref: http://www.allwinnertech.com/en/apply/mobile.html 
    295         // @ref: http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB) 
    296         // @todo: Softwiner tablets? 
    297         // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions. 
    298         'GUTablet'          => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G 
    299         // @ref: http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118 
    300         'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10', 
    301         // @ref: http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/ 
    302         // @todo: add more tests. 
    303         'OvermaxTablet'     => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)', 
    304         // @ref: http://hclmetablet.com/India/index.php 
    305         'HCLTablet'         => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync', 
    306         // @ref: http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html 
    307         'DPSTablet'         => 'DPS Dream 9|DPS Dual 7', 
    308         // @ref: http://www.visture.com/index.asp 
    309         'VistureTablet'     => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10', 
    310         // @ref: http://www.mijncresta.nl/tablet 
    311         'CrestaTablet'     => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989', 
    312         // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309 
    313         'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b', 
    314         // Concorde tab 
    315         'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan', 
    316         // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/ 
    317         'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042', 
    318         // Modecom Tablets - http://www.modecom.eu/tablets/portal/ 
    319         'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003', 
    320         // Vonino Tablets - http://www.vonino.eu/tablets 
    321         'VoninoTablet'  => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b', 
    322         // @ref: http://www.tolino.de/de/vergleichen/ 
    323         'TolinoTablet'  => 'tolino tab [0-9.]+|tolino shine', 
    324         // @ref: http://www.tesco.com/direct/hudl/ 
    325         'Hudl'              => 'Hudl HT7S3', 
    326         // @ref: http://www.telstra.com.au/home-phone/thub-2/ 
    327         'TelstraTablet'     => 'T-Hub2', 
    328         'GenericTablet'     => 'Android.*\b97D\b|Tablet(?!.*PC)|ViewPad7|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|SmartTabII10|SmartTab10|M758A|ET904|ALUMIUM10', 
    329     ); 
    330  
    331     /** 
    332      * List of mobile Operating Systems. 
    333      * 
    334      * @var array 
    335      */ 
    336     protected static $operatingSystems = array( 
    337         'AndroidOS'         => 'Android', 
    338         'BlackBerryOS'      => 'blackberry|\bBB10\b|rim tablet os', 
    339         'PalmOS'            => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino', 
    340         'SymbianOS'         => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b', 
    341         // @reference: http://en.wikipedia.org/wiki/Windows_Mobile 
    342         'WindowsMobileOS'   => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;', 
    343         // @reference: http://en.wikipedia.org/wiki/Windows_Phone 
    344         // http://wifeng.cn/?r=blog&a=view&id=106 
    345         // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx 
    346         'WindowsPhoneOS'   => 'Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7', 
    347         'iOS'               => '\biPhone.*Mobile|\biPod|\biPad', 
    348         // http://en.wikipedia.org/wiki/MeeGo 
    349         // @todo: research MeeGo in UAs 
    350         'MeeGoOS'           => 'MeeGo', 
    351         // http://en.wikipedia.org/wiki/Maemo 
    352         // @todo: research Maemo in UAs 
    353         'MaemoOS'           => 'Maemo', 
    354         'JavaOS'            => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135 
    355         'webOS'             => 'webOS|hpwOS', 
    356         'badaOS'            => '\bBada\b', 
    357         'BREWOS'            => 'BREW', 
    358     ); 
    359  
    360     /** 
    361      * List of mobile User Agents. 
    362      * 
    363      * @var array 
    364      */ 
    365     protected static $browsers = array( 
    366         // @reference: https://developers.google.com/chrome/mobile/docs/user-agent 
    367         'Chrome'          => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?', 
    368         'Dolfin'          => '\bDolfin\b', 
    369         'Opera'           => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+', 
    370         'Skyfire'         => 'Skyfire', 
    371         'IE'              => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+ 
    372         'Firefox'         => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile', 
    373         'Bolt'            => 'bolt', 
    374         'TeaShark'        => 'teashark', 
    375         'Blazer'          => 'Blazer', 
    376         // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3 
    377         'Safari'          => 'Version.*Mobile.*Safari|Safari.*Mobile', 
    378         // @ref: http://en.wikipedia.org/wiki/Midori_(web_browser) 
    379         //'Midori'          => 'midori', 
    380         'Tizen'           => 'Tizen', 
    381         'UCBrowser'       => 'UC.*Browser|UCWEB', 
    382         // @ref: https://github.com/serbanghita/Mobile-Detect/issues/7 
    383         'DiigoBrowser'    => 'DiigoBrowser', 
    384         // http://www.puffinbrowser.com/index.php 
    385         'Puffin'            => 'Puffin', 
    386         // @ref: http://mercury-browser.com/index.html 
    387         'Mercury'          => '\bMercury\b', 
    388         // @reference: http://en.wikipedia.org/wiki/Minimo 
    389         // http://en.wikipedia.org/wiki/Vision_Mobile_Browser 
    390         'GenericBrowser'  => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger' 
    391     ); 
    392  
    393     /** 
    394      * Utilities. 
    395      * 
    396      * @var array 
    397      */ 
    398     protected static $utilities = array( 
    399         // Experimental. When a mobile device wants to switch to 'Desktop Mode'. 
    400         // @ref: http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/ 
    401         // @ref: https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011 
    402         'DesktopMode' => 'WPDesktop', 
    403         'TV'          => 'SonyDTV|HbbTV', // experimental 
    404         'WebKit'      => '(webkit)[ /]([\w.]+)', 
    405         'Bot'         => 'Googlebot|DoCoMo|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit', 
    406         'MobileBot'   => 'Googlebot-Mobile|DoCoMo|YahooSeeker/M1A1-R2D2', 
    407         'Console'     => '\b(Nintendo|Nintendo WiiU|PLAYSTATION|Xbox)\b', 
    408         'Watch'       => 'SM-V700', 
    409     ); 
    410  
    411     /** 
    412      * All possible HTTP headers that represent the 
    413      * User-Agent string. 
    414      * 
    415      * @var array 
    416      */ 
    417     protected static $uaHttpHeaders = array( 
    418         // The default User-Agent string. 
    419         'HTTP_USER_AGENT', 
    420         // Header can occur on devices using Opera Mini. 
    421         'HTTP_X_OPERAMINI_PHONE_UA', 
    422         // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/ 
    423         'HTTP_X_DEVICE_USER_AGENT', 
    424         'HTTP_X_ORIGINAL_USER_AGENT', 
    425         'HTTP_X_SKYFIRE_PHONE', 
    426         'HTTP_X_BOLT_PHONE_UA', 
    427         'HTTP_DEVICE_STOCK_UA', 
    428         'HTTP_X_UCBROWSER_DEVICE_UA' 
    429     ); 
    430  
    431     /** 
    432      * The individual segments that could exist in a User-Agent string. VER refers to the regular 
    433      * expression defined in the constant self::VER. 
    434      * 
    435      * @var array 
    436      */ 
    437     protected static $properties = array( 
    438  
    439         // Build 
    440         'Mobile'        => 'Mobile/[VER]', 
    441         'Build'         => 'Build/[VER]', 
    442         'Version'       => 'Version/[VER]', 
    443         'VendorID'      => 'VendorID/[VER]', 
    444  
    445         // Devices 
    446         'iPad'          => 'iPad.*CPU[a-z ]+[VER]', 
    447         'iPhone'        => 'iPhone.*CPU[a-z ]+[VER]', 
    448         'iPod'          => 'iPod.*CPU[a-z ]+[VER]', 
    449         //'BlackBerry'    => array('BlackBerry[VER]', 'BlackBerry [VER];'), 
    450         'Kindle'        => 'Kindle/[VER]', 
    451  
    452         // Browser 
    453         'Chrome'        => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'), 
    454         'Coast'         => array('Coast/[VER]'), 
    455         'Dolfin'        => 'Dolfin/[VER]', 
    456         // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference 
    457         'Firefox'       => 'Firefox/[VER]', 
    458         'Fennec'        => 'Fennec/[VER]', 
    459         // @reference: http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx 
    460         'IE'      => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];'), 
    461         // http://en.wikipedia.org/wiki/NetFront 
    462         'NetFront'      => 'NetFront/[VER]', 
    463         'NokiaBrowser'  => 'NokiaBrowser/[VER]', 
    464         'Opera'         => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ), 
    465         'Opera Mini'    => 'Opera Mini/[VER]', 
    466         'Opera Mobi'    => 'Version/[VER]', 
    467         'UC Browser'    => 'UC Browser[VER]', 
    468         'MQQBrowser'    => 'MQQBrowser/[VER]', 
    469         'MicroMessenger' => 'MicroMessenger/[VER]', 
    470         // @note: Safari 7534.48.3 is actually Version 5.1. 
    471         // @note: On BlackBerry the Version is overwriten by the OS. 
    472         'Safari'        => array( 'Version/[VER]', 'Safari/[VER]' ), 
    473         'Skyfire'       => 'Skyfire/[VER]', 
    474         'Tizen'         => 'Tizen/[VER]', 
    475         'Webkit'        => 'webkit[ /][VER]', 
    476  
    477         // Engine 
    478         'Gecko'         => 'Gecko/[VER]', 
    479         'Trident'       => 'Trident/[VER]', 
    480         'Presto'        => 'Presto/[VER]', 
    481  
    482         // OS 
    483         'iOS'              => ' \bOS\b [VER] ', 
    484         'Android'          => 'Android [VER]', 
    485         'BlackBerry'       => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'), 
    486         'BREW'             => 'BREW [VER]', 
    487         'Java'             => 'Java/[VER]', 
    488         // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx 
    489         // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases 
    490         'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'), 
    491         'Windows Phone'    => 'Windows Phone [VER]', 
    492         'Windows CE'       => 'Windows CE/[VER]', 
    493         // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd 
    494         'Windows NT'       => 'Windows NT [VER]', 
    495         'Symbian'          => array('SymbianOS/[VER]', 'Symbian/[VER]'), 
    496         'webOS'            => array('webOS/[VER]', 'hpwOS/[VER];'), 
    497     ); 
    498  
    499     /** 
    500      * Construct an instance of this class. 
    501      * 
    502      * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored. 
    503      *                       If left empty, will use the global _SERVER['HTTP_*'] vars instead. 
    504      * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT 
    505      *                          from the $headers array instead. 
    506      */ 
    507     public function __construct( 
    508         array $headers = null, 
    509         $userAgent = null 
    510     ){ 
    511         $this->setHttpHeaders($headers); 
    512         $this->setUserAgent($userAgent); 
    513     } 
    514  
    515     /** 
    516     * Get the current script version. 
    517     * This is useful for the demo.php file, 
    518     * so people can check on what version they are testing 
    519     * for mobile devices. 
    520     * 
    521     * @return string The version number in semantic version format. 
    522     */ 
    523     public static function getScriptVersion() 
    524     { 
    525         return self::VERSION; 
    526     } 
    527  
    528     /** 
    529      * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers. 
    530      * 
    531      * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract 
    532      *                           the headers. The default null is left for backwards compatibilty. 
    533      */ 
    534     public function setHttpHeaders($httpHeaders = null) 
    535     { 
    536         //use global _SERVER if $httpHeaders aren't defined 
    537         if (!is_array($httpHeaders) || !count($httpHeaders)) { 
    538             $httpHeaders = $_SERVER; 
    539         } 
    540  
    541         //clear existing headers 
    542         $this->httpHeaders = array(); 
    543  
    544         //Only save HTTP headers. In PHP land, that means only _SERVER vars that 
    545         //start with HTTP_. 
    546         foreach ($httpHeaders as $key => $value) { 
    547             if (substr($key,0,5) == 'HTTP_') { 
    548                 $this->httpHeaders[$key] = $value; 
    549             } 
    550         } 
    551     } 
    552  
    553     /** 
    554      * Retrieves the HTTP headers. 
    555      * 
    556      * @return array 
    557      */ 
    558     public function getHttpHeaders() 
    559     { 
    560         return $this->httpHeaders; 
    561     } 
    562  
    563     /** 
    564      * Retrieves a particular header. If it doesn't exist, no exception/error is caused. 
    565      * Simply null is returned. 
    566      * 
    567      * @param string $header The name of the header to retrieve. Can be HTTP compliant such as 
    568      *                       "User-Agent" or "X-Device-User-Agent" or can be php-esque with the 
    569      *                       all-caps, HTTP_ prefixed, underscore seperated awesomeness. 
    570      * 
    571      * @return string|null The value of the header. 
    572      */ 
    573     public function getHttpHeader($header) 
    574     { 
    575         //are we using PHP-flavored headers? 
    576         if (strpos($header, '_') === false) { 
    577             $header = str_replace('-', '_', $header); 
    578             $header = strtoupper($header); 
    579         } 
    580  
    581         //test the alternate, too 
    582         $altHeader = 'HTTP_' . $header; 
    583  
    584         //Test both the regular and the HTTP_ prefix 
    585         if (isset($this->httpHeaders[$header])) { 
    586             return $this->httpHeaders[$header]; 
    587         } elseif (isset($this->httpHeaders[$altHeader])) { 
    588             return $this->httpHeaders[$altHeader]; 
    589         } 
    590     } 
    591  
    592     public function getMobileHeaders() 
    593     { 
    594         return self::$mobileHeaders; 
    595     } 
    596  
    597     /** 
    598      * Get all possible HTTP headers that 
    599      * can contain the User-Agent string. 
    600      * 
    601      * @return array List of HTTP headers. 
    602      */ 
    603     public function getUaHttpHeaders() 
    604     { 
    605         return self::$uaHttpHeaders; 
    606     } 
    607  
    608     /** 
    609      * Set the User-Agent to be used. 
    610      * 
    611      * @param string $userAgent The user agent string to set. 
    612      */ 
    613     public function setUserAgent($userAgent = null) 
    614     { 
    615         if (!empty($userAgent)) { 
    616             return $this->userAgent = $userAgent; 
    617         } else { 
    618  
    619             $this->userAgent = null; 
    620  
    621             foreach($this->getUaHttpHeaders() as $altHeader){ 
    622                 if(!empty($this->httpHeaders[$altHeader])){ // @todo: should use getHttpHeader(), but it would be slow. (Serban) 
    623                     $this->userAgent .= $this->httpHeaders[$altHeader] . " "; 
    624                 } 
    625             } 
    626  
    627             return $this->userAgent = (!empty($this->userAgent) ? trim($this->userAgent) : null); 
    628  
    629         } 
    630     } 
    631  
    632     /** 
    633      * Retrieve the User-Agent. 
    634      * 
    635      * @return string|null The user agent if it's set. 
    636      */ 
    637     public function getUserAgent() 
    638     { 
    639         return $this->userAgent; 
    640     } 
    641  
    642     /** 
    643      * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or 
    644      * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set. 
    645      * 
    646      * @deprecated since version 2.6.9 
    647      * 
    648      * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default 
    649      *                     parameter is null which will default to self::DETECTION_TYPE_MOBILE. 
    650      */ 
    651     public function setDetectionType($type = null) 
    652     { 
    653         if ($type === null) { 
    654             $type = self::DETECTION_TYPE_MOBILE; 
    655         } 
    656  
    657         if ($type != self::DETECTION_TYPE_MOBILE && $type != self::DETECTION_TYPE_EXTENDED) { 
    658             return; 
    659         } 
    660  
    661         $this->detectionType = $type; 
    662     } 
    663  
    664     /** 
    665      * Retrieve the list of known phone devices. 
    666      * 
    667      * @return array List of phone devices. 
    668      */ 
    669     public static function getPhoneDevices() 
    670     { 
    671         return self::$phoneDevices; 
    672     } 
    673  
    674     /** 
    675      * Retrieve the list of known tablet devices. 
    676      * 
    677      * @return array List of tablet devices. 
    678      */ 
    679     public static function getTabletDevices() 
    680     { 
    681         return self::$tabletDevices; 
    682     } 
    683  
    684     /** 
    685      * Alias for getBrowsers() method. 
    686      * 
    687      * @return array List of user agents. 
    688      */ 
    689     public static function getUserAgents() 
    690     { 
    691         return self::getBrowsers(); 
    692     } 
    693  
    694     /** 
    695      * Retrieve the list of known browsers. Specifically, the user agents. 
    696      * 
    697      * @return array List of browsers / user agents. 
    698      */ 
    699     public static function getBrowsers() 
    700     { 
    701         return self::$browsers; 
    702     } 
    703  
    704     /** 
    705      * Retrieve the list of known utilities. 
    706      * 
    707      * @return array List of utilities. 
    708      */ 
    709     public static function getUtilities() 
    710     { 
    711         return self::$utilities; 
    712     } 
    713  
    714     /** 
    715      * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*(). 
    716      * 
    717      * @deprecated since version 2.6.9 
    718      * 
    719      * @return array All the rules (but not extended). 
    720      */ 
    721     public static function getMobileDetectionRules() 
    722     { 
    723         static $rules; 
    724  
    725         if (!$rules) { 
    726             $rules = array_merge( 
    727                 self::$phoneDevices, 
    728                 self::$tabletDevices, 
    729                 self::$operatingSystems, 
    730                 self::$browsers 
    731             ); 
    732         } 
    733  
    734         return $rules; 
    735  
    736     } 
    737  
    738     /** 
    739      * Method gets the mobile detection rules + utilities. 
    740      * The reason this is separate is because utilities rules 
    741      * don't necessary imply mobile. This method is used inside 
    742      * the new $detect->is('stuff') method. 
    743      * 
    744      * @deprecated since version 2.6.9 
    745      * 
    746      * @return array All the rules + extended. 
    747      */ 
    748     public function getMobileDetectionRulesExtended() 
    749     { 
    750         static $rules; 
    751  
    752         if (!$rules) { 
    753             // Merge all rules together. 
    754             $rules = array_merge( 
    755                 self::$phoneDevices, 
    756                 self::$tabletDevices, 
    757                 self::$operatingSystems, 
    758                 self::$browsers, 
    759                 self::$utilities 
    760             ); 
    761         } 
    762  
    763         return $rules; 
    764     } 
    765  
    766     /** 
    767      * Retrieve the current set of rules. 
    768      * 
    769      * @deprecated since version 2.6.9 
    770      * 
    771      * @return array 
    772      */ 
    773     public function getRules() 
    774     { 
    775         if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) { 
    776             return self::getMobileDetectionRulesExtended(); 
    777         } else { 
    778             return self::getMobileDetectionRules(); 
    779         } 
    780     } 
    781  
    782     /** 
    783      * Retrieve the list of mobile operating systems. 
    784      * 
    785      * @return array The list of mobile operating systems. 
    786      */ 
    787     public static function getOperatingSystems() 
    788     { 
    789         return self::$operatingSystems; 
    790     } 
    791  
    792     /** 
    793     * Check the HTTP headers for signs of mobile. 
    794     * This is the fastest mobile check possible; it's used 
    795     * inside isMobile() method. 
    796     * 
    797     * @return bool 
    798     */ 
    799     public function checkHttpHeadersForMobile() 
    800     { 
    801  
    802         foreach($this->getMobileHeaders() as $mobileHeader => $matchType){ 
    803             if( isset($this->httpHeaders[$mobileHeader]) ){ 
    804                 if( is_array($matchType['matches']) ){ 
    805                     foreach($matchType['matches'] as $_match){ 
    806                         if( strpos($this->httpHeaders[$mobileHeader], $_match) !== false ){ 
    807                             return true; 
    808                         } 
    809                     } 
    810                     return false; 
    811                 } else { 
    812                     return true; 
    813                 } 
    814             } 
    815         } 
    816  
    817         return false; 
    818  
    819     } 
    820  
    821     /** 
    822      * Magic overloading method. 
    823      * 
    824      * @method boolean is[...]() 
    825      * @param  string                 $name 
    826      * @param  array                  $arguments 
    827      * @return mixed 
    828      * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is' 
    829      */ 
    830     public function __call($name, $arguments) 
    831     { 
    832         //make sure the name starts with 'is', otherwise 
    833         if (substr($name, 0, 2) != 'is') { 
    834             throw new BadMethodCallException("No such method exists: $name"); 
    835         } 
    836  
    837         $this->setDetectionType(self::DETECTION_TYPE_MOBILE); 
    838  
    839         $key = substr($name, 2); 
    840  
    841         return $this->matchUAAgainstKey($key); 
    842     } 
    843  
    844     /** 
    845     * Find a detection rule that matches the current User-agent. 
    846     * 
    847     * @param null $userAgent deprecated 
    848     * @return boolean 
    849     */ 
    850     protected function matchDetectionRulesAgainstUA($userAgent = null) 
    851     { 
    852         // Begin general search. 
    853         foreach ($this->getRules() as $_regex) { 
    854             if (empty($_regex)) { 
    855                 continue; 
    856             } 
    857             if ($this->match($_regex, $userAgent)) { 
    858                 return true; 
    859             } 
    860         } 
    861  
    862         return false; 
    863     } 
    864  
    865     /** 
    866     * Search for a certain key in the rules array. 
    867     * If the key is found the try to match the corresponding 
    868     * regex agains the User-Agent. 
    869     * 
    870     * @param string $key 
    871     * @param null $userAgent deprecated 
    872     * @return mixed 
    873     */ 
    874     protected function matchUAAgainstKey($key, $userAgent = null) 
    875     { 
    876         // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc. 
    877         $key = strtolower($key); 
    878  
    879         //change the keys to lower case 
    880         $_rules = array_change_key_case($this->getRules()); 
    881  
    882         if (array_key_exists($key, $_rules)) { 
    883             if (empty($_rules[$key])) { 
    884                 return null; 
    885             } 
    886  
    887             return $this->match($_rules[$key], $userAgent); 
    888         } 
    889  
    890         return false; 
    891     } 
    892  
    893     /** 
    894     * Check if the device is mobile. 
    895     * Returns true if any type of mobile device detected, including special ones 
    896     * @param null $userAgent deprecated 
    897     * @param null $httpHeaders deprecated 
    898     * @return bool 
    899     */ 
    900     public function isMobile($userAgent = null, $httpHeaders = null) 
    901     { 
    902  
    903         if ($httpHeaders) { 
    904             $this->setHttpHeaders($httpHeaders); 
    905         } 
    906  
    907         if ($userAgent) { 
    908             $this->setUserAgent($userAgent); 
    909         } 
    910  
    911         $this->setDetectionType(self::DETECTION_TYPE_MOBILE); 
    912  
    913         if ($this->checkHttpHeadersForMobile()) { 
    914             return true; 
    915         } else { 
    916             return $this->matchDetectionRulesAgainstUA(); 
    917         } 
    918  
    919     } 
    920  
    921     /** 
    922      * Check if the device is a tablet. 
    923      * Return true if any type of tablet device is detected. 
    924      * 
    925      * @param  string $userAgent   deprecated 
    926      * @param  array  $httpHeaders deprecated 
    927      * @return bool 
    928      */ 
    929     public function isTablet($userAgent = null, $httpHeaders = null) 
    930     { 
    931         $this->setDetectionType(self::DETECTION_TYPE_MOBILE); 
    932  
    933         foreach (self::$tabletDevices as $_regex) { 
    934             if ($this->match($_regex, $userAgent)) { 
    935                 return true; 
    936             } 
    937         } 
    938  
    939         return false; 
    940     } 
    941  
    942     /** 
    943      * This method checks for a certain property in the 
    944      * userAgent. 
    945      * @todo: The httpHeaders part is not yet used. 
    946      * 
    947      * @param $key 
    948      * @param  string        $userAgent   deprecated 
    949      * @param  string        $httpHeaders deprecated 
    950      * @return bool|int|null 
    951      */ 
    952     public function is($key, $userAgent = null, $httpHeaders = null) 
    953     { 
    954         // Set the UA and HTTP headers only if needed (eg. batch mode). 
    955         if ($httpHeaders) { 
    956             $this->setHttpHeaders($httpHeaders); 
    957         } 
    958  
    959         if ($userAgent) { 
    960             $this->setUserAgent($userAgent); 
    961         } 
    962  
    963         $this->setDetectionType(self::DETECTION_TYPE_EXTENDED); 
    964  
    965         return $this->matchUAAgainstKey($key); 
    966     } 
    967  
    968     /** 
    969      * Some detection rules are relative (not standard), 
    970      * because of the diversity of devices, vendors and 
    971      * their conventions in representing the User-Agent or 
    972      * the HTTP headers. 
    973      * 
    974      * This method will be used to check custom regexes against 
    975      * the User-Agent string. 
    976      * 
    977      * @param $regex 
    978      * @param  string $userAgent 
    979      * @return bool 
    980      * 
    981      * @todo: search in the HTTP headers too. 
    982      */ 
    983     public function match($regex, $userAgent = null) 
    984     { 
    985         // Escape the special character which is the delimiter. 
    986         $regex = str_replace('/', '\/', $regex); 
    987  
    988         return (bool) preg_match('/'.$regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent)); 
    989     } 
    990  
    991     /** 
    992      * Get the properties array. 
    993      * 
    994      * @return array 
    995      */ 
    996     public static function getProperties() 
    997     { 
    998         return self::$properties; 
    999     } 
    1000  
    1001     /** 
    1002      * Prepare the version number. 
    1003      * 
    1004      * @todo Remove the error supression from str_replace() call. 
    1005      * 
    1006      * @param string $ver The string version, like "2.6.21.2152"; 
    1007      * 
    1008      * @return float 
    1009      */ 
    1010     public function prepareVersionNo($ver) 
    1011     { 
    1012         $ver = str_replace(array('_', ' ', '/'), '.', $ver); 
    1013         $arrVer = explode('.', $ver, 2); 
    1014  
    1015         if (isset($arrVer[1])) { 
    1016             $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions. 
    1017         } 
    1018  
    1019         return (float) implode('.', $arrVer); 
    1020     } 
    1021  
    1022     /** 
    1023      * Check the version of the given property in the User-Agent. 
    1024      * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31) 
    1025      * 
    1026      * @param string $propertyName The name of the property. See self::getProperties() array 
    1027      *                              keys for all possible properties. 
    1028      * @param string $type Either self::VERSION_TYPE_STRING to get a string value or 
    1029      *                      self::VERSION_TYPE_FLOAT indicating a float value. This parameter 
    1030      *                      is optional and defaults to self::VERSION_TYPE_STRING. Passing an 
    1031      *                      invalid parameter will default to the this type as well. 
    1032      * 
    1033      * @return string|float The version of the property we are trying to extract. 
    1034      */ 
    1035     public function version($propertyName, $type = self::VERSION_TYPE_STRING) 
    1036     { 
    1037         if (empty($propertyName)) { 
    1038             return false; 
    1039         } 
    1040  
    1041         //set the $type to the default if we don't recognize the type 
    1042         if ($type != self::VERSION_TYPE_STRING && $type != self::VERSION_TYPE_FLOAT) { 
    1043             $type = self::VERSION_TYPE_STRING; 
    1044         } 
    1045  
    1046         $properties = self::getProperties(); 
    1047  
    1048         // Check if the property exists in the properties array. 
    1049         if (array_key_exists($propertyName, $properties)) { 
    1050  
    1051             // Prepare the pattern to be matched. 
    1052             // Make sure we always deal with an array (string is converted). 
    1053             $properties[$propertyName] = (array) $properties[$propertyName]; 
    1054  
    1055             foreach ($properties[$propertyName] as $propertyMatchString) { 
    1056  
    1057                 $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString); 
    1058  
    1059                 // Escape the special character which is the delimiter. 
    1060                 $propertyPattern = str_replace('/', '\/', $propertyPattern); 
    1061  
    1062                 // Identify and extract the version. 
    1063                 preg_match('/'.$propertyPattern.'/is', $this->userAgent, $match); 
    1064  
    1065                 if (!empty($match[1])) { 
    1066                     $version = ( $type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1] ); 
    1067  
    1068                     return $version; 
    1069                 } 
    1070  
    1071             } 
    1072  
    1073         } 
    1074  
    1075         return false; 
    1076     } 
    1077  
    1078     /** 
    1079      * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants. 
    1080      * 
    1081      * @return string One of the self::MOBILE_GRADE_* constants. 
    1082      */ 
    1083     public function mobileGrade() 
    1084     { 
    1085         $isMobile = $this->isMobile(); 
    1086  
    1087         if ( 
    1088             // Apple iOS 3.2-5.1 - Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3), iPad 3 (5.1), original iPhone (3.1), iPhone 3 (3.2), 3GS (4.3), 4 (4.3 / 5.0), and 4S (5.1) 
    1089             $this->version('iPad', self::VERSION_TYPE_FLOAT)>=4.3 || 
    1090             $this->version('iPhone', self::VERSION_TYPE_FLOAT)>=3.1 || 
    1091             $this->version('iPod', self::VERSION_TYPE_FLOAT)>=3.1 || 
    1092  
    1093             // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5) 
    1094             // Android 3.1 (Honeycomb)  - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM 
    1095             // Android 4.0 (ICS)  - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices 
    1096             // Android 4.1 (Jelly Bean)  - Tested on a Galaxy Nexus and Galaxy 7 
    1097             ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) || 
    1098  
    1099             // Windows Phone 7-7.5 - Tested on the HTC Surround (7.0) HTC Trophy (7.5), LG-E900 (7.5), Nokia Lumia 800 
    1100             $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT)>=7.0 || 
    1101  
    1102             // Blackberry 7 - Tested on BlackBerry® Torch 9810 
    1103             // Blackberry 6.0 - Tested on the Torch 9800 and Style 9670 
    1104             $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=6.0 || 
    1105             // Blackberry Playbook (1.0-2.0) - Tested on PlayBook 
    1106             $this->match('Playbook.*Tablet') || 
    1107  
    1108             // Palm WebOS (1.4-2.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0) 
    1109             ( $this->version('webOS', self::VERSION_TYPE_FLOAT)>=1.4 && $this->match('Palm|Pre|Pixi') ) || 
    1110             // Palm WebOS 3.0  - Tested on HP TouchPad 
    1111             $this->match('hp.*TouchPad') || 
    1112  
    1113             // Firefox Mobile (12 Beta) - Tested on Android 2.3 device 
    1114             ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=12 ) || 
    1115  
    1116             // Chrome for Android - Tested on Android 4.0, 4.1 device 
    1117             ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=4.0 ) || 
    1118  
    1119             // Skyfire 4.1 - Tested on Android 2.3 device 
    1120             ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT)>=4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) || 
    1121  
    1122             // Opera Mobile 11.5-12: Tested on Android 2.3 
    1123             ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>11 && $this->is('AndroidOS') ) || 
    1124  
    1125             // Meego 1.2 - Tested on Nokia 950 and N9 
    1126             $this->is('MeeGoOS') || 
    1127  
    1128             // Tizen (pre-release) - Tested on early hardware 
    1129             $this->is('Tizen') || 
    1130  
    1131             // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser 
    1132             // @todo: more tests here! 
    1133             $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT)>=2.0 || 
    1134  
    1135             // UC Browser - Tested on Android 2.3 device 
    1136             ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) || 
    1137  
    1138             // Kindle 3 and Fire  - Tested on the built-in WebKit browser for each 
    1139             ( $this->match('Kindle Fire') || 
    1140             $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT)>=3.0 ) || 
    1141  
    1142             // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet 
    1143             $this->is('AndroidOS') && $this->is('NookTablet') || 
    1144  
    1145             // Chrome Desktop 11-21 - Tested on OS X 10.7 and Windows 7 
    1146             $this->version('Chrome', self::VERSION_TYPE_FLOAT)>=11 && !$isMobile || 
    1147  
    1148             // Safari Desktop 4-5 - Tested on OS X 10.7 and Windows 7 
    1149             $this->version('Safari', self::VERSION_TYPE_FLOAT)>=5.0 && !$isMobile || 
    1150  
    1151             // Firefox Desktop 4-13 - Tested on OS X 10.7 and Windows 7 
    1152             $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=4.0 && !$isMobile || 
    1153  
    1154             // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7 
    1155             $this->version('MSIE', self::VERSION_TYPE_FLOAT)>=7.0 && !$isMobile || 
    1156  
    1157             // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7 
    1158             // @reference: http://my.opera.com/community/openweb/idopera/ 
    1159             $this->version('Opera', self::VERSION_TYPE_FLOAT)>=10 && !$isMobile 
    1160  
    1161         ){ 
    1162             return self::MOBILE_GRADE_A; 
    1163         } 
    1164  
    1165         if ( 
    1166             $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 || 
    1167             $this->version('iPhone', self::VERSION_TYPE_FLOAT)<3.1 || 
    1168             $this->version('iPod', self::VERSION_TYPE_FLOAT)<3.1 || 
    1169  
    1170             // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770 
    1171             $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 || 
    1172  
    1173             //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3 
    1174             ( $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)>=5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)<=6.5 && 
    1175             ($this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 || $this->is('iOS')) ) || 
    1176  
    1177             // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1) 
    1178             $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') || 
    1179  
    1180             // @todo: report this (tested on Nokia N71) 
    1181             $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>=11 && $this->is('SymbianOS') 
    1182         ){ 
    1183             return self::MOBILE_GRADE_B; 
    1184         } 
    1185  
    1186         if ( 
    1187             // Blackberry 4.x - Tested on the Curve 8330 
    1188             $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<5.0 || 
    1189             // Windows Mobile - Tested on the HTC Leo (WinMo 5.2) 
    1190             $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT)<=5.2 
    1191  
    1192         ){ 
    1193             return self::MOBILE_GRADE_C; 
    1194         } 
    1195  
    1196         //All older smartphone platforms and featurephones - Any device that doesn't support media queries 
    1197         //will receive the basic, C grade experience. 
    1198         return self::MOBILE_GRADE_C; 
    1199     } 
    1200 } 
     22class MobileDetect extends \Mobile_Detect {} 
  • branches/version-2_13-dev/data/module/XML/Util.php

    r21713 r23600  
    77 * 
    88 * XML Utilities package 
    9  *  
     9 * 
    1010 * PHP versions 4 and 5 
    1111 * 
     
    4444 * @copyright 2003-2008 Stephan Schmidt <schst@php.net> 
    4545 * @license   http://opensource.org/licenses/bsd-license New BSD License 
    46  * @version   CVS: $Id: Util.php,v 1.38 2008/11/13 00:03:38 ashnazg Exp $ 
     46 * @version   CVS: $Id$ 
    4747 * @link      http://pear.php.net/package/XML_Util 
    4848 */ 
     
    120120 * @copyright 2003-2008 Stephan Schmidt <schst@php.net> 
    121121 * @license   http://opensource.org/licenses/bsd-license New BSD License 
    122  * @version   Release: 1.2.1 
     122 * @version   Release: 1.2.3 
    123123 * @link      http://pear.php.net/package/XML_Util 
    124124 */ 
     
    162162     * </code> 
    163163     * 
    164      * @param string $string          string where XML special chars  
     164     * @param string $string          string where XML special chars 
    165165     *                                should be replaced 
    166      * @param int    $replaceEntities setting for entities in attribute values  
    167      *                                (one of XML_UTIL_ENTITIES_XML,  
    168      *                                XML_UTIL_ENTITIES_XML_REQUIRED,  
     166     * @param int    $replaceEntities setting for entities in attribute values 
     167     *                                (one of XML_UTIL_ENTITIES_XML, 
     168     *                                XML_UTIL_ENTITIES_XML_REQUIRED, 
    169169     *                                XML_UTIL_ENTITIES_HTML) 
    170170     * @param string $encoding        encoding value (if any)... 
     
    228228     * </code> 
    229229     * 
    230      * @param string $string          string where XML special chars  
     230     * @param string $string          string where XML special chars 
    231231     *                                should be replaced 
    232      * @param int    $replaceEntities setting for entities in attribute values  
    233      *                                (one of XML_UTIL_ENTITIES_XML,  
    234      *                                XML_UTIL_ENTITIES_XML_REQUIRED,  
     232     * @param int    $replaceEntities setting for entities in attribute values 
     233     *                                (one of XML_UTIL_ENTITIES_XML, 
     234     *                                XML_UTIL_ENTITIES_XML_REQUIRED, 
    235235     *                                XML_UTIL_ENTITIES_HTML) 
    236236     * @param string $encoding        encoding value (if any)... 
     
    287287     * @uses attributesToString() to serialize the attributes of the XML declaration 
    288288     */ 
    289     function getXMLDeclaration($version = '1.0', $encoding = null,  
     289    function getXMLDeclaration($version = '1.0', $encoding = null, 
    290290        $standalone = null) 
    291291    { 
     
    302302        } 
    303303 
    304         return sprintf('<?xml%s?>',  
     304        return sprintf('<?xml%s?>', 
    305305            XML_Util::attributesToString($attributes, false)); 
    306306    } 
     
    317317     * 
    318318     * @param string $root        name of the root tag 
    319      * @param string $uri         uri of the doctype definition  
     319     * @param string $uri         uri of the doctype definition 
    320320     *                            (or array with uri and public id) 
    321321     * @param string $internalDtd internal dtd entries 
     
    359359     * 
    360360     * @param array      $attributes attribute array 
    361      * @param bool|array $sort       sort attribute list alphabetically,  
    362      *                               may also be an assoc array containing  
    363      *                               the keys 'sort', 'multiline', 'indent',  
     361     * @param bool|array $sort       sort attribute list alphabetically, 
     362     *                               may also be an assoc array containing 
     363     *                               the keys 'sort', 'multiline', 'indent', 
    364364     *                               'linebreak' and 'entities' 
    365      * @param bool       $multiline  use linebreaks, if more than  
     365     * @param bool       $multiline  use linebreaks, if more than 
    366366     *                               one attribute is given 
    367      * @param string     $indent     string used for indentation of  
     367     * @param string     $indent     string used for indentation of 
    368368     *                               multiline attributes 
    369      * @param string     $linebreak  string used for linebreaks of  
     369     * @param string     $linebreak  string used for linebreaks of 
    370370     *                               multiline attributes 
    371      * @param int        $entities   setting for entities in attribute values  
    372      *                               (one of XML_UTIL_ENTITIES_NONE,  
    373      *                               XML_UTIL_ENTITIES_XML,  
    374      *                               XML_UTIL_ENTITIES_XML_REQUIRED,  
     371     * @param int        $entities   setting for entities in attribute values 
     372     *                               (one of XML_UTIL_ENTITIES_NONE, 
     373     *                               XML_UTIL_ENTITIES_XML, 
     374     *                               XML_UTIL_ENTITIES_XML_REQUIRED, 
    375375     *                               XML_UTIL_ENTITIES_HTML) 
    376376     * 
     
    381381     * @todo allow sort also to be an options array 
    382382     */ 
    383     function attributesToString($attributes, $sort = true, $multiline = false,  
     383    function attributesToString($attributes, $sort = true, $multiline = false, 
    384384        $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML) 
    385385    { 
     
    452452     *       in the IF branch 
    453453     */ 
    454     function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)  
     454    function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL) 
    455455    { 
    456456        if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) { 
     
    475475     * 
    476476     * // create an XML tag: 
    477      * $tag = XML_Util::createTag('myNs:myTag',  
    478      *     array('foo' => 'bar'),  
    479      *     'This is inside the tag',  
     477     * $tag = XML_Util::createTag('myNs:myTag', 
     478     *     array('foo' => 'bar'), 
     479     *     'This is inside the tag', 
    480480     *     'http://www.w3c.org/myNs#'); 
    481481     * </code> 
     
    485485     * @param mixed  $content         the content 
    486486     * @param string $namespaceUri    URI of the namespace 
    487      * @param int    $replaceEntities whether to replace XML special chars in  
    488      *                                content, embedd it in a CData section  
     487     * @param int    $replaceEntities whether to replace XML special chars in 
     488     *                                content, embedd it in a CData section 
    489489     *                                or none of both 
    490      * @param bool   $multiline       whether to create a multiline tag where  
     490     * @param bool   $multiline       whether to create a multiline tag where 
    491491     *                                each attribute gets written to a single line 
    492      * @param string $indent          string used to indent attributes  
    493      *                                (_auto indents attributes so they start  
     492     * @param string $indent          string used to indent attributes 
     493     *                                (_auto indents attributes so they start 
    494494     *                                at the same column) 
    495495     * @param string $linebreak       string used for linebreaks 
     
    502502     * @uses createTagFromArray() to create the tag 
    503503     */ 
    504     function createTag($qname, $attributes = array(), $content = null,  
    505         $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,  
    506         $multiline = false, $indent = '_auto', $linebreak = "\n",  
     504    function createTag($qname, $attributes = array(), $content = null, 
     505        $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, 
     506        $multiline = false, $indent = '_auto', $linebreak = "\n", 
    507507        $sortAttributes = true) 
    508508    { 
     
    522522        } 
    523523 
    524         return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline,  
     524        return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, 
    525525            $indent, $linebreak, $sortAttributes); 
    526526    } 
     
    532532     * array( 
    533533     *     // qualified name of the tag 
    534      *     'qname' => $qname         
     534     *     'qname' => $qname 
    535535     * 
    536536     *     // namespace prefix (optional, if qname is specified or no namespace) 
    537      *     'namespace' => $namespace     
     537     *     'namespace' => $namespace 
    538538     * 
    539539     *     // local part of the tagname (optional, if qname is specified) 
    540      *     'localpart' => $localpart,    
     540     *     'localpart' => $localpart, 
    541541     * 
    542542     *     // array containing all attributes (optional) 
    543      *     'attributes' => array(),       
     543     *     'attributes' => array(), 
    544544     * 
    545545     *     // tag content (optional) 
    546      *     'content' => $content,      
     546     *     'content' => $content, 
    547547     * 
    548548     *     // namespaceUri for the given namespace (optional) 
    549      *     'namespaceUri' => $namespaceUri  
     549     *     'namespaceUri' => $namespaceUri 
    550550     * ) 
    551551     * </pre> 
     
    565565     * 
    566566     * @param array  $tag             tag definition 
    567      * @param int    $replaceEntities whether to replace XML special chars in  
    568      *                                content, embedd it in a CData section  
     567     * @param int    $replaceEntities whether to replace XML special chars in 
     568     *                                content, embedd it in a CData section 
    569569     *                                or none of both 
    570      * @param bool   $multiline       whether to create a multiline tag where each  
     570     * @param bool   $multiline       whether to create a multiline tag where each 
    571571     *                                attribute gets written to a single line 
    572      * @param string $indent          string used to indent attributes  
    573      *                                (_auto indents attributes so they start  
     572     * @param string $indent          string used to indent attributes 
     573     *                                (_auto indents attributes so they start 
    574574     *                                at the same column) 
    575575     * @param string $linebreak       string used for linebreaks 
     
    586586     */ 
    587587    function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, 
    588         $multiline = false, $indent = '_auto', $linebreak = "\n",  
     588        $multiline = false, $indent = '_auto', $linebreak = "\n", 
    589589        $sortAttributes = true) 
    590590    { 
     
    596596        if (!isset($tag['qname']) && !isset($tag['localPart'])) { 
    597597            return XML_Util::raiseError('You must either supply a qualified name ' 
    598                 . '(qname) or local tag name (localPart).',  
     598                . '(qname) or local tag name (localPart).', 
    599599                XML_UTIL_ERROR_NO_TAG_NAME); 
    600600        } 
     
    650650 
    651651        // create attribute list 
    652         $attList = XML_Util::attributesToString($tag['attributes'],  
    653             $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities); 
     652        $attList = XML_Util::attributesToString($tag['attributes'], 
     653            $sortAttributes, $multiline, $indent, $linebreak); 
    654654        if (!isset($tag['content']) || (string)$tag['content'] == '') { 
    655655            $tag = sprintf('<%s%s />', $tag['qname'], $attList); 
     
    662662                break; 
    663663            default: 
    664                 $tag['content'] = XML_Util::replaceEntities($tag['content'],  
     664                $tag['content'] = XML_Util::replaceEntities($tag['content'], 
    665665                    $replaceEntities); 
    666666                break; 
     
    679679     * 
    680680     * // create an XML start element: 
    681      * $tag = XML_Util::createStartElement('myNs:myTag',  
     681     * $tag = XML_Util::createStartElement('myNs:myTag', 
    682682     *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#'); 
    683683     * </code> 
     
    686686     * @param array  $attributes     array containg attributes 
    687687     * @param string $namespaceUri   URI of the namespace 
    688      * @param bool   $multiline      whether to create a multiline tag where each  
     688     * @param bool   $multiline      whether to create a multiline tag where each 
    689689     *                               attribute gets written to a single line 
    690690     * @param string $indent         string used to indent attributes (_auto indents 
     
    699699     */ 
    700700    function createStartElement($qname, $attributes = array(), $namespaceUri = null, 
    701         $multiline = false, $indent = '_auto', $linebreak = "\n",  
     701        $multiline = false, $indent = '_auto', $linebreak = "\n", 
    702702        $sortAttributes = true) 
    703703    { 
     
    729729 
    730730        // create attribute list 
    731         $attList = XML_Util::attributesToString($attributes, $sortAttributes,  
     731        $attList = XML_Util::attributesToString($attributes, $sortAttributes, 
    732732            $multiline, $indent, $linebreak); 
    733733        $element = sprintf('<%s%s>', $qname, $attList); 
     
    798798    function createCDataSection($data) 
    799799    { 
    800         return sprintf('<![CDATA[%s]]>',  
     800        return sprintf('<![CDATA[%s]]>', 
    801801            preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data))); 
    802802 
     
    872872    { 
    873873        // check for invalid chars 
    874         if (!preg_match('/^[[:alpha:]_]$/', $string{0})) { 
     874        if (!preg_match('/^[[:alpha:]_]\\z/', $string{0})) { 
    875875            return XML_Util::raiseError('XML names may only start with letter ' 
    876876                . 'or underscore', XML_UTIL_ERROR_INVALID_START); 
     
    878878 
    879879        // check for invalid chars 
    880         if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?$/', 
     880        if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/', 
    881881            $string) 
    882882        ) { 
    883883            return XML_Util::raiseError('XML names may only contain alphanumeric ' 
    884                 . 'chars, period, hyphen, colon and underscores',  
     884                . 'chars, period, hyphen, colon and underscores', 
    885885                XML_UTIL_ERROR_INVALID_CHARS); 
    886886        } 
Note: See TracChangeset for help on using the changeset viewer.