This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Xls\OLE; |
||
4 | |||
5 | class PpsRoot extends PPS |
||
6 | { |
||
7 | /** |
||
8 | * @var |
||
9 | */ |
||
10 | protected $smallBlockSize; |
||
11 | |||
12 | /** |
||
13 | * @var |
||
14 | */ |
||
15 | protected $bigBlockSize; |
||
16 | |||
17 | /** |
||
18 | * @var |
||
19 | */ |
||
20 | protected $rootFilePointer; |
||
21 | |||
22 | /** |
||
23 | * @param integer $timestamp A timestamp |
||
24 | * @param PpsFile[] $children |
||
25 | */ |
||
26 | public function __construct( |
||
27 | $timestamp = null, |
||
28 | $children = array() |
||
29 | ) { |
||
30 | parent::__construct( |
||
31 | null, |
||
32 | OLE::asc2Ucs('Root Entry'), |
||
33 | self::PPS_TYPE_ROOT, |
||
34 | null, |
||
35 | null, |
||
36 | null, |
||
37 | $timestamp, |
||
38 | null, |
||
39 | $children |
||
40 | ); |
||
41 | } |
||
42 | |||
43 | /** |
||
44 | * Method for saving the whole OLE container (including files). |
||
45 | * |
||
46 | * @param string $filename The name of the file where to save the OLE container |
||
47 | * @throws \Exception |
||
48 | * @return boolean |
||
49 | */ |
||
50 | public function save($filename) |
||
51 | { |
||
52 | $this->openFile($filename); |
||
53 | |||
54 | $this->setBlockSizes(); |
||
55 | |||
56 | // Make an array of PPS's (for Save) |
||
57 | $list = array(); |
||
58 | self::setPointers($list, array($this)); |
||
59 | |||
60 | list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->calcSize($list); |
||
61 | |||
62 | $this->saveHeader($iSBDcnt, $iBBcnt, $iPPScnt); |
||
63 | $this->saveSmallData($list); |
||
64 | $this->saveBigData($iSBDcnt, $list); |
||
65 | $this->savePps($list); |
||
66 | $this->saveBigBlockChain($iSBDcnt, $iBBcnt, $iPPScnt); |
||
67 | |||
68 | fclose($this->rootFilePointer); |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * |
||
73 | */ |
||
74 | protected function setBlockSizes() |
||
75 | { |
||
76 | $this->bigBlockSize = pow(2, 9); |
||
77 | $this->smallBlockSize = pow(2, 6); |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * @param $filename |
||
82 | * |
||
83 | * @throws \Exception |
||
84 | */ |
||
85 | protected function openFile($filename) |
||
86 | { |
||
87 | $this->rootFilePointer = @fopen($filename, "wb"); |
||
88 | if ($this->rootFilePointer === false) { |
||
89 | throw new \Exception("Can't open $filename. It may be in use or protected."); |
||
90 | } |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * @param $size |
||
95 | * @param $blockSize |
||
96 | * |
||
97 | * @return float |
||
98 | */ |
||
99 | protected function getBlocksCount($size, $blockSize) |
||
100 | { |
||
101 | return floor($size / $blockSize) + (($size % $blockSize) ? 1 : 0); |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * Calculate some numbers |
||
106 | * |
||
107 | * @param PPS[] $list Reference to an array of PPS's |
||
108 | * |
||
109 | * @return array The array of numbers |
||
110 | */ |
||
111 | protected function calcSize($list) |
||
112 | { |
||
113 | $iSBcnt = 0; |
||
114 | $iBBcnt = 0; |
||
115 | foreach ($list as $item) { |
||
116 | if (!$item->isFile()) { |
||
117 | continue; |
||
118 | } |
||
119 | |||
120 | $size = $item->getSize(); |
||
121 | if ($size < self::DATA_SIZE_SMALL) { |
||
122 | $iSBcnt += $this->getBlocksCount($size, $this->smallBlockSize); |
||
123 | } else { |
||
124 | $iBBcnt += $this->getBlocksCount($size, $this->bigBlockSize); |
||
125 | } |
||
126 | } |
||
127 | |||
128 | $iSmallLen = $iSBcnt * $this->smallBlockSize; |
||
129 | $iSlCnt = $this->getPointersPerBlock($this->bigBlockSize); |
||
130 | $iSBDcnt = $this->getBlocksCount($iSBcnt, $iSlCnt); |
||
131 | $iBBcnt += $this->getBlocksCount($iSmallLen, $this->bigBlockSize); |
||
132 | $iBdCnt = $this->getPointersPerBlock($this->bigBlockSize, self::PPS_SIZE); |
||
133 | $iPPScnt = $this->getBlocksCount(count($list), $iBdCnt); |
||
134 | |||
135 | return array($iSBDcnt, $iBBcnt, $iPPScnt); |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Saving big data (PPS's with data bigger than OLE_DATA_SIZE_SMALL) |
||
140 | * |
||
141 | * @param integer $iStBlk |
||
142 | * @param PPS[] &$list Reference to array of PPS's |
||
143 | */ |
||
144 | public function saveBigData($iStBlk, &$list) |
||
145 | { |
||
146 | foreach ($list as $item) { |
||
147 | $size = $item->getSize(); |
||
148 | if ($size >= self::DATA_SIZE_SMALL |
||
149 | || ($item->isRoot() && $item->hasData()) |
||
150 | ) { |
||
151 | $this->write($item->getData()); |
||
152 | |||
153 | if ($size % $this->bigBlockSize) { |
||
154 | $zeroByteCount = ($this->bigBlockSize - ($size % $this->bigBlockSize)); |
||
155 | $this->write(str_repeat("\x00", $zeroByteCount)); |
||
156 | } |
||
157 | |||
158 | // Set For PPS |
||
159 | $item->setStartBlock($iStBlk); |
||
160 | $iStBlk += $this->getBlocksCount($size, $this->bigBlockSize); |
||
161 | } |
||
162 | } |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * get small data (PPS's with data smaller than OLE_DATA_SIZE_SMALL) |
||
167 | * |
||
168 | * @param PPS[] &$list Reference to array of PPS's |
||
169 | * @return string |
||
170 | */ |
||
171 | protected function saveSmallData(&$list) |
||
172 | { |
||
173 | $result = ''; |
||
174 | $iSmBlk = 0; |
||
175 | foreach ($list as $item) { |
||
176 | if (!$item->isFile()) { |
||
177 | continue; |
||
178 | } |
||
179 | |||
180 | $size = $item->getSize(); |
||
181 | if ($size <= 0 || $size >= self::DATA_SIZE_SMALL) { |
||
182 | continue; |
||
183 | } |
||
184 | |||
185 | $sbCount = $this->getBlocksCount($size, $this->smallBlockSize); |
||
186 | // Add to SBD |
||
187 | for ($j = 0; $j < $sbCount - 1; $j++) { |
||
188 | $this->writeUlong($j + $iSmBlk + 1); |
||
189 | } |
||
190 | $this->writeUlong(-2); |
||
191 | |||
192 | $result .= $item->getData(); |
||
193 | |||
194 | $exp = $size % $this->smallBlockSize; |
||
195 | if ($exp) { |
||
196 | $zeroByteCount = $this->smallBlockSize - $exp; |
||
197 | $result .= str_repeat("\x00", $zeroByteCount); |
||
198 | } |
||
199 | |||
200 | $item->setStartBlock($iSmBlk); |
||
201 | $iSmBlk += $sbCount; |
||
202 | } |
||
203 | |||
204 | $sbCount = $this->getPointersPerBlock($this->bigBlockSize); |
||
205 | if ($iSmBlk % $sbCount) { |
||
206 | $repeatCount = $sbCount - ($iSmBlk % $sbCount); |
||
207 | $this->writeUlong(-1, $repeatCount); |
||
208 | } |
||
209 | |||
210 | $this->data = $result; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * Saves all the PPS's WKs |
||
215 | * |
||
216 | * @param PPS[] $list Reference to an array with all PPS's |
||
217 | */ |
||
218 | protected function savePps(&$list) |
||
219 | { |
||
220 | // Save each PPS WK |
||
221 | $raListCount = count($list); |
||
222 | for ($i = 0; $i < $raListCount; $i++) { |
||
223 | $this->write($list[$i]->getPpsWk()); |
||
224 | } |
||
225 | |||
226 | // Adjust for Block |
||
227 | $iCnt = count($list); |
||
228 | $iBCnt = $this->getPointersPerBlock($this->bigBlockSize, self::PPS_SIZE); |
||
229 | if ($iCnt % $iBCnt) { |
||
230 | $zeroByteCount = ($iBCnt - ($iCnt % $iBCnt)) * self::PPS_SIZE; |
||
231 | $this->write(str_repeat("\x00", $zeroByteCount)); |
||
232 | } |
||
233 | } |
||
234 | |||
235 | /** |
||
236 | * @param $value |
||
237 | * @param int $count |
||
238 | */ |
||
239 | protected function writeUlong($value, $count = 1) |
||
240 | { |
||
241 | $packed = pack("V", $value); |
||
242 | $this->write(str_repeat($packed, $count)); |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * @param $data |
||
247 | */ |
||
248 | protected function write($data) |
||
249 | { |
||
250 | fwrite($this->rootFilePointer, $data); |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * Saving Big Block Depot |
||
255 | * |
||
256 | * @param integer $numSbBlocks - number of Smallblock depot blocks |
||
257 | * @param integer $numBbBlocks - number of Bigblock depot blocks |
||
258 | * @param integer $numPpsBlocks - number of PropertySetStorage blocks |
||
259 | */ |
||
260 | protected function saveBigBlockChain($numSbBlocks, $numBbBlocks, $numPpsBlocks) |
||
261 | { |
||
262 | $info = $this->calcBigBlockChain($numSbBlocks, $numBbBlocks, $numPpsBlocks); |
||
263 | $headerEntriesCount = $info["header_list_entries"]; |
||
264 | $entriesCount = $info["list_entries"]; |
||
265 | $entriesPerBlock = $info["entries_per_block"]; |
||
266 | |||
267 | if ($numSbBlocks > 0) { |
||
268 | for ($i = 0; $i < $numSbBlocks - 1; $i++) { |
||
269 | $this->writeUlong($i + 1); |
||
270 | } |
||
271 | $this->writeUlong(-2); |
||
272 | } |
||
273 | |||
274 | View Code Duplication | for ($i = 0; $i < $numBbBlocks - 1; $i++) { |
|
0 ignored issues
–
show
|
|||
275 | $this->writeUlong($i + $numSbBlocks + 1); |
||
276 | } |
||
277 | $this->writeUlong(-2); |
||
278 | |||
279 | View Code Duplication | for ($i = 0; $i < $numPpsBlocks - 1; $i++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
280 | $this->writeUlong($i + $numSbBlocks + $numBbBlocks + 1); |
||
281 | } |
||
282 | $this->writeUlong(-2); |
||
283 | |||
284 | $this->writeUlong(0xFFFFFFFD, $info["FD_entries"]); |
||
285 | $this->writeUlong(0xFFFFFFFC, $info["FC_entries"]); |
||
286 | |||
287 | // Adjust for Block |
||
288 | $allEntries = $numSbBlocks |
||
289 | + $numBbBlocks |
||
290 | + $numPpsBlocks |
||
291 | + $info["FD_entries"] |
||
292 | + $info["FC_entries"]; |
||
293 | if ($allEntries % $entriesPerBlock) { |
||
294 | $rest = $entriesPerBlock - ($allEntries % $entriesPerBlock); |
||
295 | $this->writeUlong(-1, $rest); |
||
296 | } |
||
297 | |||
298 | // Extra BDList |
||
299 | if ($entriesCount > $headerEntriesCount) { |
||
300 | $iN = 0; |
||
301 | $iNb = 0; |
||
302 | $lastEntryIdx = $entriesPerBlock - 1; |
||
303 | |||
304 | for ($i = $headerEntriesCount; $i < $entriesCount; $i++, $iN++) { |
||
305 | if ($iN >= $lastEntryIdx) { |
||
306 | $iN = 0; |
||
307 | $iNb++; |
||
308 | |||
309 | $val = $numSbBlocks |
||
310 | + $numBbBlocks |
||
311 | + $numPpsBlocks |
||
312 | + $info["FD_entries"] |
||
313 | + $iNb; |
||
314 | $this->writeUlong($val); |
||
315 | } |
||
316 | |||
317 | $this->writeUlong($numBbBlocks + $numSbBlocks + $numPpsBlocks + $i); |
||
318 | } |
||
319 | |||
320 | $allEntries = $entriesCount - $headerEntriesCount; |
||
321 | if ($allEntries % $lastEntryIdx) { |
||
322 | $rest = $lastEntryIdx - ($allEntries % $lastEntryIdx); |
||
323 | $this->writeUlong(-1, $rest); |
||
324 | } |
||
325 | |||
326 | $this->writeUlong(-2); |
||
327 | } |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * Save OLE header |
||
332 | * |
||
333 | * @param integer $numSbBlocks - number of Smallblock depot blocks |
||
334 | * @param integer $numBbBlocks - number of Bigblock depot blocks |
||
335 | * @param integer $numPpsBlocks - number of PropertySetStorage blocks |
||
336 | */ |
||
337 | public function saveHeader($numSbBlocks, $numBbBlocks, $numPpsBlocks) |
||
338 | { |
||
339 | $info = $this->calcBigBlockChain($numSbBlocks, $numBbBlocks, $numPpsBlocks); |
||
340 | $headerEntriesCount = $info["header_list_entries"]; |
||
341 | $entriesCount = $info["list_entries"]; |
||
342 | |||
343 | $this->write( |
||
344 | "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" |
||
345 | . pack("V4", 0, 0, 0, 0) |
||
346 | . pack("v6", 0x3b, 0x03, -2, 9, 6, 0) |
||
347 | . pack("V2", 0, 0) |
||
348 | . pack("V", $entriesCount) |
||
349 | . pack("V", $numSbBlocks + $numBbBlocks) //ROOT START |
||
350 | . pack("V2", 0, 0x1000) |
||
351 | ); |
||
352 | |||
353 | //Small Block Depot |
||
354 | $value = ($numSbBlocks > 0) ? 0 : -2; |
||
355 | $this->writeUlong($value); |
||
356 | $this->writeUlong($numSbBlocks); |
||
357 | |||
358 | // Extra BDList Start, Count |
||
359 | if ($entriesCount < $headerEntriesCount) { |
||
360 | $this->writeUlong(-2); // Extra BDList Start |
||
361 | $this->writeUlong(0); // Extra BDList Count |
||
362 | } else { |
||
363 | $this->writeUlong($numSbBlocks + $numBbBlocks + $numPpsBlocks + $info["FD_entries"]); |
||
364 | $this->writeUlong($info["FC_entries"]); |
||
365 | } |
||
366 | |||
367 | // BDList |
||
368 | for ($i = 0; $i < $headerEntriesCount && $i < $entriesCount; $i++) { |
||
369 | $this->writeUlong($numBbBlocks + $numSbBlocks + $numPpsBlocks + $i); |
||
370 | } |
||
371 | |||
372 | if ($i < $headerEntriesCount) { |
||
373 | $repeatCount = $headerEntriesCount - $i; |
||
374 | $this->writeUlong(-1, $repeatCount); |
||
375 | } |
||
376 | } |
||
377 | |||
378 | /** |
||
379 | * New method to calculate Bigblock chain |
||
380 | * |
||
381 | * @param integer $numSb - number of Smallblock depot blocks |
||
382 | * @param integer $numBb - number of Bigblock depot blocks |
||
383 | * @param integer $numPps - number of PropertySetStorage blocks |
||
384 | * @return array |
||
385 | */ |
||
386 | protected function calcBigBlockChain($numSb, $numBb, $numPps) |
||
387 | { |
||
388 | $totalBlocks = $numSb + $numBb + $numPps; |
||
389 | $info = array( |
||
390 | "entries_per_block" => $this->getPointersPerBlock($this->bigBlockSize), |
||
391 | "header_list_entries" => $this->getPointersPerBlock($this->bigBlockSize - 0x4C), |
||
392 | "entries" => $totalBlocks, |
||
393 | "ext_list_entries" => 0, |
||
394 | "FC_entries" => 0, |
||
395 | "FD_entries" => $this->getNumberOfPointerBlocks($totalBlocks) |
||
396 | ); |
||
397 | |||
398 | $info["list_entries"] = $this->getNumberOfPointerBlocks( |
||
399 | $totalBlocks + $info["FD_entries"] |
||
400 | ); |
||
401 | |||
402 | if ($info["list_entries"] <= $info["header_list_entries"]) { |
||
403 | return $info; |
||
404 | } |
||
405 | |||
406 | return $this->calcBigBlockChainExtra($info); |
||
407 | } |
||
408 | |||
409 | /** |
||
410 | * @param array $info |
||
411 | * |
||
412 | * @return array |
||
413 | */ |
||
414 | protected function calcBigBlockChainExtra($info) |
||
415 | { |
||
416 | while (true) { |
||
417 | $pointerBlocksCount = $this->getNumberOfPointerBlocks( |
||
418 | $info["entries"] + $info["FD_entries"] + $info["FC_entries"] |
||
419 | ); |
||
420 | |||
421 | if ($info["list_entries"] >= $pointerBlocksCount) { |
||
422 | break; |
||
423 | } |
||
424 | |||
425 | $info["list_entries"] = $pointerBlocksCount; |
||
426 | $info["ext_list_entries"] = $info["list_entries"] - $info["header_list_entries"]; |
||
427 | $info["FC_entries"] = $this->getNumberOfPointerBlocks( |
||
428 | $info["ext_list_entries"] |
||
429 | ); |
||
430 | $info["FD_entries"] = $this->getNumberOfPointerBlocks( |
||
431 | $info["entries"] + $info["FD_entries"] + $info["FC_entries"] |
||
432 | ); |
||
433 | } |
||
434 | |||
435 | return $info; |
||
436 | } |
||
437 | |||
438 | /** |
||
439 | * Calculates number of pointer blocks |
||
440 | * |
||
441 | * @param integer $numPointers - number of pointers |
||
442 | * |
||
443 | * @return int |
||
444 | */ |
||
445 | protected function getNumberOfPointerBlocks($numPointers) |
||
446 | { |
||
447 | return $this->getBlocksCount($numPointers, $this->getPointersPerBlock($this->bigBlockSize)); |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * @param int $blockSize |
||
452 | * @param int $pointerSize |
||
453 | * |
||
454 | * @return int |
||
455 | */ |
||
456 | protected function getPointersPerBlock($blockSize, $pointerSize = self::LONG_INT_SIZE) |
||
457 | { |
||
458 | return intval(floor($blockSize / $pointerSize)); |
||
459 | } |
||
460 | } |
||
461 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.