File: rar.php

package info (click to toggle)
horde3 3.1.3-4etch7
  • links: PTS
  • area: main
  • in suites: etch
  • size: 22,876 kB
  • ctags: 18,071
  • sloc: php: 75,151; xml: 2,979; sql: 1,069; makefile: 79; sh: 64
file content (202 lines) | stat: -rw-r--r-- 7,254 bytes parent folder | download | duplicates (2)
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
<?php
/**
 * The MIME_Viewer_rar class renders out the contents of .rar archives in HTML
 * format.
 *
 * $Horde: framework/MIME/MIME/Viewer/rar.php,v 1.18.10.9 2006/01/01 21:28:25 jan Exp $
 *
 * Copyright 1999-2006 Anil Madhavapeddy <anil@recoil.org>
 * Copyright 2002-2006 Michael Cochrane <mike@graftonhall.co.nz>
 *
 * 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  Anil Madhavapeddy <anil@recoil.org>
 * @author  Michael Cochrane <mike@graftonhall.co.nz>
 * @since   Horde 1.3
 * @package Horde_MIME_Viewer
 */
class MIME_Viewer_rar extends MIME_Viewer {

    /**
     * Rar compression methods.
     *
     * @var array
     */
    var $_methods = array(
        0x30  =>  'Store',
        0x31  =>  'Fastest',
        0x32  =>  'Fast',
        0x33  =>  'Normal',
        0x34  =>  'Good',
        0x35  =>  'Best'
    );

    /**
     * Render out the currently set contents using rar.
     *
     * @param array $params  Any parameters the Viewer may need.
     *
     * @return string  The rendered contents.
     */
    function render($params = array())
    {
        $contents = $this->mime_part->getContents();

        /* Make sure this is a valid rar file. */
        if ($this->checkRarData($contents) === false) {
            return '<pre>' . _("This does not appear to be a valid rar archive.") . '</pre>';
        }

        require_once 'Horde/Text.php';

        $rarData = $this->getRarData($contents);
        $fileCount = count($rarData);

        $text  = '<strong>' . htmlspecialchars(sprintf(_("Contents of \"%s\""), $this->mime_part->getName())) . ':</strong>' . "\n";
        $text .= '<table><tr><td align="left"><tt><span class="fixed">';
        $text .= Text::htmlAllSpaces(_("Archive Name") . ':  ' . $this->mime_part->getName()) . "\n";
        $text .= Text::htmlAllSpaces(_("Archive File Size") . ': ' . strlen($contents) . ' bytes') . "\n";
        $text .= Text::htmlAllSpaces(($fileCount != 1) ? sprintf(_("File Count: %s files"), $fileCount) : sprintf(_("File Count: %s file"), $fileCount));
        $text .= "\n\n";
        $text .= Text::htmlAllSpaces(
                     str_pad(_("File Name"),     50, ' ', STR_PAD_RIGHT) .
                     str_pad(_("Attributes"),    10, ' ', STR_PAD_LEFT) .
                     str_pad(_("Size"),          10, ' ', STR_PAD_LEFT) .
                     str_pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) .
                     str_pad(_("Method"),        10, ' ', STR_PAD_LEFT) .
                     str_pad(_("Ratio"),          7, ' ', STR_PAD_LEFT)
                 ) . "\n";

        $text .= str_repeat('-', 106) . "\n";

        foreach ($rarData as $val) {
            $ratio = (empty($val['size'])) ? 0 : 100 * ($val['csize'] / $val['size']);
            $text .= Text::htmlAllSpaces(
                         str_pad($val['name'], 50, ' ', STR_PAD_RIGHT) .
                         str_pad($val['attr'], 10, ' ', STR_PAD_LEFT) .
                         str_pad($val['size'], 10, ' ', STR_PAD_LEFT) .
                         str_pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT) .
                         str_pad($val['method'], 10, ' ', STR_PAD_LEFT) .
                         str_pad(sprintf("%1.1f%%", $ratio), 7, ' ', STR_PAD_LEFT)
                     ) . "\n";
        }

        $text .= str_repeat('-', 106) . "\n";
        $text .= '</span></tt></td></tr></table>';

        return nl2br($text);
    }

    /**
     * Returns the MIME type of this part.
     *
     * @return string  The MIME type of this part.
     */
    function getType()
    {
        return 'text/html; charset=' . NLS::getCharset();
    }

    /**
     * Checks to see if the data is a valid Rar archive.
     *
     * @param string &$data  The rar archive data.
     *
     * @return boolean  True if valid, false if invalid.
     */
    function checkRarData(&$data)
    {
        $fileHeader = "\x52\x61\x72\x21\x1a\x07\x00";
        if (strpos($data, $fileHeader) === false) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * Get the list of files/data from the rar archive.
     *
     * @param string &$data  The rar archive data.
     *
     * @return array  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
     */
    function getRarData(&$data)
    {
        $return_array = array();

        $blockStart = strpos($data, "\x52\x61\x72\x21\x1a\x07\x00");
        $position = $blockStart + 7;

        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 = array();

                /* File Header */
                $info = unpack('VPacked/VUnpacked/COS/VCRC32/VTime/CVersion/CMethod/vLength/vAttrib', substr($data, $position));

                $file['name'] = substr($data, $position + 25, $info['Length']);
                $file['size'] = $info['Unpacked'];
                $file['csize'] = $info['Packed'];

                $file['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));

                $file['method'] = $this->_methods[$info['Method']];

                $file['attr']  = '';
                $file['attr'] .= ($info['Attrib'] & 0x10) ? 'D' : '-';
                $file['attr'] .= ($info['Attrib'] & 0x20) ? 'A' : '-';
                $file['attr'] .= ($info['Attrib'] & 0x03) ? 'S' : '-';
                $file['attr'] .= ($info['Attrib'] & 0x02) ? 'H' : '-';
                $file['attr'] .= ($info['Attrib'] & 0x01) ? 'R' : '-';

                $return_array[] = $file;

                $position += $head_size;
                $position += $info['Packed'];
                break;

            default:
                $position += $head_size;
                if (isset($add_size)) {
                    $position += $add_size;
                }
                break;

            }
        }

        return $return_array;
    }

}