PPS::getSize()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Xls\OLE;
4
5
class PPS
6
{
7
    const PPS_TYPE_ROOT = 5;
8
    const PPS_TYPE_FILE = 2;
9
    const PPS_SIZE = 0x80;
10
    const DATA_SIZE_SMALL = 0x1000;
11
    const LONG_INT_SIZE = 4;
12
13
    /**
14
     * The PPS index
15
     * @var integer
16
     */
17
    protected $index;
18
19
    /**
20
     * The PPS name (in Unicode)
21
     * @var string
22
     */
23
    protected $name;
24
25
    /**
26
     * The PPS type. Dir, Root or File
27
     * @var integer
28
     */
29
    protected $type;
30
31
    /**
32
     * The index of the previous PPS
33
     * @var integer
34
     */
35
    protected $prevPps;
36
37
    /**
38
     * The index of the next PPS
39
     * @var integer
40
     */
41
    protected $nextPps;
42
43
    /**
44
     * The index of it's first child if this is a Dir or Root PPS
45
     * @var integer
46
     */
47
    protected $dirPps;
48
49
    /**
50
     * A timestamp
51
     * @var integer
52
     */
53
    protected $timestamp;
54
55
    /**
56
     * Starting block (small or big) for this PPS's data  inside the container
57
     * @var integer
58
     */
59
    protected $startBlock;
60
61
    /**
62
     * The PPS's data (only used if it's not using a temporary file)
63
     * @var string
64
     */
65
    protected $data;
66
67
    /**
68
     * Array of child PPS's (only used by Root and Dir PPS's)
69
     * @var array
70
     */
71
    protected $children = array();
72
73
    /**
74
     * The constructor
75
     *
76
     * @param integer $index The PPS index
77
     * @param string $name The PPS name
78
     * @param integer $type The PPS type. Dir, Root or File
79
     * @param integer $prev The index of the previous PPS
80
     * @param integer $next The index of the next PPS
81
     * @param integer $dir  The index of it's first child if this is a Dir or Root PPS
82
     * @param integer $timestamp A timestamp
83
     * @param string $data  The (usually binary) source data of the PPS
84
     * @param PPS[] $children Array containing children PPS for this PPS
85
     */
86
    public function __construct(
87
        $index = null,
88
        $name = null,
89
        $type = null,
90
        $prev = null,
91
        $next = null,
92
        $dir = null,
93
        $timestamp = null,
94
        $data = '',
95
        $children = array()
96
    ) {
97
        $this->index = $index;
98
        $this->name = $name;
99
        $this->type = $type;
100
101
        $this->prevPps = $prev;
102
        $this->nextPps = $next;
103
        $this->dirPps = $dir;
104
105
        $this->timestamp = $timestamp;
106
107
        $this->children = $children;
108
109
        $this->data = $data;
110
    }
111
112
    /**
113
     * @return bool
114
     */
115
    protected function hasData()
116
    {
117
        return isset($this->data);
118
    }
119
120
    /**
121
     * @return string
122
     */
123
    public function getData()
124
    {
125
        return $this->data;
126
    }
127
128
    /**
129
     * Returns the amount of data saved for this PPS
130
     *
131
     * @return integer The amount of data (in bytes)
132
     */
133
    protected function getSize()
134
    {
135
        return strlen($this->data);
136
    }
137
138
    /**
139
     * Returns a string with the PPS's WK (What is a WK?)
140
     *
141
     * @return string The binary string
142
     */
143
    public function getPpsWk()
144
    {
145
        $result = $this->name;
146
        $nameLength = strlen($this->name);
147
        for ($i = 0; $i < (64 - $nameLength); $i++) {
148
            $result .= "\x00";
149
        }
150
151
        $datetime = OLE::localDate2OLE($this->timestamp);
152
153
        $result .= pack("v", $nameLength + 2) // 66
154
            . pack("c", $this->type) // 67
155
            . pack("c", 0x00) //UK                // 68
156
            . pack("V", $this->prevPps) //Prev    // 72
157
            . pack("V", $this->nextPps) //Next    // 76
158
            . pack("V", $this->dirPps) //Dir     // 80
159
            . "\x00\x09\x02\x00" // 84
160
            . "\x00\x00\x00\x00" // 88
161
            . "\xc0\x00\x00\x00" // 92
162
            . "\x00\x00\x00\x46" // 96 // Seems to be ok only for Root
163
            . "\x00\x00\x00\x00" // 100
164
            . $datetime // 108
165
            . $datetime // 116
166
            . pack("V", $this->getStartBlock()) // 120
167
            . pack("V", $this->getSize()) // 124
168
            . pack("V", 0); // 128
169
170
        return $result;
171
    }
172
173
    /**
174
     * Updates index and pointers to previous, next and children PPS's for this
175
     * PPS. I don't think it'll work with Dir PPS's.
176
     *
177
     * @param PPS[] &$list Reference to the array of PPS's for the whole OLE container
178
     * @param PPS[] $toSave
179
     * @param $depth
180
     *
181
     * @return integer The index for this PPS
182
     */
183
    public static function setPointers(&$list, $toSave, $depth = 0)
184
    {
185
        $toSaveCount = count($toSave);
186
187
        if (!is_array($toSave) || $toSaveCount == 0) {
188
            return 0xFFFFFFFF;
189
        }
190
191
        $cnt = count($list);
192
        $iPos = intval(floor($toSaveCount / 2));
193
194
        if ($toSaveCount == 1) {
195
            $prev = 0xFFFFFFFF;
196
            $next = 0xFFFFFFFF;
197
        } else {
198
            $aPrev = array_slice($toSave, 0, $iPos);
199
            $prev = self::setPointers($list, $aPrev, $depth++);
200
201
            $aNext = array_slice($toSave, $iPos + 1);
202
            $next = self::setPointers($list, $aNext, $depth++);
203
        }
204
205
        // If the first entry, it's the root... Don't clone it!
206
        $list[$cnt] = ($depth == 0) ? $toSave[$iPos] : clone $toSave[$iPos];
207
        $list[$cnt]->setIndex($cnt);
208
209
        $list[$cnt]->setPrevPps($prev);
210
        $list[$cnt]->setNextPps($next);
211
212
        $dir = self::setPointers($list, $list[$cnt]->getChildren(), $depth++);
213
        $list[$cnt]->setDirPps($dir);
214
215
        return $cnt;
216
    }
217
218
    /**
219
     * @return bool
220
     */
221
    public function isFile()
222
    {
223
        return $this->type == self::PPS_TYPE_FILE;
224
    }
225
226
    /**
227
     * @return bool
228
     */
229
    public function isRoot()
230
    {
231
        return $this->type == self::PPS_TYPE_ROOT;
232
    }
233
234
    /**
235
     * @param int $startBlock
236
     */
237
    public function setStartBlock($startBlock)
238
    {
239
        $this->startBlock = $startBlock;
240
    }
241
242
    /**
243
     * @return int
244
     */
245
    public function getStartBlock()
246
    {
247
        return isset($this->startBlock) ? $this->startBlock : 0;
248
    }
249
250
    /**
251
     * @return array
252
     */
253
    public function getChildren()
254
    {
255
        return $this->children;
256
    }
257
258
    /**
259
     * @param int $index
260
     */
261
    public function setIndex($index)
262
    {
263
        $this->index = $index;
264
    }
265
266
    /**
267
     * @param int $prevPps
268
     */
269
    public function setPrevPps($prevPps)
270
    {
271
        $this->prevPps = $prevPps;
272
    }
273
274
    /**
275
     * @param int $nextPps
276
     */
277
    public function setNextPps($nextPps)
278
    {
279
        $this->nextPps = $nextPps;
280
    }
281
282
    /**
283
     * @param int $dirPps
284
     */
285
    public function setDirPps($dirPps)
286
    {
287
        $this->dirPps = $dirPps;
288
    }
289
290
    /**
291
     * Append data to PPS
292
     *
293
     * @param string $data The data to append
294
     */
295
    public function append($data)
296
    {
297
        $this->data .= $data;
298
    }
299
}
300