Overview

Packages

  • Auth
    • Ads
    • Ldap
    • Xoops
  • Autotasks
  • Config
    • Category
    • Item
    • Option
  • Core
    • Filesystem
    • Filters
    • Logger
    • Mail
    • Message
    • Password
    • Security
    • StopSpammer
    • Template
    • Textsanitizer
    • VersionChecker
  • Data
    • Avatar
    • Comment
  • Database
    • Connection
    • Criteria
    • Legacy
    • MySQL
    • PDO
    • Updater
  • Feeds
    • RSS
  • File
  • Form
    • Base
    • Elements
  • ICMS
    • IPF
      • View
  • Image
    • Category
  • Ipf
    • Category
    • Controller
    • Export
    • form
    • Keyhighlighter
    • Member
    • Object
    • Permission
    • richfile
    • Tree
    • urllink
    • View
  • kernel
    • Set
  • Member
    • Group
    • GroupMembership
    • GroupPermission
    • User
  • Messaging
  • Module
  • None
  • Notification
  • Page
  • Plugins
    • Editor
  • Preload
    • Libraries
  • Privmessage
  • Session
  • SmartObject
  • View
    • Block
    • Breadcrumb
    • PageNav
    • PrinterFriendly
    • Template
    • Templates
    • Theme
    • Tree

Classes

  • icms_auth_Ads
  • icms_auth_Factory
  • icms_auth_Ldap
  • icms_auth_Object
  • icms_auth_Provisionning
  • icms_auth_Xoops
  • icms_Autoloader
  • icms_config_category_Handler
  • icms_config_category_Object
  • icms_config_Handler
  • icms_config_Item_Handler
  • icms_config_Item_Object
  • icms_config_option_Handler
  • icms_config_option_Object
  • icms_core_DataFilter
  • icms_core_Debug
  • icms_core_Filesystem
  • icms_core_HTMLFilter
  • icms_core_Logger
  • icms_core_Message
  • icms_core_Object
  • icms_core_ObjectHandler
  • icms_core_OnlineHandler
  • icms_core_Password
  • icms_core_Security
  • icms_core_Session
  • icms_core_StopSpammer
  • icms_core_Textsanitizer
  • icms_core_Versionchecker
  • icms_data_avatar_Handler
  • icms_data_avatar_Object
  • icms_data_comment_Handler
  • icms_data_comment_Object
  • icms_data_comment_Renderer
  • icms_data_file_Handler
  • icms_data_file_Object
  • icms_data_notification_Handler
  • icms_data_notification_Object
  • icms_data_page_Handler
  • icms_data_page_Object
  • icms_data_privmessage_Handler
  • icms_data_privmessage_Object
  • icms_data_urllink_Handler
  • icms_data_urllink_Object
  • icms_db_Connection
  • icms_db_criteria_Compo
  • icms_db_criteria_Element
  • icms_db_criteria_Item
  • icms_db_Factory
  • icms_db_legacy_Database
  • icms_db_legacy_Factory
  • icms_db_legacy_mysql_Database
  • icms_db_legacy_mysql_Proxy
  • icms_db_legacy_mysql_Safe
  • icms_db_legacy_mysql_Utility
  • icms_db_legacy_PdoDatabase
  • icms_db_legacy_updater_Handler
  • icms_db_legacy_updater_Table
  • icms_db_mysql_Connection
  • icms_db_mysql_Utility
  • icms_Event
  • icms_feeds_Rss
  • icms_feeds_Simplerss
  • icms_file_DownloadHandler
  • icms_file_MediaUploadHandler
  • icms_file_TarDownloader
  • icms_file_TarFileHandler
  • icms_file_ZipDownloader
  • icms_file_ZipFileHandler
  • icms_form_Base
  • icms_form_Element
  • icms_form_elements_Button
  • icms_form_elements_Captcha
  • icms_form_elements_captcha_Image
  • icms_form_elements_captcha_ImageHandler
  • icms_form_elements_captcha_Object
  • icms_form_elements_captcha_Text
  • icms_form_elements_Checkbox
  • icms_form_elements_Colorpicker
  • icms_form_elements_Date
  • icms_form_elements_Datetime
  • icms_form_elements_Dhtmltextarea
  • icms_form_elements_Editor
  • icms_form_elements_File
  • icms_form_elements_Groupperm
  • icms_form_elements_Hidden
  • icms_form_elements_Hiddentoken
  • icms_form_elements_Label
  • icms_form_elements_Password
  • icms_form_elements_Radio
  • icms_form_elements_Radioyn
  • icms_form_elements_Select
  • icms_form_elements_select_Country
  • icms_form_elements_select_Editor
  • icms_form_elements_select_Group
  • icms_form_elements_select_Image
  • icms_form_elements_select_Lang
  • icms_form_elements_select_Matchoption
  • icms_form_elements_select_Theme
  • icms_form_elements_select_Timezone
  • icms_form_elements_select_User
  • icms_form_elements_Text
  • icms_form_elements_Textarea
  • icms_form_elements_Tray
  • icms_form_Groupperm
  • icms_form_Simple
  • icms_form_Table
  • icms_form_Theme
  • icms_image_category_Handler
  • icms_image_category_Object
  • icms_image_Handler
  • icms_image_Object
  • icms_image_set_Handler
  • icms_image_set_Object
  • icms_ipf_About
  • icms_ipf_category_Handler
  • icms_ipf_category_Object
  • icms_ipf_Controller
  • icms_ipf_export_Handler
  • icms_ipf_export_Renderer
  • icms_ipf_form_Base
  • icms_ipf_form_elements_Autocomplete
  • icms_ipf_form_elements_Blockoptions
  • icms_ipf_form_elements_Checkbox
  • icms_ipf_form_elements_Date
  • icms_ipf_form_elements_Datetime
  • icms_ipf_form_elements_File
  • icms_ipf_form_elements_Fileupload
  • icms_ipf_form_elements_Image
  • icms_ipf_form_elements_Imageupload
  • icms_ipf_form_elements_Language
  • icms_ipf_form_elements_Page
  • icms_ipf_form_elements_Parentcategory
  • icms_ipf_form_elements_Passwordtray
  • icms_ipf_form_elements_Radio
  • icms_ipf_form_elements_Richfile
  • icms_ipf_form_elements_Section
  • icms_ipf_form_elements_Select
  • icms_ipf_form_elements_Selectmulti
  • icms_ipf_form_elements_Signature
  • icms_ipf_form_elements_Source
  • icms_ipf_form_elements_Text
  • icms_ipf_form_elements_Time
  • icms_ipf_form_elements_Upload
  • icms_ipf_form_elements_Urllink
  • icms_ipf_form_elements_User
  • icms_ipf_form_elements_Yesno
  • icms_ipf_form_Secure
  • icms_ipf_Handler
  • icms_ipf_Highlighter
  • icms_ipf_member_Handler
  • icms_ipf_Metagen
  • icms_ipf_Object
  • icms_ipf_permission_Handler
  • icms_ipf_registry_Handler
  • icms_ipf_seo_Object
  • icms_ipf_Tree
  • icms_ipf_view_Column
  • icms_ipf_view_Row
  • icms_ipf_view_Single
  • icms_ipf_view_Table
  • icms_ipf_view_Tree
  • icms_member_group_Handler
  • icms_member_group_membership_Handler
  • icms_member_group_membership_Object
  • icms_member_group_Object
  • icms_member_groupperm_Handler
  • icms_member_groupperm_Object
  • icms_member_Handler
  • icms_member_user_Handler
  • icms_member_user_Object
  • icms_messaging_EmailHandler
  • icms_messaging_Handler
  • icms_module_Handler
  • icms_module_Object
  • icms_plugins_EditorHandler
  • icms_plugins_Handler
  • icms_plugins_Object
  • icms_preload_Handler
  • icms_preload_Item
  • icms_preload_LibrariesHandler
  • icms_sys_autotasks_System
  • icms_Utils
  • icms_view_block_Handler
  • icms_view_block_Object
  • icms_view_block_position_Handler
  • icms_view_block_position_Object
  • icms_view_Breadcrumb
  • icms_view_PageBuilder
  • icms_view_PageNav
  • icms_view_Printerfriendly
  • icms_view_template_file_Handler
  • icms_view_template_file_Object
  • icms_view_template_set_Handler
  • icms_view_template_set_Object
  • icms_view_theme_Factory
  • icms_view_theme_Object
  • icms_view_Tpl
  • icms_view_Tree

Interfaces

  • icms_db_IConnection
  • icms_db_IUtility
  • icms_db_legacy_IDatabase
  • icms_sys_autotasks_ISystem
  • Overview
  • Package
  • Class
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682: 683: 684: 685: 686: 687: 688: 
<?php
/**
 *
 */
/*
 package::i.tools

 php-downloader v1.0    -   www.ipunkt.biz

 (c)    2002 - www.ipunkt.biz (rok)

 =======================================================================
 Name:
 tar Class

 Author:
 Josh Barger <joshb@npt.com>

 Description:
 This class reads and writes Tape-Archive (TAR) Files and Gzip
 compressed TAR files, which are mainly used on UNIX systems.
 This class works on both windows AND unix systems, and does
 NOT rely on external applications!! Woohoo!

 Usage:
 Copyright (C) 2002  Josh Barger

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details at:
 http://www.gnu.org/copyleft/lesser.html

 If you use this script in your application/website, please
 send me an e-mail letting me know about it :)

 Bugs:
 Please report any bugs you might find to my e-mail address
 at joshb@npt.com.  If you have already created a fix/patch
 for the bug, please do send it to me so I can incorporate it into my release.

 Version History:
 1.0    04/10/2002  - InitialRelease

 2.0    04/11/2002  - Merged both tarReader and tarWriter
 classes into one
 - Added support for gzipped tar files
 Remember to name for .tar.gz or .tgz
 if you use gzip compression!
 :: THIS REQUIRES ZLIB EXTENSION ::
 - Added additional comments to
 functions to help users
 - Added ability to remove files and
 directories from archive
 2.1    04/12/2002  - Fixed serious bug in generating tar
 - Created another example file
 - Added check to make sure ZLIB is
 installed before running GZIP
 compression on TAR
 2.2    05/07/2002  - Added automatic detection of Gzipped
 tar files (Thanks go to Jidgen Falch
 for the idea)
 - Changed "private" functions to have
 special function names beginning with
 two underscores
 =======================================================================
 XOOPS changes onokazu <webmaster@xoops.org>

 12/25/2002 - Added flag to addFile() function for binary files

 =======================================================================
 */

/**
 * tar Class
 *
 * This class reads and writes Tape-Archive (TAR) Files and Gzip
 * compressed TAR files, which are mainly used on UNIX systems.
 * This class works on both windows AND unix systems, and does
 * NOT rely on external applications!! Woohoo!
 *
 * @author  Josh Barger <joshb@npt.com>
 * @copyright   Copyright (C) 2002  Josh Barger
 * @category    ICMS
 * @package     File
 *
 */
class icms_file_TarFileHandler {
    /**#@+
     * Unprocessed Archive Information
     */
    private $filename;
    private $isGzipped;
    private $tar_file;
    /**#@-*/

    /**#@+
     * Processed Archive Information
     */
    public $files;
    private $directories;
    public $numFiles;
    private $numDirectories;
    /**#@-*/

    /**
     * Class Constructor -- Does nothing...
     */
    public function __construct() {
        return true;
    }

    /**
     * Computes the unsigned Checksum of a file's header
     * to try to ensure valid file
     *
     * @param   string  $bytestring
     *
     */
    private function __computeUnsignedChecksum($bytestring) {
        $unsigned_chksum = '';
        for ($i=0; $i<512; $i++) {
            $unsigned_chksum += ord($bytestring[$i]);
        }
        for ($i=0; $i<8; $i++) {
            $unsigned_chksum -= ord($bytestring[148 + $i]);
        }
        $unsigned_chksum += ord(" ") * 8;

        return $unsigned_chksum;
    }

    /**
     * Converts a NULL padded string to a non-NULL padded string
     *
     * @param   string  $string
     *
     * @return  string
     *
     */
    private function __parseNullPaddedString($string) {
        $position = strpos($string, chr(0));
        return substr($string, 0, $position);
    }

    /**
     * This function parses the current TAR file
     *
     * @return  bool    always TRUE
     *
     */
    private function __parseTar() {
        // Read Files from archive
        $tar_length = strlen($this->tar_file);
        $main_offset = 0;
        $this->numFiles = 0;
        while ($main_offset < $tar_length) {
            // If we read a block of 512 nulls, we are at the end of the archive
            if (substr($this->tar_file, $main_offset, 512) == str_repeat(chr(0), 512))
            break;

            // Parse file name
            $file_name = self::__parseNullPaddedString(substr($this->tar_file, $main_offset, 100));

            // Parse the file mode
            $file_mode = substr($this->tar_file, $main_offset + 100, 8);

            // Parse the file user ID
            $file_uid = octdec(substr($this->tar_file, $main_offset + 108, 8));

            // Parse the file group ID
            $file_gid = octdec(substr($this->tar_file, $main_offset + 116, 8));

            // Parse the file size
            $file_size = octdec(substr($this->tar_file, $main_offset + 124, 12));

            // Parse the file update time - unix timestamp format
            $file_time = octdec(substr($this->tar_file, $main_offset + 136, 12));

            // Parse Checksum
            $file_chksum = octdec(substr($this->tar_file, $main_offset + 148, 6));

            // Parse user name
            $file_uname = self::__parseNullPaddedString(substr($this->tar_file, $main_offset + 265, 32));

            // Parse Group name
            $file_gname = self::__parseNullPaddedString(substr($this->tar_file, $main_offset + 297, 32));

            // Make sure our file is valid
            if (self::__computeUnsignedChecksum(substr($this->tar_file, $main_offset, 512)) != $file_chksum) {
                return false;
            }

            // Parse File Contents
            $file_contents      = substr($this->tar_file, $main_offset + 512, $file_size);

            /*  ### Unused Header Information ###
                $activeFile["typeflag"]     = substr($this->tar_file,$main_offset + 156,1);
                $activeFile["linkname"]     = substr($this->tar_file,$main_offset + 157,100);
                $activeFile["magic"]        = substr($this->tar_file,$main_offset + 257,6);
                $activeFile["version"]      = substr($this->tar_file,$main_offset + 263,2);
                $activeFile["devmajor"]     = substr($this->tar_file,$main_offset + 329,8);
                $activeFile["devminor"]     = substr($this->tar_file,$main_offset + 337,8);
                $activeFile["prefix"]       = substr($this->tar_file,$main_offset + 345,155);
                $activeFile["endheader"]    = substr($this->tar_file,$main_offset + 500,12);
                */

            if ($file_size > 0) {
                // Increment number of files
                $this->numFiles++;

                // Create us a new file in our array
                $activeFile = &$this->files[];

                // Asign Values
                $activeFile["name"] = $file_name;
                $activeFile["mode"] = $file_mode;
                $activeFile["size"] = $file_size;
                $activeFile["time"] = $file_time;
                $activeFile["user_id"] = $file_uid;
                $activeFile["group_id"] = $file_gid;
                $activeFile["user_name"] = $file_uname;
                $activeFile["group_name"] = $file_gname;
                $activeFile["checksum"] = $file_chksum;
                $activeFile["file"] = $file_contents;
            } else {
                // Increment number of directories
                $this->numDirectories++;

                // Create a new directory in our array
                $activeDir = &$this->directories[];

                // Assign values
                $activeDir["name"] = $file_name;
                $activeDir["mode"] = $file_mode;
                $activeDir["time"] = $file_time;
                $activeDir["user_id"] = $file_uid;
                $activeDir["group_id"] = $file_gid;
                $activeDir["user_name"] = $file_uname;
                $activeDir["group_name"] = $file_gname;
                $activeDir["checksum"] = $file_chksum;
            }

            // Move our offset the number of blocks we have processed
            $main_offset += 512 + (ceil($file_size / 512) * 512);
        }

        return true;
    }

    /**
     * Read a non gzipped tar file in for processing.
     *
     * @param   string  $filename   full filename
     * @return  bool    always TRUE
     *
     */
    private function __readTar($filename='') {
        // Set the filename to load
        if (!$filename) {
            $filename = $this->filename;
        }

        // Read in the TAR file
        $fp = fopen($filename, "rb");
        $this->tar_file = fread($fp, filesize($filename));
        fclose($fp);

        if ($this->tar_file[0] == chr(31) && $this->tar_file[1] == chr(139) && $this->tar_file[2] == chr(8)) {
            if (!function_exists("gzinflate")) {
                return false;
            }

            $this->isGzipped = true;

            $this->tar_file = gzinflate(substr($this->tar_file, 10, -4));
        }

        // Parse the TAR file
        self::__parseTar();

        return true;
    }

    /**
     * Generates a TAR file from the processed data
     *
     * @return  bool    always TRUE
     *
     */
    private function __generateTAR() {
        // Clear any data currently in $this->tar_file
        unset($this->tar_file);

        // Generate Records for each directory, if we have directories
        if ($this->numDirectories > 0) {
            foreach ($this->directories as $key => $information) {
                unset($header);

                // Generate tar header for this directory
                // Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
                $header .= str_pad($information["name"], 100, chr(0));
                $header .= str_pad(decoct($information["mode"]), 7, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_pad(decoct($information["user_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_pad(decoct($information["group_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_pad(decoct(0), 11, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_pad(decoct($information["time"]), 11, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_repeat(" ", 8);
                $header .= "5";
                $header .= str_repeat(chr(0), 100);
                $header .= str_pad("ustar", 6, chr(32));
                $header .= chr(32) . chr(0);
                $header .= str_pad("", 32, chr(0));
                $header .= str_pad("", 32, chr(0));
                $header .= str_repeat(chr(0), 8);
                $header .= str_repeat(chr(0), 8);
                $header .= str_repeat(chr(0), 155);
                $header .= str_repeat(chr(0), 12);

                // Compute header checksum
                $checksum = str_pad(decoct(self::__computeUnsignedChecksum($header)), 6, "0", STR_PAD_LEFT);
                for ($i=0; $i<6; $i++) {
                    $header[(148 + $i)] = substr($checksum, $i, 1);
                }
                $header[154] = chr(0);
                $header[155] = chr(32);

                // Add new tar formatted data to tar file contents
                $this->tar_file .= $header;
            }
        }

        // Generate Records for each file, if we have files (We should...)
        if ($this->numFiles > 0) {
            $this->tar_file = '';
            foreach ($this->files as $key => $information) {
                unset($header);

                // Generate the TAR header for this file
                // Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
                $header = str_pad($information["name"], 100, chr(0));
                $header .= str_pad(decoct($information["mode"]), 7, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_pad(decoct($information["user_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_pad(decoct($information["group_id"]), 7, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_pad(decoct($information["size"]), 11, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_pad(decoct($information["time"]), 11, "0", STR_PAD_LEFT) . chr(0);
                $header .= str_repeat(" ", 8);
                $header .= "0";
                $header .= str_repeat(chr(0), 100);
                $header .= str_pad("ustar", 6, chr(32));
                $header .= chr(32) . chr(0);
                $header .= str_pad($information["user_name"], 32, chr(0));  // How do I get a file's user name from PHP?
                $header .= str_pad($information["group_name"], 32, chr(0)); // How do I get a file's group name from PHP?
                $header .= str_repeat(chr(0), 8);
                $header .= str_repeat(chr(0), 8);
                $header .= str_repeat(chr(0), 155);
                $header .= str_repeat(chr(0), 12);

                // Compute header checksum
                $checksum = str_pad(decoct(self::__computeUnsignedChecksum($header)), 6, "0", STR_PAD_LEFT);
                for ($i=0; $i<6; $i++) {
                    $header[(148 + $i)] = substr($checksum, $i, 1);
                }
                $header[154] = chr(0);
                $header[155] = chr(32);

                // Pad file contents to byte count divisible by 512
                $file_contents = str_pad($information["file"], (ceil($information["size"] / 512) * 512), chr(0));

                // Add new tar formatted data to tar file contents
                $this->tar_file .= $header . $file_contents;
            }
        }

        // Add 512 bytes of NULLs to designate EOF
        $this->tar_file .= str_repeat(chr(0), 512);

        return true;
    }

    /**
     * Open a TAR file
     *
     * @param   string  $filename
     * @return  bool
     */
    public function openTAR($filename) {
        // Clear any values from previous tar archives
        unset($this->filename);
        unset($this->isGzipped);
        unset($this->tar_file);
        unset($this->files);
        unset($this->directories);
        unset($this->numFiles);
        unset($this->numDirectories);

        // If the tar file doesn't exist...
        if (!file_exists($filename)) {
            return false;
        }

        $this->filename = $filename;

        // Parse this file
        self::__readTar();

        return true;
    }

    /**
     * Appends a tar file to the end of the currently opened tar file.
     *
     * @param   string  $filename
     * @return  bool
     */
    public function appendTar($filename) {
        // If the tar file doesn't exist...
        if (!file_exists($filename)) return false;

        self::__readTar($filename);

        return true;
    }

    /**
     * Retrieves information about a file in the current tar archive
     *
     * @param   string  $filename
     * @return  string  FALSE on fail
     */
    public function getFile($filename) {
        if ($this->numFiles > 0) {
            foreach ($this->files as $key => $information) {
                if ($information["name"] == $filename) return $information;
            }
        }

        return false;
    }

    /**
     * Retrieves information about a directory in the current tar archive
     *
     * @param   string  $dirname
     * @return  string  FALSE on fail
     */
    public function getDirectory($dirname) {
        if ($this->numDirectories > 0) {
            foreach ($this->directories as $key => $information) {
                if ($information["name"] == $dirname) return $information;
            }
        }

        return false;
    }

    /**
     * Check if this tar archive contains a specific file
     *
     * @param   string  $filename
     * @return  bool
     */
    public function containsFile($filename) {
        if ($this->numFiles > 0) {
            foreach ($this->files as $key => $information) {
                if ($information["name"] == $filename)
                return true;
            }
        }
        return false;
    }

    /**
     * Check if this tar archive contains a specific directory
     *
     * @param   string  $dirname
     * @return  bool
     */
    public function containsDirectory($dirname) {
        if ($this->numDirectories > 0) {
            foreach ($this->directories as $key => $information) {
                if ($information["name"] == $dirname) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Add a directory to this tar archive
     *
     * @param   string  $dirname
     * @return  bool
     */
    public function addDirectory($dirname) {
        if (!file_exists($dirname)) {
            return false;
        }

        // Get directory information
        $file_information = stat($dirname);

        // Add directory to processed data
        $this->numDirectories++;
        $activeDir = &$this->directories[];
        $activeDir["name"] = $dirname;
        $activeDir["mode"] = $file_information["mode"];
        $activeDir["time"] = $file_information["time"];
        $activeDir["user_id"] = $file_information["uid"];
        $activeDir["group_id"] = $file_information["gid"];
        $activeDir["checksum"] = $checksum;

        return true;
    }

    /**
     * Add a file to the tar archive
     *
     * @param   string  $filename
     * @param   boolean $binary     Binary file?
     * @return  bool
     */
    public function addFile($filename, $binary = false) {
        // Make sure the file we are adding exists!
        if (!file_exists($filename)) {
            return false;
        }

        // Make sure there are no other files in the archive that have this same filename
        if (self::containsFile($filename)) {
            return false;
        }

        // Get file information
        $file_information = stat($filename);

        // Read in the file's contents
        if (!$binary) {
            $fp = fopen($filename, "r");
        } else {
            $fp = fopen($filename, "rb");
        }
        $file_contents = fread($fp, filesize($filename));
        fclose($fp);

        // Add file to processed data
        $this->numFiles++;
        $activeFile = &$this->files[];
        $activeFile["name"] = $filename;
        $activeFile["mode"] = $file_information["mode"];
        $activeFile["user_id"] = $file_information["uid"];
        $activeFile["group_id"] = $file_information["gid"];
        $activeFile["size"] = $file_information["size"];
        $activeFile["time"] = $file_information["mtime"];
        $activeFile["checksum"] = isset($checksum) ? $checksum : '';
        $activeFile["user_name"] = "";
        $activeFile["group_name"] = "";
        $activeFile["file"] = trim($file_contents);

        return true;
    }

    /**
     * Remove a file from the tar archive
     *
     * @param   string  $filename
     * @return  bool
     */
    public function removeFile($filename) {
        if ($this->numFiles > 0) {
            foreach ($this->files as $key => $information) {
                if ($information["name"] == $filename) {
                    $this->numFiles--;
                    unset($this->files[$key]);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Remove a directory from the tar archive
     *
     * @param   string  $dirname
     * @return  bool
     */
    public function removeDirectory($dirname) {
        if ($this->numDirectories > 0) {
            foreach ($this->directories as $key => $information) {
                if ($information["name"] == $dirname) {
                    $this->numDirectories--;
                    unset($this->directories[$key]);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Write the currently loaded tar archive to disk
     *
     * @return  bool
     */
    public function saveTar() {
        if (!$this->filename) {
            return false;
        }

        // Write tar to current file using specified gzip compression
        self::toTar($this->filename, $this->isGzipped);

        return true;
    }

    /**
     * Saves tar archive to a different file than the current file
     *
     * @param   string  $filename
     * @param   bool    $useGzip    Use GZ compression?
     * @return  bool
     */
    public function toTar($filename, $useGzip) {
        if (!$filename) {
            return false;
        }

        // Encode processed files into TAR file format
        self::__generateTar();

        // GZ Compress the data if we need to
        if ($useGzip) {
            // Make sure we have gzip support
            if (!function_exists("gzencode")) {
                return false;
            }

            $file = gzencode($this->tar_file);
        } else {
            $file = $this->tar_file;
        }

        // Write the TAR file
        $fp = fopen($filename, "wb");
        fwrite($fp, $file);
        fclose($fp);

        return true;
    }

    /**
     * Sends tar archive to stdout
     *
     * @param   string  $filename
     * @param   bool    $useGzip    Use GZ compression?
     * @return  string
     */
    public function toTarOutput($filename, $useGzip) {
        if (!$filename) {
            return false;
        }

        // Encode processed files into TAR file format
        self::__generateTar();

        // GZ Compress the data if we need to
        if ($useGzip) {
            // Make sure we have gzip support
            if (!function_exists("gzencode")) {
                return false;
            }

            $file = gzencode($this->tar_file);
        } else {
            $file = $this->tar_file;
        }

        return $file;
    }
}
API documentation generated by ApiGen