Passed
Push — master ( bdfaf8...931c46 )
by smiley
01:33
created

AIDXReader::readData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 0
dl 0
loc 14
rs 10
c 0
b 0
f 0
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
10
 * @author       smiley <[email protected]>
11
 * @copyright    2019 smiley
12
 * @license      MIT
13
 */
14
15
namespace codemasher\WildstarDB;
16
17
/**
18
 * @property array $dirs
19
 */
20
class AIDXReader extends PACKReaderAbstract{
21
22
	/** @var array */
23
	protected $dirs;
24
25
	/**
26
	 * @throws \codemasher\WildstarDB\WSDBException
27
	 */
28
	protected function readData():void{
29
30
		// get the root info block of the AIDX file (4+4+4+4 = 16 bytes)
31
		$rootInfo = \unpack(
32
			'a4ArchiveType/LVersion/LBuildnumber/LIndex',
33
			\fread($this->fh, $this->blocktable[$this->header['RootInfoIndex']]['Size'])
34
		);
35
36
		if($rootInfo['ArchiveType'] !== "\x58\x44\x49\x41"){ // XDIA
37
			throw new WSDBException('invalid AIDX');
38
		}
39
40
		$this->dirs = [];
41
		$this->data = $this->getBlock($this->blocktable[$rootInfo['Index']]);
42
	}
43
44
	/**
45
	 * @param array  $blockInfo
46
	 * @param string $parent
47
	 *
48
	 * @return array
49
	 */
50
	protected function getBlock(array $blockInfo, string $parent = ''):array{
51
52
		// add the current path to the collection
53
		$this->dirs[] = $parent;
54
55
		// find the info block
56
		\fseek($this->fh, $blockInfo['Offset']);
57
58
		// get the count of directories and files in that block (4+4 = 8 bytes)
59
		$n = \unpack('Ldirs/Lfiles', \fread($this->fh, 8));
60
61
		$dirs  = \array_fill(0, $n['dirs'], null);
62
		$files = \array_fill(0, $n['files'], null);
63
64
		// create a directory object for each dir (4+4 = 8 bytes)
65
		foreach($dirs as $i => $_){
66
			$dirs[$i] = new ArchiveDirectory(\unpack('LNameOffset/LBlockIndex', \fread($this->fh, 8)), $parent);
0 ignored issues
show
Bug introduced by
It seems like unpack('LNameOffset/LBlo...', fread($this->fh, 8)) can also be of type false; however, parameter $data of codemasher\WildstarDB\Ar...irectory::__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 ignore-type  annotation

66
			$dirs[$i] = new ArchiveDirectory(/** @scrutinizer ignore-type */ \unpack('LNameOffset/LBlockIndex', \fread($this->fh, 8)), $parent);
Loading history...
67
		}
68
69
		// create a file object for each file (4+4+8+8+8+20+4 = 56 bytes)
70
		foreach($files as $i => $_){
71
			$files[$i] = new ArchiveFile(
72
				\unpack('LNameOffset/LFlags/QFiletime/QSizeUncompressed/QSizeCompressed/a20Hash/x4', \fread($this->fh, 56)),
0 ignored issues
show
Bug introduced by
It seems like unpack('LNameOffset/LFla..., fread($this->fh, 56)) can also be of type false; however, parameter $data of codemasher\WildstarDB\ArchiveFile::__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 ignore-type  annotation

72
				/** @scrutinizer ignore-type */ \unpack('LNameOffset/LFlags/QFiletime/QSizeUncompressed/QSizeCompressed/a20Hash/x4', \fread($this->fh, 56)),
Loading history...
73
				$parent
74
			);
75
		}
76
77
		// read the list of names from the remaining data
78
		$names = \fread($this->fh, $blockInfo['Size'] - (\ftell($this->fh) - $blockInfo['Offset']));
79
80
		// apply the names to each object in the block
81
		$setnames = function(array &$arr) use ($names):void{
82
			foreach($arr ?? [] as $i => $e){
83
				$arr[$i]->Name = \DIRECTORY_SEPARATOR.
84
					\substr($names, $e->NameOffset, \strpos($names, "\x00", $e->NameOffset) - $e->NameOffset);
85
			}
86
		};
87
88
		$setnames($dirs);
89
		$setnames($files);
90
91
		// loop through the directory stucture recursively and add the block data
92
		foreach($dirs as $i => $info){
93
			if(isset($this->blocktable[$info->BlockIndex])){
94
				$dirs[$i]->Content = $this->getBlock($this->blocktable[$info->BlockIndex], $parent.$info->Name);
95
			}
96
		}
97
98
		return \array_merge($dirs, $files);
99
	}
100
101
}
102