/// <summary> /// Downloads a specific file from the Steam servers to the specified Stream. /// </summary> /// <param name="file">The file to download, given from the manifest.</param> /// <param name="downloadStream">The stream to which file data should be written.</param> /// <param name="priority">The download priority.</param> /// <param name="cryptKey">The AES encryption key used for any encrypted files.</param> /// <returns>A byte array representing the file.</returns> public void DownloadFileToStream(Steam2Manifest.Node file, Stream downloadStream, DownloadPriority priority = DownloadPriority.Low, byte[] cryptKey = null) { if ((file.Attributes & Steam2Manifest.Node.Attribs.EncryptedFile) != 0 && cryptKey == null) { throw new Steam2Exception(string.Format("AES encryption key required for file: {0}", file.FullName)); } const uint MaxParts = 16; uint numFileparts = (uint)Math.Ceiling((float)file.SizeOrCount / (float)file.Parent.BlockSize); uint numChunks = (uint)Math.Ceiling((float)numFileparts / (float)MaxParts); for (uint x = 0; x < numChunks; ++x) { byte[] filePart = DownloadFileParts(file, x * MaxParts, MaxParts, priority, cryptKey); downloadStream.Write(filePart, 0, filePart.Length); } }
byte[] DownloadFileParts(Steam2Manifest.Node file, uint filePart, uint numParts, DownloadPriority priority = DownloadPriority.Low, byte[] cryptKey = null) { this.SendCommand( 7, // download file this.StorageID, this.MessageID, file.FileID, filePart, numParts, ( byte )priority ); uint storId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); byte hasFile = this.Socket.Reader.ReadByte(); uint numChunks = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint fileModeValue = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); FileMode fileMode = ( FileMode )fileModeValue; MemoryStream ms = new MemoryStream(); for (int x = 0; x < numChunks; ++x) { uint storId2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint chunkLen = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint storId3 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId3 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint chunkLen2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); if (chunkLen == 0) { continue; } byte[] chunk = null; int len = 0; if (fileMode == FileMode.Compressed) { chunk = this.Socket.Reader.ReadBytes(( int )chunkLen); len = DecompressFileChunk(ref chunk, ( int )file.Parent.BlockSize); } else if (fileMode == FileMode.Encrypted) { len = DecryptFileChunk(out chunk, ( int )chunkLen, cryptKey); } else if (fileMode == FileMode.EncryptedAndCompressed) { // Account for 2 integers before the encrypted data chunkLen -= 8; // Skip first integer (length of the encrypted data) this.Socket.Reader.ReadInt32(); // Length of decrypted and decompressed data int plainLen = this.Socket.Reader.ReadInt32(); DecryptFileChunk(out chunk, ( int )chunkLen, cryptKey); len = DecompressFileChunk(ref chunk, plainLen); } else if (fileMode == FileMode.None) { chunk = this.Socket.Reader.ReadBytes(( int )chunkLen); len = chunk.Length; } ms.Write(chunk, 0, len); } byte[] data = ms.ToArray(); this.MessageID++; return(data); }