/// <summary> /// Reads a DARC archive. /// </summary> /// <param name="data">Stream of the data</param> /// <returns>The container data</returns> public static OContainer load(Stream data) { OContainer output = new OContainer(); BinaryReader input = new BinaryReader(data); string darcMagic = IOUtils.readStringWithLength(input, 4); ushort endian = input.ReadUInt16(); ushort headerLength = input.ReadUInt16(); uint version = input.ReadUInt32(); uint fileSize = input.ReadUInt32(); uint tableOffset = input.ReadUInt32(); uint tableLength = input.ReadUInt32(); uint dataOffset = input.ReadUInt32(); data.Seek(tableOffset, SeekOrigin.Begin); fileEntry root = getEntry(input); int baseOffset = (int)data.Position; int namesOffset = (int)(tableOffset + root.length * 0xc); string currDir = null; for (int i = 0; i < root.length - 1; i++) { data.Seek(baseOffset + i * 0xc, SeekOrigin.Begin); fileEntry entry = getEntry(input); if ((entry.flags & 1) > 0) { //Folder int index = i; currDir = null; for (;;) { uint parentIndex = entry.offset; currDir = getName(input, entry.nameOffset + namesOffset) + "/" + currDir; if (parentIndex == 0 || parentIndex == index) { break; } data.Seek(baseOffset + parentIndex * 0xc, SeekOrigin.Begin); entry = getEntry(input); index = (int)parentIndex; } continue; } data.Seek(entry.offset, SeekOrigin.Begin); byte[] buffer = new byte[entry.length]; data.Read(buffer, 0, buffer.Length); OContainer.FileEntry file = new OContainer.FileEntry(output, currDir + getName(input, entry.nameOffset + namesOffset), false, buffer); output.Add(file); } data.Close(); return(output); }
public void doVerify() { // try to open the file TextReader tr; try { tr = new StreamReader(file, enc); } catch (Exception ex) { onVerifyDone(ex); return; } // read the file string line; ArrayList files = new ArrayList(); while ((line = tr.ReadLine()) != null) { if (line.Length >= 35) { fileEntry entry; entry.checksum = line.Substring(0, 32); entry.file = line.Substring(34); files.Add(entry); } } // close it tr.Close(); // try to access directory try { Environment.CurrentDirectory = new FileInfo(file).Directory.FullName; } catch (Exception ex) { onVerifyDone(ex); return; } // display progress int ver = 0; int success = 0; int corrupt = 0; int missing = 0; onVerifyProgress("", MD5VerifyStatus.None, ver, success, corrupt, missing, files.Count); // check for empty (maybe invalid) files if (files.Count < 1) { onVerifyDone(null); return; } MD5CryptoServiceProvider csp = new MD5CryptoServiceProvider(); for (int idx = 0; (idx < files.Count); ++idx) { // get file fileEntry entry = (fileEntry)files[idx]; // display file name onVerifyProgress(entry.file, MD5VerifyStatus.Verifying, ver, success, corrupt, missing, files.Count); if (File.Exists(entry.file)) { try { // compute hash FileStream stmcheck = File.OpenRead(entry.file); byte[] hash = csp.ComputeHash(stmcheck); stmcheck.Close(); // convert to string string computed = BitConverter.ToString(hash).Replace("-", "").ToLower(); // compare if (computed == entry.checksum) { ++ver; ++success; onVerifyProgress(entry.file, MD5VerifyStatus.OK, ver, success, corrupt, missing, files.Count); } else { ++corrupt; ++success; onVerifyProgress(entry.file, MD5VerifyStatus.Bad, ver, success, corrupt, missing, files.Count); } } catch { // error ++ver; ++corrupt; onVerifyProgress(entry.file, MD5VerifyStatus.Error, ver, success, corrupt, missing, files.Count); } } else { // file does not exist ++ver; ++missing; onVerifyProgress(entry.file, MD5VerifyStatus.FileNotFound, ver, success, corrupt, missing, files.Count); } } onVerifyDone(null); } // public void doVerify()