Import Horde_Compress:: from CVS HEAD
authorMichael M Slusarz <slusarz@curecanti.org>
Mon, 13 Jul 2009 21:11:07 +0000 (15:11 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Mon, 13 Jul 2009 21:11:07 +0000 (15:11 -0600)
13 files changed:
framework/Compress/lib/Horde/Compress.php [new file with mode: 0644]
framework/Compress/lib/Horde/Compress/Dbx.php [new file with mode: 0644]
framework/Compress/lib/Horde/Compress/Gzip.php [new file with mode: 0644]
framework/Compress/lib/Horde/Compress/Rar.php [new file with mode: 0644]
framework/Compress/lib/Horde/Compress/Tar.php [new file with mode: 0644]
framework/Compress/lib/Horde/Compress/Tnef.php [new file with mode: 0644]
framework/Compress/lib/Horde/Compress/Zip.php [new file with mode: 0644]
framework/Compress/package.xml [new file with mode: 0644]
framework/Mime/lib/Horde/Mime/Viewer/Ooo.php
framework/Mime/lib/Horde/Mime/Viewer/Rar.php
framework/Mime/lib/Horde/Mime/Viewer/Tgz.php
framework/Mime/lib/Horde/Mime/Viewer/Tnef.php
framework/Mime/lib/Horde/Mime/Viewer/Zip.php

diff --git a/framework/Compress/lib/Horde/Compress.php b/framework/Compress/lib/Horde/Compress.php
new file mode 100644 (file)
index 0000000..e7328e8
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/**
+ * The Horde_Compress:: class provides an API for various compression
+ * techniques that can be used by Horde applications.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Horde_Compress
+ */
+class Horde_Compress
+{
+    /**
+     * Attempts to return a concrete instance based on $driver.
+     *
+     * @param mixed $driver  The type of concrete subclass to
+     *                       return. If $driver is an array, then we will look
+     *                       in $driver[0]/lib/Compress/ for the subclass
+     *                       implementation named $driver[1].php.
+     * @param array $params  A hash containing any additional configuration or
+     *                       parameters a subclass might need.
+     *
+     * @return Horde_Compress  The newly created concrete instance.
+     * @throws Horde_Exception
+     */
+    static public function factory($driver, $params = null)
+    {
+        if (is_array($driver)) {
+            list($app, $driv_name) = $driver;
+            $driver = basename($driv_name);
+        } else {
+            $driver = basename($driver);
+        }
+
+        $class = (empty($app) ? 'Horde' : $app) . '_Auth_' . ucfirst($driver);
+
+        if (class_exists($class)) {
+            return new $class($params);
+        }
+
+        throw new Horde_Exception('Class definition of ' . $class . ' not found.');
+    }
+
+    /**
+     * Compress the data.
+     *
+     * @param string $data   The data to compress.
+     * @param array $params  An array of arguments needed to compress the data.
+     *
+     * @return mixed  The compressed data.
+     * @throws Horde_Exception
+     */
+    public function compress($data, $params = array())
+    {
+        return $data;
+    }
+
+    /**
+     * Decompress the data.
+     *
+     * @param string $data   The data to decompress.
+     * @param array $params  An array of arguments needed to decompress the
+     *                       data.
+     *
+     * @return array  The decompressed data.
+     * @throws Horde_Exception
+     */
+    public function decompress($data, $params = array())
+    {
+        return $data;
+    }
+
+}
diff --git a/framework/Compress/lib/Horde/Compress/Dbx.php b/framework/Compress/lib/Horde/Compress/Dbx.php
new file mode 100644 (file)
index 0000000..39c6fc0
--- /dev/null
@@ -0,0 +1,271 @@
+<?php
+/**
+ * The Horde_Compress_Dbx class allows dbx files (e.g. from Outlook Express)
+ * to be read.
+ *
+ * This class is based on code by:
+ * Antony Raijekov <dev@strategma.bg>
+ * http://uruds.gateway.bg/zeos/
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Compress
+ */
+class Horde_Compress_Dbx extends Horde_Compress
+{
+    /**
+     * TODO
+     *
+     * @var array
+     */
+    protected $_flagArray = array(
+        0x1 => 'MsgFlags',
+        0x2 => 'Sent',
+        0x4 => 'position',
+        0x7 => 'MessageID',
+        0x8 => 'Subject',
+        0x9 => 'From_reply',
+        0xA => 'References',
+        0xB => 'Newsgroup',
+        0xD => 'From',
+        0xE => 'Reply_To',
+        0x12 => 'Received',
+        0x13 => 'Receipt',
+        0x1A => 'Account',
+        0x1B => 'AccountID',
+        0x80 => 'Msg',
+        0x81 => 'MsgFlags',
+        0x84 => 'position',
+        0x91 => 'size',
+    );
+
+    /**
+     * TODO
+     *
+     * @var array
+     */
+    protected $_mails = array();
+
+    /**
+     * TODO
+     *
+     * @var array
+     */
+    protected $_tmp = array();
+
+    /**
+     * Decompresses a DBX file and gets information from it.
+     *
+     * @param string $data   The dbx file data.
+     * @param array $params  Not used.
+     *
+     * @return mixed  The requested data.
+     * @throws Horde_Exception
+     */
+    public function decompress($data, $params = null)
+    {
+        $this->_mails = $this->_tmp = array();
+
+        $position = 0xC4;
+        $header_info = unpack('Lposition/LDataLength/nHeaderLength/nFlagCount', substr($data, $position, 12));
+        $position += 12;
+
+        // Go to the first table offest and process it.
+        if ($header_info['position'] > 0) {
+            $position = 0x30;
+            $buf = unpack('Lposition', substr($data, $position, 4));
+            $position = $buf['position'];
+            $result = $this->_readIndex($data, $position);
+        }
+
+        return $this->_mails;
+    }
+
+    /**
+     * Returns a null-terminated string from the specified data.
+     *
+     * @param string $buf   TODO
+     * @param integer $pos  TODO
+     *
+     * @return string  TODO
+     */
+    protected function _readString($buf, $pos)
+    {
+        return ($len = strpos(substr($buf, $pos), chr(0)))
+            ? substr($buf, $pos, $len)
+            : '';
+    }
+
+    /**
+     * TODO
+     *
+     * @param string $data       TODO
+     * @param integer $position  TODO
+     *
+     * @return string  TODO
+     * @throws Horde_Exception
+     */
+    protected function _readMessage($data, $position)
+    {
+        $msg = '';
+        $part = 0;
+
+        if ($position > 0) {
+            $IndexItemsCount = array_pop(unpack('S', substr($data, 0xC4, 4)));
+            if ($IndexItemsCount > 0) {
+                while ($position < strlen($data)) {
+                    $part++;
+                    $s = substr($data, $position, 528);
+                    if (strlen($s) == 0) {
+                        break;
+                    }
+                    $msg_item = unpack('LFilePos/LUnknown/LItemSize/LNextItem/a512Content', $s);
+                    if ($msg_item['FilePos'] != $position) {
+                        throw new Horde_Exception(_("Invalid file format"));
+                    }
+                    $position += 528;
+                    $msg .= substr($msg_item['Content'], 0, $msg_item['ItemSize']);
+                    $position = $msg_item['NextItem'];
+                    if ($position == 0) {
+                        break;
+                    }
+                }
+            }
+        }
+
+        return $msg;
+    }
+
+    /**
+     * TODO
+     *
+     * @param string $data       TODO
+     * @param integer $position  TODO
+     *
+     * @return array  TODO
+     * @throws Horde_Exception
+     */
+    protected function _readMessageInfo($data, $position)
+    {
+        $message_info = array();
+        $msg_header = unpack('Lposition/LDataLength/SHeaderLength/SFlagCount', substr($data, $position, 12));
+        if ($msg_header['position'] != $position) {
+            throw new Horde_Exception(_("Invalid file format"));
+        }
+        $position += 12;
+        $message_info['HeaderPosition'] = $msg_header['position'];
+        $flags = $msg_header['FlagCount'] & 0xFF;
+        $DataSize = $msg_header['DataLength'] - $flags * 4;
+        $size = 4 * $flags;
+        $FlagsBuffer = substr($data, $position, $size);
+        $position += $size;
+        $size = $DataSize;
+        $DataBuffer = substr($data, $position, $size);
+        $position += $size;
+        $message_info = array();
+
+        /* Process flags */
+        for ($i = 0; $i < $flags; ++$i) {
+            $pos = 0;
+            $f = array_pop(unpack('L', substr($FlagsBuffer, $i * 4, 4)));
+
+            $mask = $f & 0xFF;
+            switch ($mask) {
+            case 0x1:
+                $pos = $pos + ($f >> 8);
+                $message_info['MsgFlags'] = array_pop(unpack('C', substr($DataBuffer, $pos++, 1)));
+                $message_info['MsgFlags'] += array_pop(unpack('C', substr($DataBuffer, $pos++, 1))) * 256;
+                $message_info['MsgFlags'] += array_pop(unpack('C', substr($DataBuffer, $pos, 1))) * 65536;
+                break;
+
+            case 0x2:
+            case 0x4:
+                $pos += array_pop(unpack('L', substr($FlagsBuffer, $i * 4, 4))) >> 8;
+                $message_info[$this->_flagArray[$mask]] = array_pop(unpack('L', substr($DataBuffer, $pos, 4)));
+                break;
+
+            case 0x7:
+            case 0x8:
+            case 0x9:
+            case 0xA:
+            case 0xB:
+            case 0xD:
+            case 0xE:
+            case 0x13:
+            case 0x1A:
+                $pos += array_pop(unpack('L', substr($FlagsBuffer, $i * 4, 4))) >> 8;
+                $message_info[$this->_flagArray[$mask]] = $this->_readString($DataBuffer, $pos);
+                break;
+
+            case 0x12:
+                $pos += array_pop(unpack('L', substr($FlagsBuffer, $i * 4, 4))) >> 8;
+                $message_info['Received'] = array_pop(unpack('L', substr($DataBuffer, $pos, 4)));
+                break;
+
+            case 0x1B:
+                $pos += array_pop(unpack('L', substr($FlagsBuffer, $i * 4, 4))) >> 8;
+                $message_info['AccountID'] = intval($this->_readString($DataBuffer, $pos));
+                break;
+
+            case 0x80:
+            case 0x81:
+            case 0x84:
+            case 0x91:
+                $message_info[$this->_flagArray[$mask]] = array_pop(unpack('L', substr($FlagsBuffer, $i * 4, 4))) >> 8;
+                break;
+            }
+        }
+
+        return $message_info;
+    }
+
+    /**
+     * TODO
+     *
+     * @param string $data       TODO
+     * @param integer $position  TODO
+     *
+     * @throws Horde_Exception
+     */
+    protected function _readIndex($data, $position)
+    {
+        $index_header = unpack('LFilePos/LUnknown1/LPrevIndex/LNextIndex/LCount/LUnknown', substr($data, $position, 24));
+        if ($index_header['FilePos'] != $position) {
+            throw new Horde_Exception(_("Invalid file format"));
+        }
+
+        // Push it into list of processed items.
+        $this->_tmp[$position] = true;
+        if (($index_header['NextIndex'] > 0) &&
+            empty($this->_tmp[$index_header['NextIndex']])) {
+            $this->_readIndex($data, $index_header['NextIndex']);
+        }
+        if (($index_header['PrevIndex'] > 0) &&
+            empty($this->_tmp[$index_header['PrevIndex']])) {
+            $this->_readIndex($data, $index_header['PrevIndex']);
+        }
+        $position += 24;
+        $icount = $index_header['Count'] >> 8;
+        if ($icount > 0) {
+            $buf = substr($data, $position, 12 * $icount);
+            for ($i = 0; $i < $icount; $i++) {
+                $hdr_buf = substr($buf, $i * 12, 12);
+                $IndexItem = unpack('LHeaderPos/LChildIndex/LUnknown', $hdr_buf);
+                if ($IndexItem['HeaderPos'] > 0) {
+                    $mail['info'] = $this->_readMessageInfo($data, $IndexItem['HeaderPos']);
+                    $mail['content'] = $this->_readMessage($data, $mail['info']['position']);
+                    $this->_mails[] = $mail;
+                }
+                if (($IndexItem['ChildIndex'] > 0) &&
+                    empty($this->_tmp[$IndexItem['ChildIndex']])) {
+                    $this->_readIndex($fp, $IndexItem['ChildIndex']);
+                }
+            }
+        }
+    }
+
+}
diff --git a/framework/Compress/lib/Horde/Compress/Gzip.php b/framework/Compress/lib/Horde/Compress/Gzip.php
new file mode 100644 (file)
index 0000000..39ffa0c
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * The Horde_Compress_Gzip class allows gzip files to be read.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Cochrane <mike@graftonhall.co.nz>
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Horde_Compress
+ */
+class Horde_Compress_Gzip extends Horde_Compress
+{
+    /**
+     * Gzip file flags.
+     *
+     * @var array
+     */
+    protected $_flags = array(
+        'FTEXT'     =>  0x01,
+        'FHCRC'     =>  0x02,
+        'FEXTRA'    =>  0x04,
+        'FNAME'     =>  0x08,
+        'FCOMMENT'  =>  0x10
+    );
+
+    /**
+     * Decompress a gzip file and get information from it.
+     *
+     * @param string $data   The tar file data.
+     * @param array $params  The parameter array (Unused).
+     *
+     * @return string  The uncompressed data.
+     * @throws Horde_Exception
+     */
+    public function decompress($data, $params = array())
+    {
+        /* If gzip is not compiled into PHP, return now. */
+        if (!Horde_Util::extensionExists('zlib')) {
+            throw new Horde_Exception(_("This server can't uncompress gzip files."));
+        }
+
+        /* Gzipped File - decompress it first. */
+        $position = 0;
+        $info = @unpack('CCM/CFLG/VTime/CXFL/COS', substr($data, $position + 2));
+        if (!$info) {
+            throw new Horde_Exception(_("Unable to decompress data."));
+        }
+        $position += 10;
+
+        if ($info['FLG'] & $this->_flags['FEXTRA']) {
+            $XLEN = unpack('vLength', substr($data, $position + 0, 2));
+            $XLEN = $XLEN['Length'];
+            $position += $XLEN + 2;
+        }
+
+        if ($info['FLG'] & $this->_flags['FNAME']) {
+            $filenamePos = strpos($data, "\x0", $position);
+            $filename = substr($data, $position, $filenamePos - $position);
+            $position = $filenamePos + 1;
+        }
+
+        if ($info['FLG'] & $this->_flags['FCOMMENT']) {
+            $commentPos = strpos($data, "\x0", $position);
+            $comment = substr($data, $position, $commentPos - $position);
+            $position = $commentPos + 1;
+        }
+
+        if ($info['FLG'] & $this->_flags['FHCRC']) {
+            $hcrc = unpack('vCRC', substr($data, $position + 0, 2));
+            $hcrc = $hcrc['CRC'];
+            $position += 2;
+        }
+
+        $result = @gzinflate(substr($data, $position, strlen($data) - $position));
+        if (empty($result)) {
+            throw new Horde_Exception(_("Unable to decompress data."));
+        }
+
+        return $result;
+    }
+
+}
diff --git a/framework/Compress/lib/Horde/Compress/Rar.php b/framework/Compress/lib/Horde/Compress/Rar.php
new file mode 100644 (file)
index 0000000..6e77d96
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+/**
+ * The Horde_Compress_Rar class allows rar files to be read.
+ *
+ * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Cochrane <mike@graftonhall.co.nz>
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Horde_Compress
+ */
+class Horde_Compress_Rar extends Horde_Compress
+{
+    /**
+     * Rar compression methods
+     *
+     * @var array
+     */
+    protected $_methods = array(
+        0x30 => 'Store',
+        0x31 => 'Fastest',
+        0x32 => 'Fast',
+        0x33 => 'Normal',
+        0x34 => 'Good',
+        0x35 => 'Best'
+    );
+
+    /**
+     * Decompress a rar file and get information from it.
+     *
+     * @param string $data   The rar file data.
+     * @param array $params  The parameter array (Unused).
+     *
+     * @return array  The uncompressed data:
+     * <pre>
+     * KEY: Position in RAR archive
+     * VALUES:
+     *   'attr'    --  File attributes
+     *   'date'    --  File modification time
+     *   'csize'   --  Compressed file size
+     *   'method'  --  Compression method
+     *   'name'    --  Filename
+     *   'size'    --  Original file size
+     * </pre>
+     *
+     * @throws Horde_Exception
+     */
+    public function decompress($data, $params = array())
+    {
+        $blockStart = strpos($data, "\x52\x61\x72\x21\x1a\x07\x00");
+        if ($blockStart === false) {
+            throw new Horde_Exception(_("Invalid RAR data."));
+        }
+
+        $position = $blockStart + 7;
+        $return_array = array();
+
+        while ($position < strlen($data)) {
+            $head_crc = substr($data, $position + 0, 2);
+            $head_type = ord(substr($data, $position + 2, 1));
+            $head_flags = unpack('vFlags', substr($data, $position + 3, 2));
+            $head_flags = $head_flags['Flags'];
+            $head_size = unpack('vSize', substr($data, $position + 5, 2));
+            $head_size = $head_size['Size'];
+
+            $position += 7;
+            $head_size -= 7;
+
+            switch ($head_type) {
+            case 0x73:
+                /* Archive header */
+                $position += $head_size;
+                break;
+
+            case 0x74:
+                /* File Header */
+                $info = unpack('VPacked/VUnpacked/COS/VCRC32/VTime/CVersion/CMethod/vLength/vAttrib', substr($data, $position));
+
+                $return_array[] = array(
+                    'name' => substr($data, $position + 25, $info['Length']),
+                    'size' => $info['Unpacked'],
+                    'csize' => $info['Packed'],
+                    'date' => mktime((($info['Time'] >> 11) & 0x1f),
+                                     (($info['Time'] >> 5) & 0x3f),
+                                     (($info['Time'] << 1) & 0x3e),
+                                     (($info['Time'] >> 21) & 0x07),
+                                     (($info['Time'] >> 16) & 0x1f),
+                                     ((($info['Time'] >> 25) & 0x7f) + 80)),
+                    'method' => $this->_methods[$info['Method']],
+                    'attr' => (($info['Attrib'] & 0x10) ? 'D' : '-') .
+                              (($info['Attrib'] & 0x20) ? 'A' : '-') .
+                              (($info['Attrib'] & 0x03) ? 'S' : '-') .
+                              (($info['Attrib'] & 0x02) ? 'H' : '-') .
+                              (($info['Attrib'] & 0x01) ? 'R' : '-')
+                );
+
+                $position += $head_size + $info['Packed'];
+                break;
+
+            default:
+                $position += $head_size;
+                if (isset($add_size)) {
+                    $position += $add_size;
+                }
+                break;
+            }
+        }
+
+        return $return_array;
+    }
+}
diff --git a/framework/Compress/lib/Horde/Compress/Tar.php b/framework/Compress/lib/Horde/Compress/Tar.php
new file mode 100644 (file)
index 0000000..60c9bea
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+/**
+ * The Horde_Compress_Tar class allows tar files to be read.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Cochrane <mike@graftonhall.co.nz>
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Horde_Compress
+ */
+class Horde_Compress_Tar extends Horde_Compress
+{
+    /**
+     * Tar file types.
+     *
+     * @var array
+     */
+    protected $_types = array(
+        0x0   =>  'Unix file',
+        0x30  =>  'File',
+        0x31  =>  'Link',
+        0x32  =>  'Symbolic link',
+        0x33  =>  'Character special file',
+        0x34  =>  'Block special file',
+        0x35  =>  'Directory',
+        0x36  =>  'FIFO special file',
+        0x37  =>  'Contiguous file'
+    );
+
+    /**
+     * Tar file flags.
+     *
+     * @var array
+     */
+    protected $_flags = array(
+        'FTEXT'     =>  0x01,
+        'FHCRC'     =>  0x02,
+        'FEXTRA'    =>  0x04,
+        'FNAME'     =>  0x08,
+        'FCOMMENT'  =>  0x10
+    );
+
+    /**
+     * Decompress a tar file and get information from it.
+     *
+     * @param string $data   The tar file data.
+     * @param array $params  The parameter array (Unused).
+     *
+     * @return array  The requested data.
+     * <pre>
+     * KEY: Position in the array
+     * VALUES: 'attr'  --  File attributes
+     *         'data'  --  Raw file contents
+     *         'date'  --  File modification time
+     *         'name'  --  Filename
+     *         'size'  --  Original file size
+     *         'type'  --  File type
+     * </pre>
+     *
+     * @throws Horde_Exception
+     */
+    public function decompress($data, $params = array())
+    {
+        $position = 0;
+        $return_array = array();
+
+        while ($position < strlen($data)) {
+            $info = @unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/Ctypeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", substr($data, $position));
+            if (!$info) {
+                throw new Horde_Exception(_("Unable to decompress data."));
+            }
+
+            $position += 512;
+            $contents = substr($data, $position, octdec($info['size']));
+            $position += ceil(octdec($info['size']) / 512) * 512;
+
+            if ($info['filename']) {
+                $file = array(
+                    'attr' => null,
+                    'data' => null,
+                    'date' => octdec($info['mtime']),
+                    'name' => trim($info['filename']),
+                    'size' => octdec($info['size']),
+                    'type' => isset($this->_types[$info['typeflag']]) ? $this->_types[$info['typeflag']] : null
+                );
+
+                if (($info['typeflag'] == 0) ||
+                    ($info['typeflag'] == 0x30) ||
+                    ($info['typeflag'] == 0x35)) {
+                    /* File or folder. */
+                    $file['data'] = $contents;
+
+                    $mode = hexdec(substr($info['mode'], 4, 3));
+                    $file['attr'] =
+                        (($info['typeflag'] == 0x35) ? 'd' : '-') .
+                        (($mode & 0x400) ? 'r' : '-') .
+                        (($mode & 0x200) ? 'w' : '-') .
+                        (($mode & 0x100) ? 'x' : '-') .
+                        (($mode & 0x040) ? 'r' : '-') .
+                        (($mode & 0x020) ? 'w' : '-') .
+                        (($mode & 0x010) ? 'x' : '-') .
+                        (($mode & 0x004) ? 'r' : '-') .
+                        (($mode & 0x002) ? 'w' : '-') .
+                        (($mode & 0x001) ? 'x' : '-');
+                } else {
+                    /* Some other type. */
+                }
+
+                $return_array[] = $file;
+            }
+        }
+
+        return $return_array;
+    }
+
+}
diff --git a/framework/Compress/lib/Horde/Compress/Tnef.php b/framework/Compress/lib/Horde/Compress/Tnef.php
new file mode 100644 (file)
index 0000000..1ebe1fa
--- /dev/null
@@ -0,0 +1,336 @@
+<?php
+/**
+ * The Horde_Compress_Tnef class allows MS-TNEF data to be displayed.
+ *
+ * The TNEF rendering is based on code by:
+ *   Graham Norbury <gnorbury@bondcar.com>
+ * Original design by:
+ *   Thomas Boll <tb@boll.ch>, Mark Simpson <damned@world.std.com>
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Horde_Compress
+ */
+class Horde_Compress_Tnef extends Horde_Compress
+{
+    const SIGNATURE = 0x223e9f78;
+    const LVL_MESSAGE = 0x01;
+    const LVL_ATTACHMENT = 0x02;
+
+    const STRING = 0x00010000;
+    const BYTE = 0x00060000;
+    const WORD = 0x00070000;
+    const DWORD = 0x00080000;
+
+    const ASUBJECT = self::DWORD | 0x8004;
+    const AMCLASS = self::WORD | 0x8008;
+    const ATTACHDATA = self::BYTE | 0x800f;
+    const AFILENAME = self::STRING | 0x8010;
+    const ARENDDATA = self::BYTE | 0x9002;
+    const AMAPIATTRS = self::BYTE | 0x9005;
+    const AVERSION = self::DWORD | 0x9006;
+
+    const MAPI_NULL = 0x0001;
+    const MAPI_SHORT = 0x0002;
+    const MAPI_INT = 0x0003;
+    const MAPI_FLOAT = 0x0004;
+    const MAPI_DOUBLE = 0x0005;
+    const MAPI_CURRENCY = 0x0006;
+    const MAPI_APPTIME = 0x0007;
+    const MAPI_ERROR = 0x000a;
+    const MAPI_BOOLEAN = 0x000b;
+    const MAPI_OBJECT = 0x000d;
+    const MAPI_INT8BYTE = 0x0014;
+    const MAPI_STRING = 0x001e;
+    const MAPI_UNICODE_STRING = 0x001f;
+    const MAPI_SYSTIME = 0x0040;
+    const MAPI_CLSID = 0x0048;
+    const MAPI_BINARY = 0x0102;
+
+    const MAPI_ATTACH_LONG_FILENAME = 0x3707;
+    const MAPI_ATTACH_MIME_TAG = 0x370E;
+
+    const MAPI_NAMED_TYPE_ID = 0x0000;
+    const MAPI_NAMED_TYPE_STRING = 0x0001;
+    const MAPI_MV_FLAG = 0x1000;
+
+    /**
+     * Decompress the data.
+     *
+     * @param string $data   The data to decompress.
+     * @param array $params  An array of arguments needed to decompress the
+     *                       data.
+     *
+     * @return mixed  The decompressed data.
+     * @throws Horde_Exception
+     */
+    public function decompress($data, $params = array())
+    {
+        $out = array();
+
+        if ($this->_geti($data, 32) == self::SIGNATURE) {
+            $this->_geti($data, 16);
+
+            while (strlen($data) > 0) {
+                switch ($this->_geti($data, 8)) {
+                case self::LVL_MESSAGE:
+                    $this->_decodeMessage($data);
+                    break;
+
+                case self::LVL_ATTACHMENT:
+                    $this->_decodeAttachment($data, $out);
+                    break;
+                }
+            }
+        }
+
+        return array_reverse($out);
+    }
+
+    /**
+     * TODO
+     *
+     * @param string &$data  The data string.
+     * @param integer $bits  How many bits to retrieve.
+     *
+     * @return TODO
+     */
+    protected function _getx(&$data, $bits)
+    {
+        $value = null;
+
+        if (strlen($data) >= $bits) {
+            $value = substr($data, 0, $bits);
+            $data = substr_replace($data, '', 0, $bits);
+        }
+
+        return $value;
+    }
+
+    /**
+     * TODO
+     *
+     * @param string &$data  The data string.
+     * @param integer $bits  How many bits to retrieve.
+     *
+     * @return TODO
+     */
+    protected function _geti(&$data, $bits)
+    {
+        $bytes = $bits / 8;
+        $value = null;
+
+        if (strlen($data) >= $bytes) {
+            $value = ord($data[0]);
+            if ($bytes >= 2) {
+                $value += (ord($data[1]) << 8);
+            }
+            if ($bytes >= 4) {
+                $value += (ord($data[2]) << 16) + (ord($data[3]) << 24);
+            }
+            $data = substr_replace($data, '', 0, $bytes);
+        }
+
+        return $value;
+    }
+
+    /**
+     * TODO
+     *
+     * @param string &$data      The data string.
+     * @param string $attribute  TODO
+     */
+    protected function _decodeAttribute(&$data, $attribute)
+    {
+        /* Data. */
+        $this->_getx($data, $this->_geti($data, 32));
+
+        /* Checksum. */
+        $this->_geti($data, 16);
+    }
+
+    /**
+     * TODO
+     *
+     * @param string $data             The data string.
+     * @param array &$attachment_data  TODO
+     */
+    protected function _extractMapiAttributes($data, &$attachment_data)
+    {
+        /* Number of attributes. */
+        $number = $this->_geti($data, 32);
+
+        while ((strlen($data) > 0) && $number--) {
+            $have_mval = false;
+            $num_mval = 1;
+            $named_id = $value = null;
+            $attr_type = $this->_geti($data, 16);
+            $attr_name = $this->_geti($data, 16);
+
+            if (($attr_type & self::MAPI_MV_FLAG) != 0) {
+                $have_mval = true;
+                $attr_type = $attr_type & ~self::MAPI_MV_FLAG;
+            }
+
+            if (($attr_name >= 0x8000) && ($attr_name < 0xFFFE)) {
+                $this->_getx($data, 16);
+                $named_type = $this->_geti($data, 32);
+
+                switch ($named_type) {
+                case self::MAPI_NAMED_TYPE_ID:
+                    $named_id = $this->_geti($data, 32);
+                    $attr_name = $named_id;
+                    break;
+
+                case self::MAPI_NAMED_TYPE_STRING:
+                    $attr_name = 0x9999;
+                    $idlen = $this->_geti($data, 32);
+                    $datalen = $idlen + ((4 - ($idlen % 4)) % 4);
+                    $named_id = substr($this->_getx($data, $datalen), 0, $idlen);
+                    break;
+                }
+            }
+
+            if ($have_mval) {
+                $num_mval = $this->_geti($data, 32);
+            }
+
+            switch ($attr_type) {
+            case self::MAPI_SHORT:
+                $value = $this->_geti($data, 16);
+                break;
+
+            case self::MAPI_INT:
+            case self::MAPI_BOOLEAN:
+                for ($i = 0; $i < $num_mval; $i++) {
+                    $value = $this->_geti($data, 32);
+                }
+                break;
+
+            case self::MAPI_FLOAT:
+            case self::MAPI_ERROR:
+                $value = $this->_getx($data, 4);
+                break;
+
+            case self::MAPI_DOUBLE:
+            case self::MAPI_APPTIME:
+            case self::MAPI_CURRENCY:
+            case self::MAPI_INT8BYTE:
+            case self::MAPI_SYSTIME:
+                $value = $this->_getx($data, 8);
+                break;
+
+            case self::MAPI_STRING:
+            case self::MAPI_UNICODE_STRING:
+            case self::MAPI_BINARY:
+            case self::MAPI_OBJECT:
+                $num_vals = ($have_mval) ? $num_mval : $this->_geti($data, 32);
+                for ($i = 0; $i < $num_vals; $i++) {
+                    $length = $this->_geti($data, 32);
+
+                    /* Pad to next 4 byte boundary. */
+                    $datalen = $length + ((4 - ($length % 4)) % 4);
+
+                    if ($attr_type == self::MAPI_STRING) {
+                        $length -= 1;
+                    }
+
+                    /* Read and truncate to length. */
+                    $value = substr($this->_getx($data, $datalen), 0, $length);
+                }
+                break;
+            }
+
+            /* Store any interesting attributes. */
+            switch ($attr_name) {
+            case self::MAPI_ATTACH_LONG_FILENAME:
+                /* Used in preference to AFILENAME value. */
+                $attachment_data[0]['name'] = preg_replace('/.*[\/](.*)$/', '\1', $value);
+                $attachment_data[0]['name'] = str_replace("\0", '', $attachment_data[0]['name']);
+                break;
+
+            case self::MAPI_ATTACH_MIME_TAG:
+                /* Is this ever set, and what is format? */
+                $attachment_data[0]['type'] = preg_replace('/^(.*)\/.*/', '\1', $value);
+                $attachment_data[0]['subtype'] = preg_replace('/.*\/(.*)$/', '\1', $value);
+                $attachment_data[0]['subtype'] = str_replace("\0", '', $attachment_data[0]['subtype']);
+                break;
+            }
+        }
+    }
+
+    /**
+     * TODO
+     *
+     * @param string &$data  The data string.
+     */
+    protected function _decodeMessage(&$data)
+    {
+        $this->_decodeAttribute($data, $this->_geti($data, 32));
+    }
+
+    /**
+     * TODO
+     *
+     * @param string &$data            The data string.
+     * @param array &$attachment_data  TODO
+     */
+    protected function _decodeAttachment(&$data, &$attachment_data)
+    {
+        $attribute = $this->_geti($data, 32);
+
+        switch ($attribute) {
+        case self::ARENDDATA:
+            /* Marks start of new attachment. */
+            $this->_getx($data, $this->_geti($data, 32));
+
+            /* Checksum */
+            $this->_geti($data, 16);
+
+            /* Add a new default data block to hold details of this
+               attachment. Reverse order is easier to handle later! */
+            array_unshift($attachment_data, array('type'    => 'application',
+                                                  'subtype' => 'octet-stream',
+                                                  'name'    => 'unknown',
+                                                  'stream'  => ''));
+            break;
+
+        case self::AFILENAME:
+            /* Strip path. */
+            $attachment_data[0]['name'] = preg_replace('/.*[\/](.*)$/', '\1', $this->_getx($data, $this->_geti($data, 32)));
+            $attachment_data[0]['name'] = str_replace("\0", '', $attachment_data[0]['name']);
+
+            /* Checksum */
+            $this->_geti($data, 16);
+            break;
+
+        case self::ATTACHDATA:
+            /* The attachment itself. */
+            $length = $this->_geti($data, 32);
+            $attachment_data[0]['size'] = $length;
+            $attachment_data[0]['stream'] = $this->_getx($data, $length);
+
+            /* Checksum */
+            $this->_geti($data, 16);
+            break;
+
+        case self::AMAPIATTRS:
+            $length = $this->_geti($data, 32);
+            $value = $this->_getx($data, $length);
+
+            /* Checksum */
+            $this->_geti($data, 16);
+            $this->_extractMapiAttributes($value, $attachment_data);
+            break;
+
+        default:
+            $this->_decodeAttribute($data, $attribute);
+        }
+    }
+
+}
diff --git a/framework/Compress/lib/Horde/Compress/Zip.php b/framework/Compress/lib/Horde/Compress/Zip.php
new file mode 100644 (file)
index 0000000..bcc8ae7
--- /dev/null
@@ -0,0 +1,359 @@
+<?php
+/**
+ * The Horde_Compress_zip class allows ZIP files to be created and read.
+ *
+ * The ZIP compression code is partially based on code from:
+ *   Eric Mueller <eric@themepark.com>
+ *   http://www.zend.com/codex.php?id=535&single=1
+ *
+ *   Deins125 <webmaster@atlant.ru>
+ *   http://www.zend.com/codex.php?id=470&single=1
+ *
+ * The ZIP compression date code is partially based on code from
+ *   Peter Listiak <mlady@users.sourceforge.net>
+ *
+ * Copyright 2000-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @author  Michael Cochrane <mike@graftonhall.co.nz>
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Horde_Compress
+ */
+class Horde_Compress_Zip extends Horde_Compress
+{
+    /* Constants used with decompress(). */
+    const ZIP_LIST = 1;
+    const ZIP_DATA = 2;
+
+    /* Beginning of central directory record. */
+    const CTRL_DIR_HEADER = "\x50\x4b\x01\x02";
+
+    /* End of central directory record. */
+    const CTRL_DIR_END = "\x50\x4b\x05\x06\x00\x00\x00\x00";
+
+    /* Beginning of file contents. */
+    const FILE_HEADER = "\x50\x4b\x03\x04";
+
+    /**
+     * ZIP compression methods.
+     *
+     * @var array
+     */
+    protected $_methods = array(
+        0x0 => 'None',
+        0x1 => 'Shrunk',
+        0x2 => 'Super Fast',
+        0x3 => 'Fast',
+        0x4 => 'Normal',
+        0x5 => 'Maximum',
+        0x6 => 'Imploded',
+        0x8 => 'Deflated'
+    );
+
+    /**
+     * Create a ZIP compressed file from an array of file data.
+     *
+     * @param array $data    The data to compress.
+     * <pre>
+     * Requires an array of arrays - each subarray should contain the
+     * following fields:
+     * 'data' - (string) The data to compress.
+     * 'name' - (string) The pathname to the file.
+     * 'time' - (integer) [optional] The timestamp to use for the file.
+     * </pre>
+     * @param array $params  The parameter array (unused).
+     *
+     * @return string  The ZIP file.
+     */
+    public function compress($data, $params = array())
+    {
+        $contents = '';
+        $ctrldir = array();
+
+        reset($data);
+        while (list(, $val) = each($data)) {
+            $ctrldir = $this->_addToZipFile($val, $contents, $ctrldir);
+        }
+
+        return $this->_createZIPFile($contents, $ctrldir);
+    }
+
+    /**
+     * Decompress a ZIP file and get information from it.
+     *
+     * @param string $data   The zipfile data.
+     * @param array $params  The parameter array.
+     * <pre>
+     * The following parameters are REQUIRED:
+     * 'action' - (integer) The action to take on the data.  Either
+     *                      self::ZIP_LIST or self::ZIP_DATA.
+     *
+     * The following parameters are REQUIRED for self::ZIP_DATA also:
+     * 'info' - (array) The zipfile list.
+     * 'key' - (integer) The position of the file in the archive list.
+     * </pre>
+     *
+     * @return mixed  The requested data.
+     * @throws Horde_Exception
+     */
+    public function decompress($data, $params)
+    {
+        if (isset($params['action'])) {
+            switch ($params['action']) {
+            case self::ZIP_LIST:
+                return $this->_getZipInfo($data);
+
+            case self::ZIP_DATA:
+                return $this->_getZipData($data, $params['info'], $params['key']);
+            }
+        }
+    }
+
+    /**
+     * Get the list of files/data from the zip archive.
+     *
+     * @param string $data  The zipfile data.
+     *
+     * @return array  KEY: Position in zipfile
+     *                VALUES:
+     * <pre>
+     * 'attr'    --  File attributes
+     * 'crc'     --  CRC checksum
+     * 'csize'   --  Compressed file size
+     * 'date'    --  File modification time
+     * 'name'    --  Filename
+     * 'method'  --  Compression method
+     * 'size'    --  Original file size
+     * 'type'    --  File type
+     * </pre>
+     *
+     * @throws Horde_Exception
+     */
+    protected function _getZipInfo($data)
+    {
+        $entries = array();
+
+        /* Get details from Central directory structure. */
+        $fhStart = strpos($data, self::CTRL_DIR_HEADER);
+
+        do {
+            if (strlen($data) < $fhStart + 31) {
+                throw new Horde_Exception(_("Invalid ZIP data"));
+            }
+            $info = unpack('vMethod/VTime/VCRC32/VCompressed/VUncompressed/vLength', substr($data, $fhStart + 10, 20));
+            $name = substr($data, $fhStart + 46, $info['Length']);
+
+            $entries[$name] = array(
+                'attr' => null,
+                'crc' => sprintf("%08s", dechex($info['CRC32'])),
+                'csize' => $info['Compressed'],
+                'date' => null,
+                '_dataStart' => null,
+                'name' => $name,
+                'method' => $this->_methods[$info['Method']],
+                '_method' => $info['Method'],
+                'size' => $info['Uncompressed'],
+                'type' => null
+            );
+
+            $entries[$name]['date'] =
+                mktime((($info['Time'] >> 11) & 0x1f),
+                       (($info['Time'] >> 5) & 0x3f),
+                       (($info['Time'] << 1) & 0x3e),
+                       (($info['Time'] >> 21) & 0x07),
+                       (($info['Time'] >> 16) & 0x1f),
+                       ((($info['Time'] >> 25) & 0x7f) + 1980));
+
+            if (strlen($data) < $fhStart + 43) {
+                throw new Horde_Exception(_("Invalid ZIP data"));
+            }
+            $info = unpack('vInternal/VExternal', substr($data, $fhStart + 36, 6));
+
+            $entries[$name]['type'] = ($info['Internal'] & 0x01) ? 'text' : 'binary';
+            $entries[$name]['attr'] =
+                (($info['External'] & 0x10) ? 'D' : '-') .
+                (($info['External'] & 0x20) ? 'A' : '-') .
+                (($info['External'] & 0x03) ? 'S' : '-') .
+                (($info['External'] & 0x02) ? 'H' : '-') .
+                (($info['External'] & 0x01) ? 'R' : '-');
+        } while (($fhStart = strpos($data, self::CTRL_DIR_HEADER, $fhStart + 46)) !== false);
+
+        /* Get details from local file header. */
+        $fhStart = strpos($data, self::FILE_HEADER);
+
+        do {
+            if (strlen($data) < $fhStart + 34) {
+                throw new Horde_Exception(_("Invalid ZIP data"));
+            }
+            $info = unpack('vMethod/VTime/VCRC32/VCompressed/VUncompressed/vLength/vExtraLength', substr($data, $fhStart + 8, 25));
+            $name = substr($data, $fhStart + 30, $info['Length']);
+            $entries[$name]['_dataStart'] = $fhStart + 30 + $info['Length'] + $info['ExtraLength'];
+        } while (strlen($data) > $fhStart + 30 + $info['Length'] &&
+                 ($fhStart = strpos($data, self::FILE_HEADER, $fhStart + 30 + $info['Length'])) !== false);
+
+        return array_values($entries);
+    }
+
+    /**
+     * Returns the data for a specific archived file.
+     *
+     * @param string $data  The zip archive contents.
+     * @param array $info   The information array from _getZipInfo().
+     * @param integer $key  The position of the file in the archive.
+     *
+     * @return string  The file data.
+     */
+    protected function _getZipData($data, $info, $key)
+    {
+        if (($info[$key]['_method'] == 0x8) &&
+            Horde_Util::extensionExists('zlib')) {
+            /* If the file has been deflated, and zlib is installed,
+               then inflate the data again. */
+            return @gzinflate(substr($data, $info[$key]['_dataStart'], $info[$key]['csize']));
+        } elseif ($info[$key]['_method'] == 0x0) {
+            /* Files that aren't compressed. */
+            return substr($data, $info[$key]['_dataStart'], $info[$key]['csize']);
+        }
+
+        return '';
+    }
+
+    /**
+     * Checks to see if the data is a valid ZIP file.
+     *
+     * @param string $data  The ZIP file data.
+     *
+     * @return boolean  True if valid, false if invalid.
+     */
+    public function checkZipData($data)
+    {
+        return (strpos($data, self::FILE_HEADER) !== false);
+    }
+
+    /**
+     * Converts a UNIX timestamp to a 4-byte DOS date and time format
+     * (date in high 2-bytes, time in low 2-bytes allowing magnitude
+     * comparison).
+     *
+     * @param integer $unixtime  The current UNIX timestamp.
+     *
+     * @return integer  The current date in a 4-byte DOS format.
+     */
+    protected function _unix2DOSTime($unixtime = null)
+    {
+        $timearray = (is_null($unixtime)) ? getdate() : getdate($unixtime);
+
+        if ($timearray['year'] < 1980) {
+            $timearray['year']    = 1980;
+            $timearray['mon']     = 1;
+            $timearray['mday']    = 1;
+            $timearray['hours']   = 0;
+            $timearray['minutes'] = 0;
+            $timearray['seconds'] = 0;
+        }
+
+        return (($timearray['year'] - 1980) << 25) |
+                ($timearray['mon'] << 21) |
+                ($timearray['mday'] << 16) |
+                ($timearray['hours'] << 11) |
+                ($timearray['minutes'] << 5) |
+                ($timearray['seconds'] >> 1);
+    }
+
+    /**
+     * Adds a "file" to the ZIP archive.
+     *
+     * @param array $file       See self::createZipFile().
+     * @param string $contents  The zip data.
+     * @param array $ctrldir    An array of central directory information.
+     *
+     * @return array  The updated value of $ctrldir.
+     */
+    protected function _addToZipFile($file, $contents, $ctrldir)
+    {
+        $data = $file['data'];
+        $name = str_replace('\\', '/', $file['name']);
+
+        /* See if time/date information has been provided. */
+        $ftime = (isset($file['time'])) ? $file['time'] : null;
+
+        /* Get the hex time. */
+        $dtime    = dechex($this->_unix2DosTime($ftime));
+        $hexdtime = chr(hexdec($dtime[6] . $dtime[7])) .
+                    chr(hexdec($dtime[4] . $dtime[5])) .
+                    chr(hexdec($dtime[2] . $dtime[3])) .
+                    chr(hexdec($dtime[0] . $dtime[1]));
+
+        /* "Local file header" segment. */
+        $unc_len = strlen($data);
+        $crc     = crc32($data);
+        $zdata   = gzcompress($data);
+        $zdata   = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
+        $c_len   = strlen($zdata);
+        $old_offset = strlen($contents);
+
+        /* Common data for the two entries. */
+        $common =
+            "\x14\x00" .                /* Version needed to extract. */
+            "\x00\x00" .                /* General purpose bit flag. */
+            "\x08\x00" .                /* Compression method. */
+            $hexdtime .                 /* Last modification time/date. */
+            pack('V', $crc) .           /* CRC 32 information. */
+            pack('V', $c_len) .         /* Compressed filesize. */
+            pack('V', $unc_len) .       /* Uncompressed filesize. */
+            pack('v', strlen($name)) .  /* Length of filename. */
+            pack('v', 0);               /* Extra field length. */
+
+        /* Add this entry to zip data. */
+        $contents .=
+            self::FILE_HEADER .        /* Begin creating the ZIP data. */
+            $common .                   /* Common data. */
+            $name .                     /* File name. */
+            $zdata;                     /* "File data" segment. */
+
+        /* Add to central directory record. */
+        $cdrec = self::CTRL_DIR_HEADER .
+                 "\x00\x00" .               /* Version made by. */
+                 $common .                  /* Common data. */
+                 pack('v', 0) .             /* File comment length. */
+                 pack('v', 0) .             /* Disk number start. */
+                 pack('v', 0) .             /* Internal file attributes. */
+                 pack('V', 32) .            /* External file attributes -
+                                               'archive' bit set. */
+                 pack('V', $old_offset) .   /* Relative offset of local
+                                               header. */
+                 $name;                     /* File name. */
+
+        // Save to central directory array. */
+        $ctrldir[] = $cdrec;
+
+        return $ctrldir;
+    }
+
+    /**
+     * Creates the ZIP file.
+     * Official ZIP file format: http://www.pkware.com/appnote.txt
+     *
+     * @return string  The ZIP file.
+     */
+    protected function _createZIPFile($contents, $ctrlDir)
+    {
+        $dir = implode('', $ctrlDir);
+
+        return $contents . $dir . self::CTRL_DIR_END .
+            /* Total # of entries "on this disk". */
+            pack('v', count($ctrlDir)) .
+            /* Total # of entries overall. */
+            pack('v', count($ctrlDir)) .
+            /* Size of central directory. */
+            pack('V', strlen($dir)) .
+            /* Offset to start of central dir. */
+            pack('V', strlen($contents)) .
+            /* ZIP file comment length. */
+            "\x00\x00";
+    }
+
+}
diff --git a/framework/Compress/package.xml b/framework/Compress/package.xml
new file mode 100644 (file)
index 0000000..d537f17
--- /dev/null
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Compress</name>
+ <channel>pear.horde.org</channel>
+ <summary>Horde Compression API</summary>
+ <description>This package provides an API for various compression techniques.
+ </description>
+ <lead>
+  <name>Chuck Hagenbuch</name>
+  <user>chuck</user>
+  <email>chuck@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Jan Schneider</name>
+  <user>jan</user>
+  <email>jan@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Michael Slusarz</name>
+  <user>slusarz</user>
+  <email>slusarz@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <date>2009-07-13</date>
+ <version>
+  <release>0.1.0</release>
+  <api>0.1.0</api>
+ </version>
+ <stability>
+  <release>beta</release>
+  <api>beta</api>
+ </stability>
+ <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+ <notes>* Initial Horde 4 package.
+ </notes>
+ <contents>
+  <dir name="/">
+   <dir name="lib">
+    <dir name="Horde">
+     <dir name="Compress">
+      <file name="Dbx.php" role="php" />
+      <file name="Gzip.php" role="php" />
+      <file name="Rar.php" role="php" />
+      <file name="Tar.php" role="php" />
+      <file name="Tnef.php" role="php" />
+      <file name="Zip.php" role="php" />
+     </dir> <!-- /lib/Horde/Compress -->
+     <file name="Compress.php" role="php" />
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+  </dir> <!-- / -->
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.5.4</min>
+   </pearinstaller>
+   <package>
+    <name>Exception</name>
+    <channel>pear.horde.org</channel>
+   </package>
+   <package>
+    <name>Util</name>
+    <channel>pear.horde.org</channel>
+   </package>
+  </required>
+  <optional>
+   <extension>
+    <name>gettext</name>
+   </extension>
+   <extension>
+    <name>zlib</name>
+   </extension>
+  </optional>
+ </dependencies>
+ <phprelease>
+  <filelist>
+   <install name="lib/Horde/Compress/Dbx.php" as="Horde/Compress/Dbx.php" />
+   <install name="lib/Horde/Compress/Gzip.php" as="Horde/Compress/Gzip.php" />
+   <install name="lib/Horde/Compress/Rar.php" as="Horde/Compress/Rar.php" />
+   <install name="lib/Horde/Compress/Tar.php" as="Horde/Compress/Tar.php" />
+   <install name="lib/Horde/Compress/Tnef.php" as="Horde/Compress/Tnef.php" />
+   <install name="lib/Horde/Compress/Zip.php" as="Horde/Compress/Zip.php" />
+   <install name="lib/Horde/Compress.php" as="Horde/Compress.php" />
+  </filelist>
+ </phprelease>
+ <changelog>
+  <release>
+   <date>2006-05-08</date>
+   <time>18:34:08</time>
+   <version>
+    <release>0.0.2</release>
+    <api>0.0.2</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>* Added rar driver.
+  * Converted to package.xml 2.0 for pear.horde.org
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.0.1</release>
+    <api>0.0.1</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <date>2003-07-03</date>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Initial release as a PEAR package
+   </notes>
+  </release>
+ </changelog>
+</package>
index dbe39a9..fb9a4ba 100644 (file)
@@ -49,7 +49,7 @@ class Horde_Mime_Viewer_Ooo extends Horde_Mime_Viewer_Driver
             'table:number-columns-spanned=' => 'colspan='
         );
 
-        $zip = Horde_Compress::singleton('zip');
+        $zip = Horde_Compress::factory('zip');
         $list = $zip->decompress($this->_mimepart->getContents(), array('action' => HORDE_COMPRESS_ZIP_LIST));
 
         foreach ($list as $key => $file) {
index 798a4d4..2c8c569 100644 (file)
@@ -51,12 +51,8 @@ class Horde_Mime_Viewer_Rar extends Horde_Mime_Viewer_Driver
     {
         $contents = $this->_mimepart->getContents();
 
-        $rar = Horde_Compress::singleton('rar');
-
+        $rar = Horde_Compress::factory('rar');
         $rarData = $rar->decompress($contents);
-        if (is_a($rarData, 'PEAR_Error')) {
-            return array();
-        }
 
         $charset = Horde_Nls::getCharset();
         $fileCount = count($rarData);
index 5495088..901b916 100644 (file)
@@ -52,19 +52,13 @@ class Horde_Mime_Viewer_Tgz extends Horde_Mime_Viewer_Driver
 
         /* Decompress gzipped files. */
         if (in_array($subtype, $this->_gzipSubtypes)) {
-            $gzip = Horde_Compress::singleton('gzip');
+            $gzip = Horde_Compress::factory('gzip');
             $contents = $gzip->decompress($contents);
-            if (is_a($contents, 'PEAR_Error') || empty($contents)) {
-                return array();
-            }
         }
 
         /* Obtain the list of files/data in the tar file. */
-        $tar = Horde_Compress::singleton('tar');
+        $tar = Horde_Compress::factory('tar');
         $tarData = $tar->decompress($contents);
-        if (is_a($tarData, 'PEAR_Error')) {
-            return array();
-        }
 
         $charset = Horde_Nls::getCharset();
         $fileCount = count($tarData);
index e7f0431..71ca81e 100644 (file)
@@ -49,11 +49,11 @@ class Horde_Mime_Viewer_Tnef extends Horde_Mime_Viewer_Driver
      */
     protected function _renderInline()
     {
-        $tnef = Horde_Compress::singleton('tnef');
+        $tnef = Horde_Compress::factory('tnef');
+        $info = $tnef->decompress($this->_mimepart->getContents());
 
         $data = '<table border="1">';
-        $info = $tnef->decompress($this->_mimepart->getContents());
-        if (empty($info) || is_a($info, 'PEAR_Error')) {
+        if (empty($info)) {
             $data .= '<tr><td>' . _("MS-TNEF Attachment contained no data.") . '</td></tr>';
         } else {
             $data .= '<tr><td>' . _("Name") . '</td><td>' . _("Mime Type") . '</td></tr>';
index d9637a8..bf93540 100644 (file)
@@ -68,17 +68,9 @@ class Horde_Mime_Viewer_Zip extends Horde_Mime_Viewer_Driver
     {
         $contents = $this->_mimepart->getContents();
 
-        $zip = Horde_Compress::singleton('zip');
-
-        /* Make sure this is a valid zip file. */
-        if ($zip->checkZipData($contents) === false) {
-            return array();
-        }
-
+        $zip = Horde_Compress::factory('zip');
         $zipInfo = $zip->decompress($contents, array('action' => HORDE_COMPRESS_ZIP_LIST));
-        if (is_a($zipInfo, 'PEAR_Error')) {
-            return array();
-        }
+
         $fileCount = count($zipInfo);
 
         /* Determine maximum file name length. */