Failed Conditions
Push — develop ( a6bb49...7a4cbd )
by Adrien
36:15
created

Root::_saveBbd()   F

Complexity

Conditions 21
Paths 17920

Size

Total Lines 78

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 66.6108

Importance

Changes 0
Metric Value
cc 21
nc 17920
nop 3
dl 0
loc 78
ccs 26
cts 49
cp 0.5306
crap 66.6108
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
3
namespace PhpOffice\PhpSpreadsheet\Shared\OLE\PPS;
4
5
// vim: set expandtab tabstop=4 shiftwidth=4:
6
// +----------------------------------------------------------------------+
7
// | PHP Version 4                                                        |
8
// +----------------------------------------------------------------------+
9
// | Copyright (c) 1997-2002 The PHP Group                                |
10
// +----------------------------------------------------------------------+
11
// | This source file is subject to version 2.02 of the PHP license,      |
12
// | that is bundled with this package in the file LICENSE, and is        |
13
// | available at through the world-wide-web at                           |
14
// | http://www.php.net/license/2_02.txt.                                 |
15
// | If you did not receive a copy of the PHP license and are unable to   |
16
// | obtain it through the world-wide-web, please send a note to          |
17
// | [email protected] so we can mail you a copy immediately.               |
18
// +----------------------------------------------------------------------+
19
// | Author: Xavier Noguer <[email protected]>                              |
20
// | Based on OLE::Storage_Lite by Kawai, Takanori                        |
21
// +----------------------------------------------------------------------+
22
//
23
use PhpOffice\PhpSpreadsheet\Shared\OLE;
24
use PhpOffice\PhpSpreadsheet\Shared\OLE\PPS;
25
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
26
27
/**
28
 * Class for creating Root PPS's for OLE containers.
29
 *
30
 * @author   Xavier Noguer <[email protected]>
31
 *
32
 * @category PhpSpreadsheet
33
 */
34
class Root extends PPS
35
{
36
    /**
37
     * Directory for temporary files.
38
     *
39
     * @var string
40
     */
41
    protected $tempDirectory;
42
43
    /**
44
     * @var resource
45
     */
46
    private $fileHandle;
47
48
    /**
49
     * @var string
50
     */
51
    private $tempFilename;
52
53
    /**
54
     * @var int
55
     */
56
    private $smallBlockSize;
57
58
    /**
59
     * @var int
60
     */
61
    private $bigBlockSize;
62
63
    /**
64
     * @param int $time_1st A timestamp
65
     * @param int $time_2nd A timestamp
66
     * @param File[] $raChild
67
     */
68 43
    public function __construct($time_1st, $time_2nd, $raChild)
69
    {
70 43
        $this->tempDirectory = \PhpOffice\PhpSpreadsheet\Shared\File::sysGetTempDir();
71
72 43
        parent::__construct(null, OLE::ascToUcs('Root Entry'), OLE::OLE_PPS_TYPE_ROOT, null, null, null, $time_1st, $time_2nd, null, $raChild);
73 43
    }
74
75
    /**
76
     * Method for saving the whole OLE container (including files).
77
     * In fact, if called with an empty argument (or '-'), it saves to a
78
     * temporary file and then outputs it's contents to stdout.
79
     * If a resource pointer to a stream created by fopen() is passed
80
     * it will be used, but you have to close such stream by yourself.
81
     *
82
     * @param resource|string $filename the name of the file or stream where to save the OLE container
83
     *
84
     * @throws WriterException
85
     *
86
     * @return bool true on success
87
     */
88 43
    public function save($filename)
89
    {
90
        // Initial Setting for saving
91 43
        $this->bigBlockSize = pow(
92 43
            2,
93 43
            (isset($this->bigBlockSize)) ? self::adjust2($this->bigBlockSize) : 9
94
        );
95 43
        $this->smallBlockSize = pow(
96 43
            2,
97 43
            (isset($this->smallBlockSize)) ? self::adjust2($this->smallBlockSize) : 6
98
        );
99
100 43
        if (is_resource($filename)) {
101
            $this->fileHandle = $filename;
102 43
        } elseif ($filename == '-' || $filename == '') {
103
            if ($this->tempDirectory === null) {
104
                $this->tempDirectory = \PhpOffice\PhpSpreadsheet\Shared\File::sysGetTempDir();
105
            }
106
            $this->tempFilename = tempnam($this->tempDirectory, 'OLE_PPS_Root');
107
            $this->fileHandle = fopen($this->tempFilename, 'w+b');
0 ignored issues
show
Documentation Bug introduced by
It seems like fopen($this->tempFilename, 'w+b') can also be of type false. However, the property $fileHandle is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
108
            if ($this->fileHandle == false) {
109
                throw new WriterException("Can't create temporary file.");
110
            }
111
        } else {
112 43
            $this->fileHandle = fopen($filename, 'wb');
113
        }
114 43
        if ($this->fileHandle == false) {
115
            throw new WriterException("Can't open $filename. It may be in use or protected.");
116
        }
117
        // Make an array of PPS's (for Save)
118 43
        $aList = [];
119 43
        PPS::_savePpsSetPnt($aList, [$this]);
120
        // calculate values for header
121 43
        list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo);
122
        // Save Header
123 43
        $this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
0 ignored issues
show
Bug introduced by
$iBBcnt of type double is incompatible with the type integer expected by parameter $iBBcnt of PhpOffice\PhpSpreadsheet...PPS\Root::_saveHeader(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

123
        $this->_saveHeader($iSBDcnt, /** @scrutinizer ignore-type */ $iBBcnt, $iPPScnt);
Loading history...
Bug introduced by
$iPPScnt of type double is incompatible with the type integer expected by parameter $iPPScnt of PhpOffice\PhpSpreadsheet...PPS\Root::_saveHeader(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

123
        $this->_saveHeader($iSBDcnt, $iBBcnt, /** @scrutinizer ignore-type */ $iPPScnt);
Loading history...
Bug introduced by
$iSBDcnt of type double is incompatible with the type integer expected by parameter $iSBDcnt of PhpOffice\PhpSpreadsheet...PPS\Root::_saveHeader(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

123
        $this->_saveHeader(/** @scrutinizer ignore-type */ $iSBDcnt, $iBBcnt, $iPPScnt);
Loading history...
124
125
        // Make Small Data string (write SBD)
126 43
        $this->_data = $this->_makeSmallData($aList);
127
128
        // Write BB
129 43
        $this->_saveBigData($iSBDcnt, $aList);
0 ignored issues
show
Bug introduced by
$iSBDcnt of type double is incompatible with the type integer expected by parameter $iStBlk of PhpOffice\PhpSpreadsheet...PS\Root::_saveBigData(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

129
        $this->_saveBigData(/** @scrutinizer ignore-type */ $iSBDcnt, $aList);
Loading history...
130
        // Write PPS
131 43
        $this->_savePps($aList);
132
        // Write Big Block Depot and BDList and Adding Header informations
133 43
        $this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
0 ignored issues
show
Bug introduced by
$iBBcnt of type double is incompatible with the type integer expected by parameter $iBsize of PhpOffice\PhpSpreadsheet...LE\PPS\Root::_saveBbd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
        $this->_saveBbd($iSBDcnt, /** @scrutinizer ignore-type */ $iBBcnt, $iPPScnt);
Loading history...
Bug introduced by
$iPPScnt of type double is incompatible with the type integer expected by parameter $iPpsCnt of PhpOffice\PhpSpreadsheet...LE\PPS\Root::_saveBbd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
        $this->_saveBbd($iSBDcnt, $iBBcnt, /** @scrutinizer ignore-type */ $iPPScnt);
Loading history...
Bug introduced by
$iSBDcnt of type double is incompatible with the type integer expected by parameter $iSbdSize of PhpOffice\PhpSpreadsheet...LE\PPS\Root::_saveBbd(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
        $this->_saveBbd(/** @scrutinizer ignore-type */ $iSBDcnt, $iBBcnt, $iPPScnt);
Loading history...
134
135 43
        if (!is_resource($filename)) {
136 43
            fclose($this->fileHandle);
137
        }
138
139 43
        return true;
140
    }
141
142
    /**
143
     * Calculate some numbers.
144
     *
145
     * @param array $raList Reference to an array of PPS's
146
     *
147
     * @return float[] The array of numbers
148
     */
149 43
    public function _calcSize(&$raList)
150
    {
151
        // Calculate Basic Setting
152 43
        list($iSBDcnt, $iBBcnt, $iPPScnt) = [0, 0, 0];
153 43
        $iSmallLen = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $iSmallLen is dead and can be removed.
Loading history...
154 43
        $iSBcnt = 0;
155 43
        $iCount = count($raList);
156 43
        for ($i = 0; $i < $iCount; ++$i) {
157 43
            if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) {
158 43
                $raList[$i]->Size = $raList[$i]->getDataLen();
159 43
                if ($raList[$i]->Size < OLE::OLE_DATA_SIZE_SMALL) {
160 43
                    $iSBcnt += floor($raList[$i]->Size / $this->smallBlockSize)
161 43
                                  + (($raList[$i]->Size % $this->smallBlockSize) ? 1 : 0);
162
                } else {
163 21
                    $iBBcnt += (floor($raList[$i]->Size / $this->bigBlockSize) +
164 21
                        (($raList[$i]->Size % $this->bigBlockSize) ? 1 : 0));
165
                }
166
            }
167
        }
168 43
        $iSmallLen = $iSBcnt * $this->smallBlockSize;
169 43
        $iSlCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE);
170 43
        $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt) ? 1 : 0);
171 43
        $iBBcnt += (floor($iSmallLen / $this->bigBlockSize) +
172 43
                      (($iSmallLen % $this->bigBlockSize) ? 1 : 0));
173 43
        $iCnt = count($raList);
174 43
        $iBdCnt = $this->bigBlockSize / OLE::OLE_PPS_SIZE;
175 43
        $iPPScnt = (floor($iCnt / $iBdCnt) + (($iCnt % $iBdCnt) ? 1 : 0));
176
177 43
        return [$iSBDcnt, $iBBcnt, $iPPScnt];
178
    }
179
180
    /**
181
     * Helper function for caculating a magic value for block sizes.
182
     *
183
     * @param int $i2 The argument
184
     *
185
     * @see save()
186
     *
187
     * @return float
188
     */
189
    private static function adjust2($i2)
190
    {
191
        $iWk = log($i2) / log(2);
192
193
        return ($iWk > floor($iWk)) ? floor($iWk) + 1 : $iWk;
194
    }
195
196
    /**
197
     * Save OLE header.
198
     *
199
     * @param int $iSBDcnt
200
     * @param int $iBBcnt
201
     * @param int $iPPScnt
202
     */
203 43
    public function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt)
204
    {
205 43
        $FILE = $this->fileHandle;
206
207
        // Calculate Basic Setting
208 43
        $iBlCnt = $this->bigBlockSize / OLE::OLE_LONG_INT_SIZE;
209 43
        $i1stBdL = ($this->bigBlockSize - 0x4C) / OLE::OLE_LONG_INT_SIZE;
210
211 43
        $iBdExL = 0;
212 43
        $iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
213 43
        $iAllW = $iAll;
214 43
        $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
215 43
        $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0);
216
217
        // Calculate BD count
218 43
        if ($iBdCnt > $i1stBdL) {
219
            while (1) {
220
                ++$iBdExL;
221
                ++$iAllW;
222
                $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
223
                $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0);
224
                if ($iBdCnt <= ($iBdExL * $iBlCnt + $i1stBdL)) {
225
                    break;
226
                }
227
            }
228
        }
229
230
        // Save Header
231 43
        fwrite(
232 43
            $FILE,
233
            "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
234
            . "\x00\x00\x00\x00"
235
            . "\x00\x00\x00\x00"
236
            . "\x00\x00\x00\x00"
237
            . "\x00\x00\x00\x00"
238 43
            . pack('v', 0x3b)
239 43
            . pack('v', 0x03)
240 43
            . pack('v', -2)
241 43
            . pack('v', 9)
242 43
            . pack('v', 6)
243 43
            . pack('v', 0)
244 43
            . "\x00\x00\x00\x00"
245 43
            . "\x00\x00\x00\x00"
246 43
            . pack('V', $iBdCnt)
247 43
            . pack('V', $iBBcnt + $iSBDcnt) //ROOT START
248 43
            . pack('V', 0)
249 43
            . pack('V', 0x1000)
250 43
            . pack('V', $iSBDcnt ? 0 : -2) //Small Block Depot
251 43
            . pack('V', $iSBDcnt)
252
        );
253
        // Extra BDList Start, Count
254 43
        if ($iBdCnt < $i1stBdL) {
255 43
            fwrite(
256 43
                $FILE,
257 43
                pack('V', -2) // Extra BDList Start
258 43
                . pack('V', 0)// Extra BDList Count
259
            );
260
        } else {
261
            fwrite($FILE, pack('V', $iAll + $iBdCnt) . pack('V', $iBdExL));
262
        }
263
264
        // BDList
265 43
        for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) {
266 43
            fwrite($FILE, pack('V', $iAll + $i));
267
        }
268 43
        if ($i < $i1stBdL) {
269 43
            $jB = $i1stBdL - $i;
270 43
            for ($j = 0; $j < $jB; ++$j) {
271 43
                fwrite($FILE, (pack('V', -1)));
272
            }
273
        }
274 43
    }
275
276
    /**
277
     * Saving big data (PPS's with data bigger than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL).
278
     *
279
     * @param int $iStBlk
280
     * @param array &$raList Reference to array of PPS's
281
     */
282 43
    public function _saveBigData($iStBlk, &$raList)
283
    {
284 43
        $FILE = $this->fileHandle;
285
286
        // cycle through PPS's
287 43
        $iCount = count($raList);
288 43
        for ($i = 0; $i < $iCount; ++$i) {
289 43
            if ($raList[$i]->Type != OLE::OLE_PPS_TYPE_DIR) {
290 43
                $raList[$i]->Size = $raList[$i]->getDataLen();
291 43
                if (($raList[$i]->Size >= OLE::OLE_DATA_SIZE_SMALL) || (($raList[$i]->Type == OLE::OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data))) {
292 43
                    fwrite($FILE, $raList[$i]->_data);
293
294 43
                    if ($raList[$i]->Size % $this->bigBlockSize) {
295 40
                        fwrite($FILE, str_repeat("\x00", $this->bigBlockSize - ($raList[$i]->Size % $this->bigBlockSize)));
296
                    }
297
                    // Set For PPS
298 43
                    $raList[$i]->startBlock = $iStBlk;
299
                    $iStBlk +=
300 43
                            (floor($raList[$i]->Size / $this->bigBlockSize) +
301 43
                                (($raList[$i]->Size % $this->bigBlockSize) ? 1 : 0));
302
                }
303
            }
304
        }
305 43
    }
306
307
    /**
308
     * get small data (PPS's with data smaller than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL).
309
     *
310
     * @param array &$raList Reference to array of PPS's
311
     *
312
     * @return string
313
     */
314 43
    public function _makeSmallData(&$raList)
315
    {
316 43
        $sRes = '';
317 43
        $FILE = $this->fileHandle;
318 43
        $iSmBlk = 0;
319
320 43
        $iCount = count($raList);
321 43
        for ($i = 0; $i < $iCount; ++$i) {
322
            // Make SBD, small data string
323 43
            if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) {
324 43
                if ($raList[$i]->Size <= 0) {
325
                    continue;
326
                }
327 43
                if ($raList[$i]->Size < OLE::OLE_DATA_SIZE_SMALL) {
328 43
                    $iSmbCnt = floor($raList[$i]->Size / $this->smallBlockSize)
329 43
                                  + (($raList[$i]->Size % $this->smallBlockSize) ? 1 : 0);
330
                    // Add to SBD
331 43
                    $jB = $iSmbCnt - 1;
332 43
                    for ($j = 0; $j < $jB; ++$j) {
333 43
                        fwrite($FILE, pack('V', $j + $iSmBlk + 1));
334
                    }
335 43
                    fwrite($FILE, pack('V', -2));
336
337
                    // Add to Data String(this will be written for RootEntry)
338 43
                    $sRes .= $raList[$i]->_data;
339 43
                    if ($raList[$i]->Size % $this->smallBlockSize) {
340 43
                        $sRes .= str_repeat("\x00", $this->smallBlockSize - ($raList[$i]->Size % $this->smallBlockSize));
341
                    }
342
                    // Set for PPS
343 43
                    $raList[$i]->startBlock = $iSmBlk;
344 43
                    $iSmBlk += $iSmbCnt;
345
                }
346
            }
347
        }
348 43
        $iSbCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE);
349 43
        if ($iSmBlk % $iSbCnt) {
350 43
            $iB = $iSbCnt - ($iSmBlk % $iSbCnt);
351 43
            for ($i = 0; $i < $iB; ++$i) {
352 43
                fwrite($FILE, pack('V', -1));
353
            }
354
        }
355
356 43
        return $sRes;
357
    }
358
359
    /**
360
     * Saves all the PPS's WKs.
361
     *
362
     * @param array $raList Reference to an array with all PPS's
363
     */
364 43
    public function _savePps(&$raList)
365
    {
366
        // Save each PPS WK
367 43
        $iC = count($raList);
368 43
        for ($i = 0; $i < $iC; ++$i) {
369 43
            fwrite($this->fileHandle, $raList[$i]->_getPpsWk());
370
        }
371
        // Adjust for Block
372 43
        $iCnt = count($raList);
373 43
        $iBCnt = $this->bigBlockSize / OLE::OLE_PPS_SIZE;
374 43
        if ($iCnt % $iBCnt) {
375
            fwrite($this->fileHandle, str_repeat("\x00", ($iBCnt - ($iCnt % $iBCnt)) * OLE::OLE_PPS_SIZE));
376
        }
377 43
    }
378
379
    /**
380
     * Saving Big Block Depot.
381
     *
382
     * @param int $iSbdSize
383
     * @param int $iBsize
384
     * @param int $iPpsCnt
385
     */
386 43
    public function _saveBbd($iSbdSize, $iBsize, $iPpsCnt)
387
    {
388 43
        $FILE = $this->fileHandle;
389
        // Calculate Basic Setting
390 43
        $iBbCnt = $this->bigBlockSize / OLE::OLE_LONG_INT_SIZE;
391 43
        $i1stBdL = ($this->bigBlockSize - 0x4C) / OLE::OLE_LONG_INT_SIZE;
392
393 43
        $iBdExL = 0;
394 43
        $iAll = $iBsize + $iPpsCnt + $iSbdSize;
395 43
        $iAllW = $iAll;
396 43
        $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
397 43
        $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0);
398
        // Calculate BD count
399 43
        if ($iBdCnt > $i1stBdL) {
400
            while (1) {
401
                ++$iBdExL;
402
                ++$iAllW;
403
                $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
404
                $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0);
405
                if ($iBdCnt <= ($iBdExL * $iBbCnt + $i1stBdL)) {
406
                    break;
407
                }
408
            }
409
        }
410
411
        // Making BD
412
        // Set for SBD
413 43
        if ($iSbdSize > 0) {
414 43
            for ($i = 0; $i < ($iSbdSize - 1); ++$i) {
415
                fwrite($FILE, pack('V', $i + 1));
416
            }
417 43
            fwrite($FILE, pack('V', -2));
418
        }
419
        // Set for B
420 43
        for ($i = 0; $i < ($iBsize - 1); ++$i) {
421 43
            fwrite($FILE, pack('V', $i + $iSbdSize + 1));
422
        }
423 43
        fwrite($FILE, pack('V', -2));
424
425
        // Set for PPS
426 43
        for ($i = 0; $i < ($iPpsCnt - 1); ++$i) {
427
            fwrite($FILE, pack('V', $i + $iSbdSize + $iBsize + 1));
428
        }
429 43
        fwrite($FILE, pack('V', -2));
430
        // Set for BBD itself ( 0xFFFFFFFD : BBD)
431 43
        for ($i = 0; $i < $iBdCnt; ++$i) {
432 43
            fwrite($FILE, pack('V', 0xFFFFFFFD));
433
        }
434
        // Set for ExtraBDList
435 43
        for ($i = 0; $i < $iBdExL; ++$i) {
436
            fwrite($FILE, pack('V', 0xFFFFFFFC));
437
        }
438
        // Adjust for Block
439 43
        if (($iAllW + $iBdCnt) % $iBbCnt) {
440 43
            $iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt));
441 43
            for ($i = 0; $i < $iBlock; ++$i) {
442 43
                fwrite($FILE, pack('V', -1));
443
            }
444
        }
445
        // Extra BDList
446 43
        if ($iBdCnt > $i1stBdL) {
447
            $iN = 0;
448
            $iNb = 0;
449
            for ($i = $i1stBdL; $i < $iBdCnt; $i++, ++$iN) {
450
                if ($iN >= ($iBbCnt - 1)) {
451
                    $iN = 0;
452
                    ++$iNb;
453
                    fwrite($FILE, pack('V', $iAll + $iBdCnt + $iNb));
454
                }
455
                fwrite($FILE, pack('V', $iBsize + $iSbdSize + $iPpsCnt + $i));
456
            }
457
            if (($iBdCnt - $i1stBdL) % ($iBbCnt - 1)) {
458
                $iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1));
459
                for ($i = 0; $i < $iB; ++$i) {
460
                    fwrite($FILE, pack('V', -1));
461
                }
462
            }
463
            fwrite($FILE, pack('V', -2));
464
        }
465 43
    }
466
}
467