diff options
| author | pabs <pabs@pablotron.org> | 2007-08-23 03:17:11 -0400 | 
|---|---|---|
| committer | pabs <pabs@pablotron.org> | 2007-08-23 03:17:11 -0400 | 
| commit | c3a6497713aa6fd6ba90540f734cad25fbcbb23a (patch) | |
| tree | 752c29798b811649124ae584d12e41dbf758c68f | |
| parent | 86382ea71cf242b15efd86b6bc2555ede8f451c0 (diff) | |
| download | zipstream-php-c3a6497713aa6fd6ba90540f734cad25fbcbb23a.tar.xz zipstream-php-c3a6497713aa6fd6ba90540f734cad25fbcbb23a.zip  | |
api cleanup.  added full documentation.
| -rw-r--r-- | zipstream.php | 216 | 
1 files changed, 162 insertions, 54 deletions
diff --git a/zipstream.php b/zipstream.php index 9323569..39173ec 100644 --- a/zipstream.php +++ b/zipstream.php @@ -6,27 +6,96 @@  #  # Usage:  # +# Streaming zip archives is a simple, three-step process: +# +# 1.  Create the zip stream: +# +#     $zip = new ZipStream('example.zip'); +# +# 2.  Add one or more files to the archive: +# +#     # add first file +#     $data = file_get_contents('some_file.gif'); +#     $zip->add_file('some_file.gif', $data); +# +#     # add second file +#     $data = file_get_contents('some_file.gif'); +#     $zip->add_file('another_file.png', $data); +# +# 3.  Finish the zip stream: +# +#     $zip->finish(); +# +# You can also add an archive comment, add comments to individual files, +# and adjust the timestamp of files.  See the API documentation below +# for additional information. +# +# Example: +#  #   # create a new zip stream object -#   $zs = new ZipStream(); +#   $zip = new ZipStream('some_files.zip');  #  #   # list of local files  #   $files = array('foo.txt', 'bar.jpg');  #  #   # read and add each file to the archive  #   foreach ($files as $path) -#     $zs->add_file($path, file_get_contents($path)); +#     $zip->add_file($path, file_get_contents($path));  #   #   # write archive footer to stream -#   $zs->finish(); +#   $zip->finish();  #  class ZipStream { -  var $files = array(), +  var $opt = array(), +      $files = array(),        $cdr_ofs = 0,        $ofs = 0;  -  function ZipStream($name = 'untitled.zip', $send_http_headers = false) { +  # +  # Create a new ZipStream object. +  # +  # Parameters: +  # +  #   $name - Name of output file (optional). +  #   $opt  - Hash of archive options (optional, see "Archive Options" +  #           below). +  # +  # Archive Options: +  # +  #   comment             - Comment for this archive. +  #   content_type        - HTTP Content-Type.  Defaults to 'application/x-zip'. +  #   content_disposition - HTTP Content-Disposition.  Defaults to  +  #                         'attachment; filename=\"FILENAME\"', where +  #                         FILENAME is the specified filename. +  #   send_http_headers   - Boolean indicating whether or not to send +  #                         the HTTP headers for this file. +  # +  # Note that content_type and content_disposition do nothing if you are +  # not sending HTTP headers. +  # +  # Examples: +  # +  #   # create a new zip file named 'foo.zip' +  #   $zip = new ZipStream('foo.zip'); +  # +  #   # create a new zip file named 'bar.zip' with a comment +  #   $zip = new ZipStream('bar.zip', array( +  #     'comment' => 'this is a comment for the zip file.', +  #   )); +  # +  # Notes: +  # +  # If you do not set a filename, then this library _DOES NOT_ send HTTP +  # headers by default.  This behavior is to allow software to send its +  # own headers (including the filename), and still use this library. +  # +  function ZipStream($name = null, $opt = array()) { +    # save options +    $this->opt = $opt; +      $this->output_name = $name; -    $this->need_headers = $send_http_headers;  +    if ($name || $opt['send_http_headers']) +      $this->need_headers = true;     }    # @@ -36,16 +105,30 @@ class ZipStream {    #       #  $name - path of file in archive (including directory).    #  $data - contents of file -  #  $time - last-modified timestamp of file (optional) +  #  $opt  - Hash of options for file (optional, see "File Options" +  #          below).      # -  # Example: +  # File Options:  +  #  time     - Last-modified timestamp (seconds since the epoch) of +  #             this file.  Defaults to the current time. +  #  comment  - Comment related to this file. +  # +  # Examples:    # +  #   # add a file named 'foo.txt'    #   $data = file_get_contents('foo.txt'); -  #   $zs->add_file('foo.txt', $data); +  #   $zip->add_file('foo.txt', $data);    #  -  function add_file($name, $data, $time = 0) { +  #   # add a file named 'bar.jpg' with a comment and a last-modified +  #   # time of two hours ago +  #   $data = file_get_contents('bar.jpg'); +  #   $zip->add_file('bar.jpg', $data, array( +  #     'time'    => time() - 2 * 3600, +  #     'comment' => 'this is a comment about bar.jpg', +  #   )); +  #  +  function add_file($name, $data, $opt = array()) {      # compress data -    # $zdata = substr(gzcompress($data), 2, -4);      $zdata = gzdeflate($data);      # calculate header attributes @@ -55,8 +138,8 @@ class ZipStream {      $len  = strlen($data);      # create dos timestamp -    $time = $time ? $time : time(); -    $dts = $this->dostime($time); +    $opt['time'] = $opt['time'] ? $opt['time'] : time(); +    $dts = $this->dostime($opt['time']);      # build file header      $fields = array(              # (from V.A of APPNOTE.TXT) @@ -76,7 +159,7 @@ class ZipStream {      $ret = $this->pack_fields($fields) . $name . $zdata;      # add to central directory record and increment offset -    $this->add_to_cdr($name, $time, $crc, $zlen, $len, strlen($ret)); +    $this->add_to_cdr($name, $opt, $crc, $zlen, $len, strlen($ret));      # print data      $this->send($ret); @@ -90,63 +173,55 @@ class ZipStream {    #   # add a list of files to the archive    #   $files = array('foo.txt', 'bar.jpg');    #   foreach ($files as $path) -  #     $zs->add_file($path, file_get_contents($path)); +  #     $zip->add_file($path, file_get_contents($path));    #     #   # write footer to stream -  #   $zs->finish(); +  #   $zip->finish();    #  -  function finish($opt = null) { -    $this->add_cdr($opt); +  function finish() { +    $this->add_cdr($this->opt);      $this->clear();    } -  function send_http_headers($name = 'untitled.zip') { -    $headers = array( -      'Content-Type'              => 'application/x-zip', -      'Content-Disposition'       => "attachment; filename=\"{$name}\"", -      'Pragma'                    => 'public', -      'Cache-Control'             => 'public, must-revalidate', -      'Content-Transfer-Encoding' => 'binary', -    ); - -    foreach ($headers as $key => $val) -      header("$key: $val"); -  } -    ###################    # PRIVATE METHODS #    ################### -  function add_to_cdr($name, $time, $crc, $zlen, $len, $rec_len) { -    $this->files[] = array($name, $time, $crc, $zlen, $len, $this->ofs); +  function add_to_cdr($name, $opt, $crc, $zlen, $len, $rec_len) { +    $this->files[] = array($name, $opt, $crc, $zlen, $len, $this->ofs);      $this->ofs += $rec_len;    }    function add_cdr_file($args) { -    list ($name, $time, $crc, $zlen, $len, $ofs) = $args; -    $dts = $this->dostime($time); +    list ($name, $opt, $crc, $zlen, $len, $ofs) = $args; + +    # get attributes +    $comment = $opt['comment'] ? $opt['comment'] : ''; + +    # get dos timestamp +    $dts = $this->dostime($opt['time']);      $fields = array(              # (from V,F of APPNOTE.TXT) -      array('V', 0x02014b50),     # central file header signature -      array('v', 0x00),           # version made by -      array('v', 0x14),           # version needed to extract -      array('v', 0x00),           # general purpose bit flag -      array('v', 0x08),           # compresion method (deflate) -      array('V', $dts),           # dos timestamp -      array('V', $crc),           # crc32 of data -      array('V', $zlen),          # compressed data length -      array('V', $len),           # uncompressed data length -      array('v', strlen($name)),  # filename length -      array('v', 0),              # extra data len -      array('v', 0),              # file comment length -      array('v', 0),              # disk number start -      array('v', 0),              # internal file attributes -      array('V', 32),             # external file attributes -      array('V', $ofs),           # relative offset of local header +      array('V', 0x02014b50),           # central file header signature +      array('v', 0x00),                 # version made by +      array('v', 0x14),                 # version needed to extract +      array('v', 0x00),                 # general purpose bit flag +      array('v', 0x08),                 # compresion method (deflate) +      array('V', $dts),                 # dos timestamp +      array('V', $crc),                 # crc32 of data +      array('V', $zlen),                # compressed data length +      array('V', $len),                 # uncompressed data length +      array('v', strlen($name)),        # filename length +      array('v', 0),                    # extra data len +      array('v', strlen($comment)),     # file comment length +      array('v', 0),                    # disk number start +      array('v', 0),                    # internal file attributes +      array('V', 32),                   # external file attributes +      array('V', $ofs),                 # relative offset of local header      ); -    # pack fields and append name -    $ret = $this->pack_fields($fields) . $name; +    # pack fields, then append name and comment +    $ret = $this->pack_fields($fields) . $name . $comment;      $this->send($ret); @@ -191,9 +266,42 @@ class ZipStream {      $this->cdr_ofs = 0;    } +  ########################### +  # PRIVATE UTILITY METHODS # +  ########################### + +  function send_http_headers() { +    # grab options +    $opt = $this->opt; +     +    # grab content type from options +    $content_type = 'application/x-zip', +    if ($opt['content_type']) +      $content_type = $this->opt['content_type']; + +    # grab content disposition  +    $disposition = 'attachment'; +    if ($opt['content_disposition']) +      $disposition = $opt['content_disposition']; + +    if ($this->output_name)  +      $disposition .= "; filename=\"{$this->output_name}\""; + +    $headers = array( +      'Content-Type'              => $content_type, +      'Content-Disposition'       => $disposition, +      'Pragma'                    => 'public', +      'Cache-Control'             => 'public, must-revalidate', +      'Content-Transfer-Encoding' => 'binary', +    ); + +    foreach ($headers as $key => $val) +      header("$key: $val"); +  } +    function send($str) {      if ($this->need_headers) -      $this->send_http_headers($this->output_name); +      $this->send_http_headers();      $this->need_headers = false;      echo $str;  | 
