1 | <?php |
||||
2 | /** |
||||
3 | * Class AIDXReader |
||||
4 | * |
||||
5 | * @link https://github.com/Narthorn/Halon/blob/master/halon.py |
||||
6 | * |
||||
7 | * @filesource AIDXReader.php |
||||
8 | * @created 06.01.2019 |
||||
9 | * @package codemasher\WildstarDB\Archive |
||||
10 | * @author smiley <[email protected]> |
||||
11 | * @copyright 2019 smiley |
||||
12 | * @license MIT |
||||
13 | */ |
||||
14 | |||||
15 | namespace codemasher\WildstarDB\Archive; |
||||
16 | |||||
17 | use codemasher\WildstarDB\WSDBException; |
||||
18 | |||||
19 | use function array_fill, array_merge, fread, fseek, ftell, strpos, substr, unpack; |
||||
20 | |||||
21 | /** |
||||
22 | * @property array $dirs |
||||
23 | */ |
||||
24 | final class AIDXReader extends PACKReaderAbstract{ |
||||
25 | |||||
26 | private const AIDX_ROOT = 'a4ArchiveType/LVersion/LBuildnumber/LIndex'; |
||||
27 | private const AIDX_DATA = 'LNameOffset/LFlags/QFiletime/QSizeUncompressed/QSizeCompressed/a20Hash/x4'; |
||||
28 | |||||
29 | /** @var array */ |
||||
30 | protected $dirs; |
||||
31 | |||||
32 | /** |
||||
33 | * @inheritDoc |
||||
34 | */ |
||||
35 | protected function readData():void{ |
||||
36 | |||||
37 | // get the root info block of the AIDX file (4+4+4+4 = 16 bytes) |
||||
38 | $rootInfo = unpack($this::AIDX_ROOT, fread($this->fh, 16)); |
||||
39 | |||||
40 | if($rootInfo['ArchiveType'] !== "\x58\x44\x49\x41"){ // XDIA |
||||
41 | throw new WSDBException('invalid AIDX'); |
||||
42 | } |
||||
43 | |||||
44 | $this->dirs = []; |
||||
45 | $this->data = $this->getBlock($this->blocktable[$rootInfo['Index']]); |
||||
46 | } |
||||
47 | |||||
48 | /** |
||||
49 | * @param array $blockInfo |
||||
50 | * @param string $parent |
||||
51 | * |
||||
52 | * @return array |
||||
53 | */ |
||||
54 | private function getBlock(array $blockInfo, string $parent = ''):array{ |
||||
55 | |||||
56 | // add the current path to the collection |
||||
57 | $this->dirs[] = $parent; |
||||
58 | |||||
59 | // find the info block |
||||
60 | fseek($this->fh, $blockInfo['Offset']); |
||||
61 | |||||
62 | // get the count of directories and files in that block (4+4 = 8 bytes) |
||||
63 | $n = unpack('Ldirs/Lfiles', fread($this->fh, 8)); |
||||
64 | |||||
65 | $dirs = array_fill(0, $n['dirs'], null); |
||||
66 | $files = array_fill(0, $n['files'], null); |
||||
67 | |||||
68 | // create a directory object for each dir (4+4 = 8 bytes) |
||||
69 | foreach($dirs as $i => $_){ |
||||
70 | $dirs[$i] = new Directory(unpack('LNameOffset/LBlockIndex', fread($this->fh, 8)), $parent); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
71 | } |
||||
72 | |||||
73 | // create a file object for each file (4+4+8+8+8+20+4 = 56 bytes) |
||||
74 | foreach($files as $i => $_){ |
||||
75 | $files[$i] = new File(unpack($this::AIDX_DATA, fread($this->fh, 56)), $parent); |
||||
0 ignored issues
–
show
It seems like
unpack($this::AIDX_DATA, fread($this->fh, 56)) can also be of type false ; however, parameter $data of codemasher\WildstarDB\Archive\File::__construct() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
76 | } |
||||
77 | |||||
78 | // read the list of names from the remaining data |
||||
79 | $names = fread($this->fh, $blockInfo['Size'] - (ftell($this->fh) - $blockInfo['Offset'])); |
||||
80 | |||||
81 | $getname = function(ItemAbstract $e) use ($names){ |
||||
82 | return '/'.substr($names, $e->NameOffset, strpos($names, "\x00", $e->NameOffset) - $e->NameOffset); |
||||
83 | }; |
||||
84 | |||||
85 | // apply the names to each object in the block |
||||
86 | foreach($dirs as $i => $e){ |
||||
87 | $dirs[$i]->Name = $getname($e); |
||||
88 | } |
||||
89 | |||||
90 | foreach($files as $i => $e){ |
||||
91 | $files[$i]->Name = $getname($e); |
||||
92 | } |
||||
93 | |||||
94 | // loop through the directory stucture recursively and add the block data |
||||
95 | foreach($dirs as $i => $info){ |
||||
96 | if(isset($this->blocktable[$info->BlockIndex])){ |
||||
97 | $dirs[$i]->Content = $this->getBlock($this->blocktable[$info->BlockIndex], $parent.$info->Name); |
||||
98 | } |
||||
99 | } |
||||
100 | |||||
101 | return array_merge($dirs, $files); |
||||
102 | } |
||||
103 | |||||
104 | } |
||||
105 |