public BSPHeader(BinaryReader map) { map.BaseStream.Position=0; version = map.ReadInt32(); if(version!=30) Debug.LogError("Bsp is wrong type"); for (int i = 0; i < 16; i++) { directory[i]= new HeaderEntry(map.ReadInt32(),map.ReadInt32(),Lump_type[i]); } }
/// <summary> /// Encode the header field into the header block. /// </summary> /// <param name="output">Output.</param> /// <param name="name">Name.</param> /// <param name="value">Value.</param> /// <param name="sensitive">If set to <c>true</c> sensitive.</param> public void EncodeHeader(BinaryWriter output, byte[] name, byte[] value, bool sensitive) { // If the header value is sensitive then it must never be indexed if (sensitive) { int nameIndex = this.GetNameIndex(name); this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NEVER, nameIndex); return; } // If the peer will only use the static table if (this.capacity == 0) { int staticTableIndex = StaticTable.GetIndex(name, value); if (staticTableIndex == -1) { int nameIndex = StaticTable.GetIndex(name); this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NONE, nameIndex); } else { Encoder.EncodeInteger(output, 0x80, 7, staticTableIndex); } return; } int headerSize = HeaderField.SizeOf(name, value); // If the headerSize is greater than the max table size then it must be encoded literally if (headerSize > this.capacity) { int nameIndex = this.GetNameIndex(name); this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NONE, nameIndex); return; } HeaderEntry headerField = this.GetEntry(name, value); if (headerField != null) { int index = this.GetIndex(headerField.Index) + StaticTable.Length; // Section 6.1. Indexed Header Field Representation Encoder.EncodeInteger(output, 0x80, 7, index); } else { int staticTableIndex = StaticTable.GetIndex(name, value); if (staticTableIndex != -1) { // Section 6.1. Indexed Header Field Representation Encoder.EncodeInteger(output, 0x80, 7, staticTableIndex); } else { int nameIndex = this.GetNameIndex(name); if (useIndexing) { this.EnsureCapacity(headerSize); } var indexType = useIndexing ? HPackUtil.IndexType.INCREMENTAL : HPackUtil.IndexType.NONE; this.EncodeLiteral(output, name, value, indexType, nameIndex); if (useIndexing) { this.Add(name, value); } } } }
public POFile(IO.TextFile textFile, LanguageGetter languageGetter) { this._dirty = false; this._textFile = textFile; this._textFile.Saved += this.TextFile_Saved; List <IO.TextLine> group = null; List <Entry> entries = new List <Entry>(); Regex rxNoSpaces = new Regex(@"\s+", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.Singleline); bool firstGroup = true; this._header = null; foreach (IO.TextLine line in textFile.Lines) { if (rxNoSpaces.Replace(line.Value, "").Length > 0) { if (group == null) { group = new List <IO.TextLine>(); } group.Add(line); } else { if (group != null) { Entry entry = Entry.Parse(firstGroup, this, group); entries.Add(entry); if (entry is HeaderEntry) { this._header = (HeaderEntry)entry; } firstGroup = false; group = null; } } } if (group != null) { Entry entry = Entry.Parse(firstGroup, this, group); entries.Add(entry); if (entry is HeaderEntry) { this._header = (HeaderEntry)entry; } firstGroup = false; group = null; } this._entries = entries.ToArray(); this._header = (this._entries.Length > 0) ? (this._entries[0] as HeaderEntry) : null; this._language = null; if ((this._header != null) && (this.Header.LanguageCode.Length > 0)) { try { this._language = new CultureInfo(this.Header.LanguageCode); } catch { } } if (this._language == null) { if (languageGetter != null) { CultureInfo suggest = null; Match match = Regex.Match(Path.GetFileNameWithoutExtension(textFile.FileName), @"(^|\b)(?<code>[a-z]{2})($|[_-](?<code2>[a-z]{2})$)", RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.Singleline | RegexOptions.IgnoreCase); if (match.Success) { if (!string.IsNullOrEmpty(match.Groups["code2"].Value)) { try { suggest = new CultureInfo(string.Format("{0}-{1}", match.Groups["code"].Value.ToLowerInvariant(), match.Groups["code2"].Value.ToUpperInvariant())); } catch { } if (suggest == null) { try { suggest = new CultureInfo(match.Groups["code2"].Value.ToLowerInvariant()); } catch { } } } if (suggest == null) { try { suggest = new CultureInfo(match.Groups["code"].Value.ToLowerInvariant()); } catch { } } } this._language = languageGetter(suggest); if (this._language == null) { throw new OperationCanceledException(); } } } if (this._language == null) { throw new Exception("Unable to determine the language."); } this.TotalDataEntries = 0; foreach (Entry entry in this._entries) { if (entry.Kind == Entry.Kinds.Standard) { this.TotalDataEntries++; } } }
/// <summary> /// Creates new entry. /// </summary> /// <param name="hash">Hash.</param> /// <param name="name">Name.</param> /// <param name="value">Value.</param> /// <param name="index">Index.</param> /// <param name="next">Next.</param> public HeaderEntry(int hash, string name, string value, int index, HeaderEntry next) : base(name, value) { Index = index; Hash = hash; Next = next; }
/// <summary> /// Creates new entry. /// </summary> /// <param name="hash">Hash.</param> /// <param name="name">Name.</param> /// <param name="value">Value.</param> /// <param name="index">Index.</param> /// <param name="next">Next.</param> public HeaderEntry(int hash, byte[] name, byte[] value, int index, HeaderEntry next) : base(name, value) { this.index = index; this.hash = hash; this.next = next; }
/// <summary> /// Creates new entry. /// </summary> /// <param name="hash"></param> /// <param name="name"></param> /// <param name="value"></param> /// <param name="index"></param> /// <param name="next"></param> internal HeaderEntry(int hash, ICharSequence name, ICharSequence value, int index, HeaderEntry next) : base(name, value) { Index = index; Hash = hash; Next = next; }
public override IHeaders <ICharSequence, ICharSequence> Clear() { _firstNonPseudo = _head; return(base.Clear()); }
/// <summary> /// Inserts this entry before the specified existing entry in the list. /// </summary> /// <param name="existingEntry">Existing entry.</param> public void AddBefore(HeaderEntry existingEntry) { after = existingEntry; before = existingEntry.before; before.after = this; after.before = this; }
public AsyncDecompressArgs(HeaderEntry he, FileStream file) { Entry = he; File = file; }
/// <summary> /// Add the header field to the dynamic table. /// Entries are evicted from the dynamic table until the size of the table /// and the new header field is less than the table's capacity. /// If the size of the new entry is larger than the table's capacity, /// the dynamic table will be cleared. /// </summary> /// <param name="name">Name.</param> /// <param name="value">Value.</param> private void Add(byte[] name, byte[] value) { int headerSize = HeaderField.SizeOf(name, value); // Clear the table if the header field size is larger than the capacity. if (headerSize > this.capacity) { this.Clear(); return; } // Evict oldest entries until we have enough capacity. while(this.size + headerSize > this.capacity) { this.Remove(); } // Copy name and value that modifications of original do not affect the dynamic table. name.CopyTo(name, 0); value.CopyTo(value, 0); int h = Encoder.Hash(name); int i = Encoder.Index(h); HeaderEntry old = headerFields[i]; HeaderEntry e = new HeaderEntry(h, name, value, head.Before.Index - 1, old); headerFields[i] = e; e.AddBefore(head); this.size += headerSize; }
public static void Rebuild(string[] args) { if (!Directory.Exists(args[1])) { Console.Error.WriteLine("Directory '{0}' doesn't exist!", args[1]); } args[1] = Path.GetFullPath(args[1]); // demo vol byte[] rofsHeader = new byte[4] { (byte)'R', (byte)'o', (byte)'F', (byte)'S' }; byte[] headerString = null; if (args.Length > 3) { g_compressedFlag = 0x2; g_directoryFlag = 0x1; headerString = rofsHeader; g_demoVol = true; } else { g_compressedFlag = 0x02000000; g_directoryFlag = 0x01000000; headerString = BitConverter.GetBytes(~BitConverter.ToUInt32(rofsHeader, 0)); g_demoVol = false; } uint numFolders = 0, numFiles = 0, namesLength = 0; List <HeaderEntry> rootDir = null; #if DEBUG // building the entry list takes for freaking ever due to all the decompressing // so when debugging we do it once, then save the results to a file // then on the next run, we don't have to wait for the same info to be recollected string serializeName = Path.GetFileName(args[1]); EntryListInfo eli = DeserializeEntryList(serializeName); //Console.WriteLine("Press enter to continue"); //Console.ReadLine(); if (eli == null) { #endif //DateTime start = DateTime.Now; List <HeaderEntry> fileHeaders = BuildEntryList(args[1], ref numFolders, ref numFiles, out namesLength); // The dot<nul> for the root entry needs accounting for namesLength += g_demoVol ? 4u : 2u; rootDir = new List <HeaderEntry>(1); HeaderEntry rootEntry = new HeaderEntry(); rootDir.Add(rootEntry); rootEntry.children = fileHeaders; rootEntry.fullFileName = "."; // wait for all the decompression jobs to finish before continuing while (Interlocked.CompareExchange(ref g_jobsFinished, g_jobsStarted, g_jobsStarted) != g_jobsStarted) { Thread.Sleep(100); } //DateTime end = DateTime.Now; //TimeSpan dur = end - start; //Console.WriteLine("Building entry list took {0}ms/{1}s", dur.TotalMilliseconds, dur.TotalSeconds); #if DEBUG // still in the if(eli == null) case eli = new EntryListInfo(); eli.namesLength = namesLength; eli.numCompressed = (uint)g_numCompressed; eli.numFiles = numFiles; eli.numFolders = numFolders; eli.root = rootDir; SerializeEntryList(serializeName, eli); } // end of eli == null else { g_numCompressed = (int)eli.numCompressed; numFiles = eli.numFiles; numFolders = eli.numFolders; namesLength = eli.namesLength; rootDir = eli.root; } #endif byte[] volHead = BuildHeaderFromList(headerString, rootDir, numFolders, numFiles, namesLength); using (FileStream fs = new FileStream(args[2], FileMode.Create, FileAccess.Write)) { byte[] blank = new byte[8191]; fs.Write(volHead, 0, volHead.Length); Stack <List <HeaderEntry> > entryStack = new Stack <List <HeaderEntry> >(); List <HeaderEntry> curIterList = rootDir; while (true) { if (curIterList.Count == 0) { if (entryStack.Count == 0) { break; } curIterList = entryStack.Pop(); continue; } int last = curIterList.Count - 1; HeaderEntry entry = curIterList[last]; curIterList.RemoveAt(last); if (entry.children == null) { fs.Seek(entry.fileDataPosition, SeekOrigin.Begin); Console.WriteLine("Reading {0} to write to the vol at {1:x}", Path.GetFileName(entry.fullFileName), entry.fileDataPosition); byte[] data = File.ReadAllBytes(entry.fullFileName); fs.Write(data, 0, data.Length); fs.Write(blank, 0, 0x800 - (data.Length % 0x800)); } else { entryStack.Push(curIterList); Console.WriteLine("Moving to directory {0}", Path.GetFileName(entry.fullFileName)); curIterList = entry.children; } } } }
private static List <DirInfo> WriteNewDirectory( HeaderEntry directory, uint parentDirPos, ref uint nextDirInfoPos, // for the directory contents ref uint nextFileInfoPos, // for the file info ref uint nextFileDataPos, // for the file data uint startOfNamesOffset, BinaryWriter headerWriter, BinaryWriter names, List <DirInfo> directories ) { uint thisDirPos = GetCurrentStreamPosition(headerWriter); // write the name uint dirNameOffset = 0; AppendVolHeaderFileName(names, Path.GetFileName(directory.fullFileName), out dirNameOffset); // fix it up and write it dirNameOffset += startOfNamesOffset; headerWriter.Write(dirNameOffset | g_directoryFlag); List <HeaderEntry> contents = directory.children; // then how many entries headerWriter.Write(contents.Count + 1); // then the parent pos headerWriter.Write(parentDirPos); // then the entries bool doLoop = (directories == null); if (directories == null) { directories = new List <DirInfo>(); } for (int i = 0; i < contents.Count; ++i) { HeaderEntry he = contents[i]; if (he.children != null && he.children.Count > 0) { // the format of the vol is // root // DirA DirB DirC // DirAA DirAB DirBA DirBB DirCA DirCB // // All these go in file order so root->DirA->DirB->DirC->DirAA rather than root->DirA->DirAA->DirAB->DirB // so don't recurse here, or that's what we'd get // headerWriter.Write(nextDirInfoPos); directories.Add(new DirInfo(nextDirInfoPos, thisDirPos, he)); // update the position for the next dir nextDirInfoPos += (uint)((3 + he.children.Count) * 4); } else { // next file pos headerWriter.Write(nextFileInfoPos); uint curPos = GetCurrentStreamPosition(headerWriter); SetCurrentStreamPosition(headerWriter, nextFileInfoPos); uint nameOffset = 0; // write the name and fix up its position from name-stream relative // to vol header relative AppendVolHeaderFileName(names, Path.GetFileName(he.fullFileName), out nameOffset); nameOffset += startOfNamesOffset; // save these so we know where to dump the file data in the vol // without having to recalculate stuff he.fileDataPosition = nextFileDataPos; if (he.isCompressed) { headerWriter.Write(nameOffset | g_compressedFlag); headerWriter.Write(nextFileDataPos / 0x800); // this seems to be ignored (if it's incorrect and more than actually required) nothing happens // smaller than required not tested headerWriter.Write(he.decompSize); headerWriter.Write(he.fileSize); nextFileInfoPos += (4 * 4); } else { headerWriter.Write(nameOffset); headerWriter.Write(nextFileDataPos / 0x800); headerWriter.Write(he.fileSize); nextFileInfoPos += (3 * 4); // demo always has four entries per file info, compressed or not if (g_demoVol) { headerWriter.Write(he.fileSize); nextFileInfoPos += 4; } } // reset file pointer for next entry SetCurrentStreamPosition(headerWriter, curPos); // round the file data position to the start of the next sector nextFileDataPos = ((nextFileDataPos + he.fileSize + 0x7ffu) & ~0x7ffu); } } if (!doLoop) { return(directories); } while (directories.Count > 0) { DirInfo dir = directories[0]; SetCurrentStreamPosition(headerWriter, dir.offset); List <DirInfo> childDirs = new List <DirInfo>(); WriteNewDirectory( dir.entry, dir.parentOffset, ref nextDirInfoPos, ref nextFileInfoPos, ref nextFileDataPos, startOfNamesOffset, headerWriter, names, childDirs ); directories.RemoveAt(0); directories.AddRange(childDirs); } return(null); }
public DirInfo(uint inOffset, uint inParentOffset, HeaderEntry inEntry) { offset = inOffset; parentOffset = inParentOffset; entry = inEntry; }
/// <summary> /// Removes this entry from the linked list. /// </summary> public void Remove() { this.before.after = this.after; this.after.before = this.before; }
/// <summary> /// 加载数据 /// </summary> /// <param name="reader">树型包读取器实例</param> /// <param name="password">密码,为空将会是默认密码。</param> /// <returns>返回加载后的树型包实例。</returns> public static unsafe TreePackage Load(System.IO.Stream reader, byte[] password = null) { //if (reader == null) // throw new ArgumentNullException("reader", "树型包读取器不能为 null 。"); if (reader == null) { return(null); } if (!reader.CanRead) { throw new ArgumentNullException("reader", "树型包读取器不能进行读取操作。"); } //if (reader.Closed) // throw new ObjectDisposedException("reader", "树型包读取器已经关闭。"); #region header 1 byte[] buffer = new byte[8]; if (reader.Read(buffer, 0, 4) != 4) //位数不够 { return(null); } //错误的标识 if (buffer[0] != HeaderEntry.StartFlag[0] || buffer[1] != HeaderEntry.StartFlag[1] || buffer[2] != HeaderEntry.StartFlag[2] || buffer[3] != HeaderEntry.StartFlag[3]) { return(null); } HeaderEntry packageEntry = new HeaderEntry(); packageEntry.Started = true; //Version,EncryptType if (reader.Read(buffer, 0, 2) != 2) { return(null); } if (buffer[0] > 9) { packageEntry.Version = (byte)(buffer[0] / 10); buffer[0] -= (byte)(packageEntry.Version * 10); } packageEntry.EncryptType = (PackageEncryptTypes)buffer[0]; //KeyIgnoreCase,HasAttributes,HasComment if (buffer[1] >= 100) { packageEntry.KeyIgnoreCase = true; buffer[1] -= 100; } if (buffer[1] >= 10) { packageEntry.HasAttributes = true; buffer[1] -= 10; } if (buffer[1] == 1) { packageEntry.HasComment = true; } #endregion if (password == null || password.Length == 0 || password == _defaultBinaryWavePassword) { password = _defaultBinaryWavePassword; if (packageEntry.EncryptType != PackageEncryptTypes.BinaryWave_EmptyPassword) { packageEntry.EncryptType = PackageEncryptTypes.BinaryWave_DefaultPassword; } } else { if (packageEntry.EncryptType != PackageEncryptTypes.BinaryWave_EmptyPassword) { packageEntry.EncryptType = PackageEncryptTypes.BinaryWave_CustomPassword; } } TreePackage result = null; using (Symbol.Encryption.BinaryEncryptionStream binaryEncryptionStream = new Symbol.Encryption.BinaryEncryptionStream(reader, password, packageEntry.EncryptType == PackageEncryptTypes.BinaryWave_EmptyPassword)) { int int32Var; #region header 2 //AttributesLength if (packageEntry.HasAttributes) { if (binaryEncryptionStream.Read(buffer, 0, 4) != 4) { return(null); } Marshal.Copy(buffer, 0, (IntPtr)(&int32Var), 4); packageEntry.AttributesLength = int32Var; } //CommentLength if (packageEntry.HasComment) { if (binaryEncryptionStream.Read(buffer, 0, 4) != 4) { return(null); } Marshal.Copy(buffer, 0, (IntPtr)(&int32Var), 4); packageEntry.CommentLength = int32Var; } //KeysCount if (binaryEncryptionStream.Read(buffer, 0, 4) != 4) { return(null); } Marshal.Copy(buffer, 0, (IntPtr)(&int32Var), 4); packageEntry.KeysCount = int32Var; //AttributesData if (packageEntry.HasAttributes) { packageEntry.AttributesData = new byte[packageEntry.AttributesLength]; if (binaryEncryptionStream.Read(packageEntry.AttributesData, 0, packageEntry.AttributesLength) != packageEntry.AttributesLength) { return(null); } } //CommentData if (packageEntry.HasComment) { packageEntry.CommentData = new byte[packageEntry.CommentLength]; if (binaryEncryptionStream.Read(packageEntry.CommentData, 0, packageEntry.CommentLength) != packageEntry.CommentLength) { return(null); } } #endregion result = new TreePackage(packageEntry); #region Keys //Keys ushort uShortVar = 0; ulong uInt64Var = 0; KeyEntry keyEntry; byte[] bufferValueData = null; Entry entry = null; for (int keyIndex = 0; keyIndex < packageEntry.KeysCount; keyIndex++) { #region Header if (binaryEncryptionStream.Read(buffer, 0, 5) != 5) { return(null); } //KeyLength Marshal.Copy(buffer, 0, (IntPtr)(&uShortVar), 2); keyEntry = new KeyEntry(); keyEntry.KeyLength = uShortVar; if (keyEntry.KeyLength == 0) { return(null); } //ValueType keyEntry.ValueType = (PackageValueTypes)buffer[2]; //Nullable|ArrayType if (buffer[3] >= 100) { keyEntry.Nullable = true; buffer[3] -= 100; } keyEntry.ArrayType = (PackageArrayTypes)buffer[3]; //HasAttributes,CompressType if (buffer[4] >= 100) { keyEntry.HasAttributes = true; buffer[4] -= 100; } keyEntry.CompressType = (PackageCompressTypes)buffer[4]; if (keyEntry.HasAttributes) //AttributesLength { if (binaryEncryptionStream.Read(buffer, 0, 4) != 4) { return(null); } Marshal.Copy(buffer, 0, (IntPtr)(&int32Var), 4); keyEntry.AttributesLength = int32Var; } //ValueDataLength if (!keyEntry.Nullable) { if (binaryEncryptionStream.Read(buffer, 0, 4) != 4) { return(null); } Marshal.Copy(buffer, 0, (IntPtr)(&int32Var), 4); keyEntry.ValueDataLength = int32Var; //CRC32 if (binaryEncryptionStream.Read(buffer, 0, 8) != 8) { return(null); } Marshal.Copy(buffer, 0, (IntPtr)(&uInt64Var), 8); keyEntry.CRC32 = uInt64Var; } #endregion #region Data //KeyData keyEntry.KeyData = new byte[keyEntry.KeyLength]; if (binaryEncryptionStream.Read(keyEntry.KeyData, 0, keyEntry.KeyLength) != keyEntry.KeyLength) { return(null); } //AttributesData if (keyEntry.HasAttributes) { keyEntry.AttributesData = new byte[keyEntry.AttributesLength]; if (binaryEncryptionStream.Read(keyEntry.AttributesData, 0, keyEntry.AttributesLength) != keyEntry.AttributesLength) { return(null); } } entry = new Entry(keyEntry); ((IEntry)entry).SetIsAdd(false); //ValueData if (!keyEntry.Nullable) { bufferValueData = new byte[keyEntry.ValueDataLength]; if (keyEntry.CompressType == PackageCompressTypes.NonEncrypt_NonCompress) { if (binaryEncryptionStream.BaseRead(bufferValueData, 0, keyEntry.ValueDataLength) != keyEntry.ValueDataLength) { return(null); } } else { if (binaryEncryptionStream.Read(bufferValueData, 0, keyEntry.ValueDataLength) != keyEntry.ValueDataLength) { return(null); } } uInt64Var = Symbol.Encryption.CRC32EncryptionHelper.Encrypt(bufferValueData); if (uInt64Var != keyEntry.CRC32) { throw new System.IO.InvalidDataException(string.Format("“{0}”的CRC32数据验证失败。应为:{1:X8},实际:{2:X8}", entry.Key, keyEntry.CRC32, uInt64Var)); } UnPackageValueData(keyEntry, entry, bufferValueData, result); } else { entry.Value = null; } #endregion bufferValueData = null; result.Add(entry); } #endregion } return(result); }