Completed
Push — master ( dca322...47e653 )
by Julito
08:54
created

OLE_PPS_Root::_saveBbd()   F

Complexity

Conditions 21
Paths 17920

Size

Total Lines 76
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 46
nc 17920
nop 3
dl 0
loc 76
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
// +----------------------------------------------------------------------+
4
// | PHP Version 4                                                        |
5
// +----------------------------------------------------------------------+
6
// | Copyright (c) 1997-2002 The PHP Group                                |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.02 of the PHP license,      |
9
// | that is bundled with this package in the file LICENSE, and is        |
10
// | available at through the world-wide-web at                           |
11
// | http://www.php.net/license/2_02.txt.                                 |
12
// | If you did not receive a copy of the PHP license and are unable to   |
13
// | obtain it through the world-wide-web, please send a note to          |
14
// | [email protected] so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
16
// | Author: Xavier Noguer <[email protected]>                              |
17
// | Based on OLE::Storage_Lite by Kawai, Takanori                        |
18
// +----------------------------------------------------------------------+
19
//
20
// $Id: Root.php,v 1.9 2005/04/23 21:53:49 dufuz Exp $
21
22
23
require_once __DIR__.'/../PPS.php';
24
25
/**
26
* Class for creating Root PPS's for OLE containers
27
*
28
* @author   Xavier Noguer <[email protected]>
29
* @category Structures
30
* @package  OLE
31
*/
32
class OLE_PPS_Root extends OLE_PPS
33
{
34
    /**
35
    * The temporary dir for storing the OLE file
36
    * @var string
37
    */
38
    var $_tmp_dir;
39
40
    /**
41
    * Constructor
42
    *
43
    * @access public
44
    * @param integer $time_1st A timestamp
45
    * @param integer $time_2nd A timestamp
46
    */
47
    function OLE_PPS_Root($time_1st, $time_2nd, $raChild)
48
    {
49
        $this->_tmp_dir = '';
50
        $this->OLE_PPS(
51
           null,
52
           OLE::Asc2Ucs('Root Entry'),
53
           OLE_PPS_TYPE_ROOT,
54
           null,
55
           null,
56
           null,
57
           $time_1st,
58
           $time_2nd,
59
           null,
60
           $raChild);
61
    }
62
63
    /**
64
    * Sets the temp dir used for storing the OLE file
65
    *
66
    * @access public
67
    * @param string $dir The dir to be used as temp dir
68
    * @return true if given dir is valid, false otherwise
69
    */
70
    function setTempDir($dir)
71
    {
72
        if (is_dir($dir)) {
73
            $this->_tmp_dir = $dir;
74
            return true;
75
        }
76
        return false;
77
    }
78
79
    /**
80
    * Method for saving the whole OLE container (including files).
81
    * In fact, if called with an empty argument (or '-'), it saves to a
82
    * temporary file and then outputs it's contents to stdout.
83
    *
84
    * @param string $filename The name of the file where to save the OLE container
85
    * @access public
86
    * @return mixed true on success, PEAR_Error on failure
87
    */
88
    function save($filename)
89
    {
90
        // Initial Setting for saving
91
        $this->_BIG_BLOCK_SIZE  = pow(2,
92
                      ((isset($this->_BIG_BLOCK_SIZE))? $this->_adjust2($this->_BIG_BLOCK_SIZE)  : 9));
93
        $this->_SMALL_BLOCK_SIZE= pow(2,
94
                      ((isset($this->_SMALL_BLOCK_SIZE))?  $this->_adjust2($this->_SMALL_BLOCK_SIZE): 6));
95
96
        // Open temp file if we are sending output to stdout
97
        if (($filename == '-') || ($filename == '')) {
98
            $this->_tmp_filename = tempnam($this->_tmp_dir, "OLE_PPS_Root");
99
            $this->_FILEH_ = @fopen($this->_tmp_filename,"w+b");
100
            if ($this->_FILEH_ == false) {
101
                return $this->raiseError("Can't create temporary file.");
102
            }
103
        } else {
104
            $this->_FILEH_ = @fopen($filename, "wb");
105
            if ($this->_FILEH_ == false) {
106
                return $this->raiseError("Can't open $filename. It may be in use or protected.");
107
            }
108
        }
109
        // Make an array of PPS's (for Save)
110
        $aList = array();
111
        $this->_savePpsSetPnt($aList);
112
        // calculate values for header
113
        list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo);
114
        // Save Header
115
        $this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
116
117
        // Make Small Data string (write SBD)
118
        $this->_data = $this->_makeSmallData($aList);
119
120
        // Write BB
121
        $this->_saveBigData($iSBDcnt, $aList);
122
        // Write PPS
123
        $this->_savePps($aList);
124
        // Write Big Block Depot and BDList and Adding Header informations
125
        $this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
126
        // Close File, send it to stdout if necessary
127
        if (($filename == '-') || ($filename == '')) {
128
            fseek($this->_FILEH_, 0);
129
            fpassthru($this->_FILEH_);
130
            @fclose($this->_FILEH_);
131
            // Delete the temporary file.
132
            @unlink($this->_tmp_filename);
133
        } else {
134
            @fclose($this->_FILEH_);
135
        }
136
137
        return true;
138
    }
139
140
    /**
141
    * Calculate some numbers
142
    *
143
    * @access private
144
    * @param array $raList Reference to an array of PPS's
145
    * @return array The array of numbers
146
    */
147
    function _calcSize(&$raList)
148
    {
149
        // Calculate Basic Setting
150
        list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0);
151
        $iSmallLen = 0;
152
        $iSBcnt = 0;
153
        for ($i = 0; $i < count($raList); $i++) {
154
            if ($raList[$i]->Type == OLE_PPS_TYPE_FILE) {
155
                $raList[$i]->Size = $raList[$i]->_DataLen();
156
                if ($raList[$i]->Size < OLE_DATA_SIZE_SMALL) {
157
                    $iSBcnt += floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
158
                                  + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
159
                } else {
160
                    $iBBcnt += (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) +
161
                        (($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0));
162
                }
163
            }
164
        }
165
        $iSmallLen = $iSBcnt * $this->_SMALL_BLOCK_SIZE;
166
        $iSlCnt = floor($this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE);
167
        $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt)? 1:0);
168
        $iBBcnt +=  (floor($iSmallLen / $this->_BIG_BLOCK_SIZE) +
169
                      (( $iSmallLen % $this->_BIG_BLOCK_SIZE)? 1: 0));
170
        $iCnt = count($raList);
171
        $iBdCnt = $this->_BIG_BLOCK_SIZE / OLE_PPS_SIZE;
172
        $iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt)? 1: 0));
173
174
        return array($iSBDcnt, $iBBcnt, $iPPScnt);
175
    }
176
177
    /**
178
    * Helper function for caculating a magic value for block sizes
179
    *
180
    * @access private
181
    * @param integer $i2 The argument
182
    * @see save()
183
    * @return integer
184
    */
185
    function _adjust2($i2)
186
    {
187
        $iWk = log($i2)/log(2);
188
        return ($iWk > floor($iWk))? floor($iWk)+1:$iWk;
189
    }
190
191
    /**
192
    * Save OLE header
193
    *
194
    * @access private
195
    * @param integer $iSBDcnt
196
    * @param integer $iBBcnt
197
    * @param integer $iPPScnt
198
    */
199
    function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt)
200
    {
201
        $FILE = $this->_FILEH_;
202
203
        // Calculate Basic Setting
204
        $iBlCnt = $this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE;
205
        $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE_LONG_INT_SIZE;
206
207
        $iBdExL = 0;
208
        $iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
209
        $iAllW = $iAll;
210
        $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0);
211
        $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0);
212
213
        // Calculate BD count
214
        if ($iBdCnt > $i1stBdL) {
215
            while (1) {
216
                $iBdExL++;
217
                $iAllW++;
218
                $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0);
219
                $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0);
220
                if ($iBdCnt <= ($iBdExL*$iBlCnt+ $i1stBdL)) {
221
                    break;
222
                }
223
            }
224
        }
225
226
        // Save Header
227
        fwrite($FILE,
228
                  "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
229
                  . "\x00\x00\x00\x00"
230
                  . "\x00\x00\x00\x00"
231
                  . "\x00\x00\x00\x00"
232
                  . "\x00\x00\x00\x00"
233
                  . pack("v", 0x3b)
234
                  . pack("v", 0x03)
235
                  . pack("v", -2)
236
                  . pack("v", 9)
237
                  . pack("v", 6)
238
                  . pack("v", 0)
239
                  . "\x00\x00\x00\x00"
240
                  . "\x00\x00\x00\x00"
241
                  . pack("V", $iBdCnt)
242
                  . pack("V", $iBBcnt+$iSBDcnt) //ROOT START
243
                  . pack("V", 0)
244
                  . pack("V", 0x1000)
245
                  . pack("V", 0)                  //Small Block Depot
246
                  . pack("V", 1)
247
          );
248
        // Extra BDList Start, Count
249
        if ($iBdCnt < $i1stBdL) {
250
            fwrite($FILE,
251
                      pack("V", -2).      // Extra BDList Start
252
                      pack("V", 0)        // Extra BDList Count
253
                  );
254
        } else {
255
            fwrite($FILE, pack("V", $iAll+$iBdCnt) . pack("V", $iBdExL));
256
        }
257
258
        // BDList
259
        for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; $i++) {
260
            fwrite($FILE, pack("V", $iAll+$i));
261
        }
262
        if ($i < $i1stBdL) {
263
            for ($j = 0; $j < ($i1stBdL-$i); $j++) {
264
                fwrite($FILE, (pack("V", -1)));
265
            }
266
        }
267
    }
268
269
    /**
270
    * Saving big data (PPS's with data bigger than OLE_DATA_SIZE_SMALL)
271
    *
272
    * @access private
273
    * @param integer $iStBlk
274
    * @param array &$raList Reference to array of PPS's
275
    */
276
    function _saveBigData($iStBlk, &$raList)
277
    {
278
        $FILE = $this->_FILEH_;
279
280
        // cycle through PPS's
281
        for ($i = 0; $i < count($raList); $i++) {
282
            if ($raList[$i]->Type != OLE_PPS_TYPE_DIR) {
283
                $raList[$i]->Size = $raList[$i]->_DataLen();
284
                if (($raList[$i]->Size >= OLE_DATA_SIZE_SMALL) ||
285
                    (($raList[$i]->Type == OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data)))
286
                {
287
                    // Write Data
288
                    if (isset($raList[$i]->_PPS_FILE)) {
289
                        $iLen = 0;
290
                        fseek($raList[$i]->_PPS_FILE, 0); // To The Top
291
                        while($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) {
292
                            $iLen += strlen($sBuff);
293
                            fwrite($FILE, $sBuff);
294
                        }
295
                    } else {
296
                        fwrite($FILE, $raList[$i]->_data);
297
                    }
298
299
                    if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) {
300
                        for ($j = 0; $j < ($this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)); $j++) {
301
                            fwrite($FILE, "\x00");
302
                        }
303
                    }
304
                    // Set For PPS
305
                    $raList[$i]->_StartBlock = $iStBlk;
306
                    $iStBlk +=
307
                            (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) +
308
                                (($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0));
309
                }
310
                // Close file for each PPS, and unlink it
311
                if (isset($raList[$i]->_PPS_FILE)) {
312
                    @fclose($raList[$i]->_PPS_FILE);
313
                    $raList[$i]->_PPS_FILE = null;
314
                    @unlink($raList[$i]->_tmp_filename);
315
                }
316
            }
317
        }
318
    }
319
320
    /**
321
    * get small data (PPS's with data smaller than OLE_DATA_SIZE_SMALL)
322
    *
323
    * @access private
324
    * @param array &$raList Reference to array of PPS's
325
    */
326
    function _makeSmallData(&$raList)
327
    {
328
        $sRes = '';
329
        $FILE = $this->_FILEH_;
330
        $iSmBlk = 0;
331
332
        for ($i = 0; $i < count($raList); $i++) {
333
            // Make SBD, small data string
334
            if ($raList[$i]->Type == OLE_PPS_TYPE_FILE) {
335
                if ($raList[$i]->Size <= 0) {
336
                    continue;
337
                }
338
                if ($raList[$i]->Size < OLE_DATA_SIZE_SMALL) {
339
                    $iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
340
                                  + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
341
                    // Add to SBD
342
                    for ($j = 0; $j < ($iSmbCnt-1); $j++) {
343
                        fwrite($FILE, pack("V", $j+$iSmBlk+1));
344
                    }
345
                    fwrite($FILE, pack("V", -2));
346
347
                    // Add to Data String(this will be written for RootEntry)
348
                    if ($raList[$i]->_PPS_FILE) {
349
                        fseek($raList[$i]->_PPS_FILE, 0); // To The Top
350
                        while ($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) {
351
                            $sRes .= $sBuff;
352
                        }
353
                    } else {
354
                        $sRes .= $raList[$i]->_data;
355
                    }
356
                    if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) {
357
                        for ($j = 0; $j < ($this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); $j++) {
358
                            $sRes .= "\x00";
359
                        }
360
                    }
361
                    // Set for PPS
362
                    $raList[$i]->_StartBlock = $iSmBlk;
363
                    $iSmBlk += $iSmbCnt;
364
                }
365
            }
366
        }
367
        $iSbCnt = floor($this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE);
368
        if ($iSmBlk % $iSbCnt) {
369
            for ($i = 0; $i < ($iSbCnt - ($iSmBlk % $iSbCnt)); $i++) {
370
                fwrite($FILE, pack("V", -1));
371
            }
372
        }
373
        return $sRes;
374
    }
375
376
    /**
377
    * Saves all the PPS's WKs
378
    *
379
    * @access private
380
    * @param array $raList Reference to an array with all PPS's
381
    */
382
    function _savePps(&$raList)
383
    {
384
        // Save each PPS WK
385
        for ($i = 0; $i < count($raList); $i++) {
386
            fwrite($this->_FILEH_, $raList[$i]->_getPpsWk());
387
        }
388
        // Adjust for Block
389
        $iCnt = count($raList);
390
        $iBCnt = $this->_BIG_BLOCK_SIZE / OLE_PPS_SIZE;
391
        if ($iCnt % $iBCnt) {
392
            for ($i = 0; $i < (($iBCnt - ($iCnt % $iBCnt)) * OLE_PPS_SIZE); $i++) {
393
                fwrite($this->_FILEH_, "\x00");
394
            }
395
        }
396
    }
397
398
    /**
399
    * Saving Big Block Depot
400
    *
401
    * @access private
402
    * @param integer $iSbdSize
403
    * @param integer $iBsize
404
    * @param integer $iPpsCnt
405
    */
406
    function _saveBbd($iSbdSize, $iBsize, $iPpsCnt)
407
    {
408
        $FILE = $this->_FILEH_;
409
        // Calculate Basic Setting
410
        $iBbCnt = $this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE;
411
        $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE_LONG_INT_SIZE;
412
413
        $iBdExL = 0;
414
        $iAll = $iBsize + $iPpsCnt + $iSbdSize;
415
        $iAllW = $iAll;
416
        $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0);
417
        $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
418
        // Calculate BD count
419
        if ($iBdCnt >$i1stBdL) {
420
            while (1) {
421
                $iBdExL++;
422
                $iAllW++;
423
                $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0);
424
                $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
425
                if ($iBdCnt <= ($iBdExL*$iBbCnt+ $i1stBdL)) {
426
                    break;
427
                }
428
            }
429
        }
430
431
        // Making BD
432
        // Set for SBD
433
        if ($iSbdSize > 0) {
434
            for ($i = 0; $i < ($iSbdSize - 1); $i++) {
435
                fwrite($FILE, pack("V", $i+1));
436
            }
437
            fwrite($FILE, pack("V", -2));
438
        }
439
        // Set for B
440
        for ($i = 0; $i < ($iBsize - 1); $i++) {
441
            fwrite($FILE, pack("V", $i+$iSbdSize+1));
442
        }
443
        fwrite($FILE, pack("V", -2));
444
445
        // Set for PPS
446
        for ($i = 0; $i < ($iPpsCnt - 1); $i++) {
447
            fwrite($FILE, pack("V", $i+$iSbdSize+$iBsize+1));
448
        }
449
        fwrite($FILE, pack("V", -2));
450
        // Set for BBD itself ( 0xFFFFFFFD : BBD)
451
        for ($i = 0; $i < $iBdCnt; $i++) {
452
            fwrite($FILE, pack("V", 0xFFFFFFFD));
453
        }
454
        // Set for ExtraBDList
455
        for ($i = 0; $i < $iBdExL; $i++) {
456
            fwrite($FILE, pack("V", 0xFFFFFFFC));
457
        }
458
        // Adjust for Block
459
        if (($iAllW + $iBdCnt) % $iBbCnt) {
460
            for ($i = 0; $i < ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); $i++) {
461
                fwrite($FILE, pack("V", -1));
462
            }
463
        }
464
        // Extra BDList
465
        if ($iBdCnt > $i1stBdL) {
466
            $iN=0;
467
            $iNb=0;
468
            for ($i = $i1stBdL;$i < $iBdCnt; $i++, $iN++) {
469
                if ($iN >= ($iBbCnt - 1)) {
470
                    $iN = 0;
471
                    $iNb++;
472
                    fwrite($FILE, pack("V", $iAll+$iBdCnt+$iNb));
473
                }
474
                fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i));
475
            }
476
            if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) {
477
                for ($i = 0; $i < (($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1))); $i++) {
478
                    fwrite($FILE, pack("V", -1));
479
                }
480
            }
481
            fwrite($FILE, pack("V", -2));
482
        }
483
    }
484
}
485
?>
486