1- using System ;
2- using System . Collections . Generic ;
3- using System . Security . Cryptography ;
4- using System . Text ;
1+ using System . Security . Cryptography ;
52using TACTSharp ;
63
74namespace TACTTool . RunModes
@@ -15,79 +12,163 @@ public static void Run(BuildInstance buildInstance)
1512 Console . WriteLine ( "NOTE: This is currently a very basic implementation that only checks archive/loose file existence & sizes." ) ;
1613 Console . WriteLine ( "!!!" ) ;
1714
18- if ( buildInstance . Settings . CDNConfig is null )
19- {
20- Console . WriteLine ( "!!! Warning, no CDN config given so will check entire directory. This may take a long time and may fail on SMB mounted shares." ) ;
21- Console . WriteLine ( "Also, this is not yet implemented." ) ;
22- throw new NotImplementedException ( ) ;
23- }
24- else
15+ var badFiles = new List < string > ( ) ;
16+ var missingFiles = new List < string > ( ) ;
17+
18+ var buildConfigs = new List < string > ( ) ;
19+ var cdnConfigs = new List < string > ( ) ;
20+ var patchConfigs = new List < string > ( ) ;
21+ var keyRings = new List < string > ( ) ;
22+
23+ var checkedFiles = new HashSet < string > ( ) ;
24+
25+ Console . WriteLine ( "Scanning configs..." ) ;
26+ var configPath = Path . Combine ( buildInstance . Settings . CDNDir , "tpr" , "wow" , "config" ) ;
27+ foreach ( var file in Directory . GetFiles ( configPath , "*" , SearchOption . AllDirectories ) )
2528 {
26- var config = new TACTSharp . Config ( buildInstance . cdn , buildInstance . Settings . CDNConfig , false ) ;
29+ using ( var stream = File . OpenRead ( file ) )
30+ {
31+ using ( var reader = new StreamReader ( stream ) )
32+ {
33+ var firstLine = reader . ReadLine ( ) ;
34+ if ( firstLine == "# Build Configuration" )
35+ buildConfigs . Add ( file ) ;
36+ else if ( firstLine == "# CDN Configuration" )
37+ cdnConfigs . Add ( file ) ;
38+ else if ( firstLine == "# Patch Configuration" )
39+ patchConfigs . Add ( file ) ;
40+ else if ( firstLine ! . StartsWith ( "key" ) )
41+ keyRings . Add ( file ) ;
42+ else
43+ Console . WriteLine ( $ "!!! Warning, unknown config file { file } with first line of : " + firstLine ) ;
44+ }
45+ }
2746
28- var archiveCount = config . Values [ "archives" ] . Length ;
29- for ( var i = 0 ; i < archiveCount ; i ++ )
47+ var md5 = Convert . ToHexStringLower ( MD5 . HashData ( File . ReadAllBytes ( file ) ) ) ;
48+ if ( md5 != Path . GetFileNameWithoutExtension ( file ) )
3049 {
31- var archiveIndex = config . Values [ "archives" ] [ i ] ;
50+ Console . WriteLine ( $ "!!! Warning, config file { file } has incorrect MD5 hash! Expected { Path . GetFileNameWithoutExtension ( file ) } but got { md5 } .") ;
51+ badFiles . Add ( file ) ;
52+ }
3253
33- var indexPath = Path . Combine ( buildInstance . Settings . CDNDir , "tpr" , "wow" , "data" , archiveIndex [ 0 ..2 ] , archiveIndex [ 2 ..4 ] , archiveIndex + ".index" ) ;
34- if ( ! File . Exists ( indexPath ) )
35- throw new FileNotFoundException ( indexPath ) ;
54+ checkedFiles . Add ( file ) ;
55+ }
3656
37- var index = new IndexInstance ( indexPath ) ;
57+ Console . WriteLine ( "Found " + buildConfigs . Count + " build configs, " + cdnConfigs . Count + " CDN configs and " + patchConfigs . Count + " patch configs." ) ;
3858
39- var allFiles = index . GetAllEntries ( ) ;
40- var highestOffset = allFiles . Select ( x => x . offset + x . size ) . Max ( ) ;
59+ for ( var c = 0 ; c < cdnConfigs . Count ; c ++ )
60+ {
61+ {
62+ var cdnConfig = cdnConfigs [ c ] ;
63+ var config = new TACTSharp . Config ( buildInstance . cdn , cdnConfig , true ) ;
64+ var configName = Path . GetFileNameWithoutExtension ( cdnConfig ) ;
4165
42- var archiveFileInfo = new FileInfo ( indexPath . Replace ( ".index" , "" ) ) ;
43- if ( ! archiveFileInfo . Exists )
44- throw new FileNotFoundException ( archiveFileInfo . FullName ) ;
45- var archiveLength = archiveFileInfo . Length ;
66+ Console . Write ( "Checking cdnconfigs.. " + ( c + 1 ) + "/" + cdnConfigs . Count + "\r " ) ;
4667
47- if ( highestOffset != archiveLength )
68+ var archiveCount = config . Values [ "archives" ] . Length ;
69+ for ( var i = 0 ; i < archiveCount ; i ++ )
4870 {
49- Console . WriteLine ( $ "!!! Archive { archiveIndex } has wrong size! Expected { highestOffset } bytes but only found { archiveLength } bytes.") ;
50- }
71+ var archiveIndex = config . Values [ "archives" ] [ i ] ;
72+ if ( checkedFiles . Contains ( archiveIndex ) )
73+ continue ;
5174
52- Console . Write ( "Checking archives.. " + ( i + 1 ) + "/" + archiveCount + "\r " ) ;
53- }
75+ var indexPath = Path . Combine ( buildInstance . Settings . CDNDir , "tpr" , "wow" , "data" , archiveIndex [ 0 ..2 ] , archiveIndex [ 2 ..4 ] , archiveIndex + ".index" ) ;
76+ if ( ! File . Exists ( indexPath ) )
77+ {
78+ Console . WriteLine ( $ "!!! [{ configName } ] Archive index { archiveIndex } is missing!\n ") ;
79+ missingFiles . Add ( indexPath ) ;
80+ checkedFiles . Add ( indexPath ) ;
81+ continue ;
82+ }
5483
55- Console . WriteLine ( ) ;
84+ var index = new IndexInstance ( indexPath ) ;
5685
57- if ( config . Values . TryGetValue ( "file-index" , out string [ ] ? fileIndexName ) )
58- {
59- var fileIndexPath = Path . Combine ( buildInstance . Settings . CDNDir , "tpr" , "wow" , "data" , fileIndexName [ 0 ] [ 0 ..2 ] , fileIndexName [ 0 ] [ 2 ..4 ] , fileIndexName [ 0 ] + ".index" ) ;
60- var fileIndex = new IndexInstance ( fileIndexPath ) ;
61- var allFiles = fileIndex . GetAllEntries ( ) ;
62- var looseFileCount = allFiles . Count ;
63- for ( var i = 0 ; i < looseFileCount ; i ++ )
86+ // TODO: Check index integrity
87+
88+ var allFiles = index . GetAllEntries ( ) ;
89+ var highestOffset = allFiles . Select ( x => x . offset + x . size ) . Max ( ) ;
90+
91+ var archiveFileInfo = new FileInfo ( indexPath . Replace ( ".index" , "" ) ) ;
92+ if ( archiveFileInfo . Exists )
93+ {
94+ var archiveLength = archiveFileInfo . Length ;
95+
96+ if ( highestOffset != archiveLength )
97+ {
98+ Console . WriteLine ( $ "!!! [{ configName } ] Archive { archiveIndex } has wrong size! Expected { highestOffset } bytes but only found { archiveLength } bytes.\n ") ;
99+ badFiles . Add ( archiveFileInfo . FullName ) ;
100+ }
101+ }
102+ else
103+ {
104+ Console . WriteLine ( $ "!!! [{ configName } ] Archive file { archiveIndex } is missing!\n ") ;
105+ missingFiles . Add ( indexPath ) ;
106+ }
107+
108+ checkedFiles . Add ( archiveIndex ) ;
109+
110+ //Console.Write("Checking archives.. " + (i + 1) + "/" + archiveCount + "\r");
111+ }
112+
113+ if ( config . Values . TryGetValue ( "file-index" , out string [ ] ? fileIndexName ) )
64114 {
65- Console . Write ( "Checking loose files.. " + ( i + 1 ) + "/" + looseFileCount + "\r " ) ;
66- var looseFile = allFiles [ i ] ;
67- var looseFileName = Convert . ToHexStringLower ( looseFile . eKey ) ;
68- var looseFilePath = Path . Combine ( buildInstance . Settings . CDNDir , "tpr" , "wow" , "data" , looseFileName [ 0 ..2 ] , looseFileName [ 2 ..4 ] , looseFileName ) ;
69- var looseFileInfo = new FileInfo ( looseFilePath ) ;
70- if ( ! looseFileInfo . Exists )
71- throw new FileNotFoundException ( looseFilePath ) ;
72-
73- var looseFileSize = looseFileInfo . Length ;
74- var looseFileSupposedSize = looseFile . size ;
75-
76- //var looseFileMD5 = Convert.ToHexStringLower(MD5.HashData(File.ReadAllBytes(looseFilePath)));
77- //if(looseFileMD5 != looseFileName)
78- //{
79- // Console.WriteLine($"!!! MD5 for file {looseFileName} is incorrect ({looseFileName} != {looseFileMD5}!");
80- //}
81-
82- if ( looseFileSize != looseFileSupposedSize )
115+ var fileIndexPath = Path . Combine ( buildInstance . Settings . CDNDir , "tpr" , "wow" , "data" , fileIndexName [ 0 ] [ 0 ..2 ] , fileIndexName [ 0 ] [ 2 ..4 ] , fileIndexName [ 0 ] + ".index" ) ;
116+ var fileIndex = new IndexInstance ( fileIndexPath ) ;
117+ var allFiles = fileIndex . GetAllEntries ( ) ;
118+ var looseFileCount = allFiles . Count ;
119+ for ( var i = 0 ; i < looseFileCount ; i ++ )
83120 {
84- Console . WriteLine ( $ "!!! Loose file { looseFileName } has wrong size! Expected { looseFileSupposedSize } bytes but only found { looseFileSize } bytes.") ;
121+ //Console.Write("Checking loose files.. " + (i + 1) + "/" + looseFileCount + "\r");
122+
123+ var looseFile = allFiles [ i ] ;
124+ var looseFileName = Convert . ToHexStringLower ( looseFile . eKey ) ;
125+
126+ if ( checkedFiles . Contains ( looseFileName ) )
127+ continue ;
128+
129+ var looseFilePath = Path . Combine ( buildInstance . Settings . CDNDir , "tpr" , "wow" , "data" , looseFileName [ 0 ..2 ] , looseFileName [ 2 ..4 ] , looseFileName ) ;
130+ var looseFileInfo = new FileInfo ( looseFilePath ) ;
131+ if ( looseFileInfo . Exists )
132+ {
133+ var looseFileSize = looseFileInfo . Length ;
134+ var looseFileSupposedSize = looseFile . size ;
135+
136+ // bad assumption here
137+ //var looseFileMD5 = Convert.ToHexStringLower(MD5.HashData(File.ReadAllBytes(looseFilePath)));
138+ //if (looseFileMD5 != looseFileName)
139+ //{
140+ // Console.WriteLine($"!!! MD5 for file {looseFileName} is incorrect ({looseFileName} != {looseFileMD5}!");
141+ // badFiles.Add(looseFilePath);
142+ //}
143+
144+ if ( looseFileSize != looseFileSupposedSize )
145+ {
146+ Console . WriteLine ( $ "!!! [{ configName } ] Loose file { looseFileName } has wrong size! Expected { looseFileSupposedSize } bytes but only found { looseFileSize } bytes.\n ") ;
147+ badFiles . Add ( looseFileName ) ;
148+ }
149+ }
150+ else
151+ {
152+ Console . WriteLine ( $ "!!! [{ configName } ] Loose file { looseFileName } is missing!\n ") ;
153+ missingFiles . Add ( looseFileName ) ;
154+ }
155+
156+ checkedFiles . Add ( looseFileName ) ;
85157 }
86158 }
87- }
159+ else
160+ {
161+ // TODO: No file index, list loose files from connected builds => encodings?
162+ //Console.WriteLine($"!!! [{configName}] No file index specified, skipping loose file checks.\n");
163+ }
88164
89- Console . WriteLine ( ) ;
165+ // TODO: Other cdnconfig listed things such as patch archives
166+ }
90167 }
168+
169+ Console . WriteLine ( "Verification complete! " + ( badFiles . Count + missingFiles . Count ) + " total issues found (" + badFiles . Count + " bad files, " + missingFiles . Count + " missing files)." ) ;
170+ File . WriteAllLines ( "badFiles.txt" , badFiles ) ;
171+ File . WriteAllLines ( "missingFiles.txt" , missingFiles ) ;
91172 }
92173 }
93174}
0 commit comments