/// <summary> /// Adds the account login information (for SID_AUTH_ACCOUNTLOGON) /// to the specified packet. /// </summary> /// <param name="loginPacket">The packet to which to add the login information.</param> /// <exception cref="InvalidOperationException">Thrown if the object has not /// yet been initialized.</exception> /// <remarks> /// <para>This method may be called first after creating the instance, or after the /// <see cref="CreateAccount(DataBuffer)">CreateAccount</see> method.</para> /// </remarks> /// <returns>The total number of bytes written to the buffer.</returns> public int LoginAccount(DataBuffer loginPacket) { byte[] temp = new byte[33 + userNameAscii.Length]; int len = LoginAccount(temp, 0, temp.Length); loginPacket.InsertByteArray(temp); return len; }
public override async Task ExecuteRequest() { using (AsyncConnectionBase connection = new AsyncConnectionBase(Gateway.ServerHost, Gateway.ServerPort, 0, 0)) { byte[] fileNameBytes = Encoding.UTF8.GetBytes(FileName); DataBuffer buf = new DataBuffer(); buf.InsertInt16(20); // Length buf.InsertInt16(0x0200); // Protocol version buf.InsertDwordString("IX86"); buf.InsertDwordString(Product.ProductCode); if (_ad) { buf.InsertInt32(_adId); buf.InsertDwordString(_adExt); } else { buf.InsertInt64(0); } bool connected = await connection.ConnectAsync(); if (!connected) throw new IOException("Battle.net refused the connection."); await connection.SendAsync(new byte[] { 2 }); byte[] outgoingData = buf.UnderlyingStream.ToArray(); await connection.SendAsync(outgoingData); byte[] incomingData = new byte[4]; incomingData = await connection.ReceiveAsync(incomingData, 0, 4); if (incomingData == null) throw new IOException("Battle.net rejected the request."); int serverToken = BitConverter.ToInt32(incomingData, 0); buf = new DataBuffer(); buf.InsertInt32(0); // No resuming if (FileTime.HasValue) buf.InsertInt64(FileTime.Value.ToFileTimeUtc()); else buf.InsertInt64(0); int clientToken = new Random().Next(); buf.InsertInt32(clientToken); buf.InsertInt32(_key.Key.Length); buf.InsertInt32(_key.Product); buf.InsertInt32(_key.Value1); buf.InsertInt32(0); buf.InsertByteArray(_key.GetHash(clientToken, serverToken)); buf.InsertByteArray(fileNameBytes); buf.InsertByte(0); outgoingData = buf.UnderlyingStream.ToArray(); await connection.SendAsync(outgoingData); incomingData = new byte[8]; incomingData = await connection.ReceiveAsync(incomingData, 0, 8); if (incomingData == null) throw new IOException("Battle.net rejected the file request."); int remainingHeaderSize = BitConverter.ToInt32(incomingData, 0) - 8; int fileSize = BitConverter.ToInt32(incomingData, 4); this.FileSize = fileSize; incomingData = new byte[remainingHeaderSize]; incomingData = await connection.ReceiveAsync(incomingData, 0, remainingHeaderSize); if (incomingData == null) throw new IOException("Battle.net did not send a complete file header."); DataReader reader = new DataReader(incomingData); reader.Seek(8); // banner id / extension long fileTime = reader.ReadInt64(); string name = reader.ReadCString(); if (string.Compare(name, FileName, StringComparison.OrdinalIgnoreCase) != 0 || FileSize == 0) { throw new FileNotFoundException("The specified file was not found by Battle.net."); } incomingData = new byte[fileSize]; incomingData = await connection.ReceiveAsync(incomingData, 0, fileSize); if (incomingData == null) throw new IOException("Battle.net did not send the file data."); File.WriteAllBytes(LocalFileName, incomingData); DateTime time = DateTime.FromFileTimeUtc(fileTime); File.SetLastWriteTimeUtc(LocalFileName, time); } }
/// <summary> /// Adds the account creation information (for SID_AUTH_ACCOUNTCREATE) /// to the specified packet. /// </summary> /// <param name="acctPacket">The packet to which to add the account creation information.</param> /// <exception cref="InvalidOperationException">Thrown if the object has not /// yet been initialized.</exception> /// <remarks> /// <para>This method must be called first if you are creating a new account.</para> /// </remarks> /// <returns>The total number of bytes written to the buffer.</returns> public int CreateAccount(DataBuffer acctPacket) { byte[] temp = new byte[65 + userName.Length]; int len = CreateAccount(temp, 0, temp.Length); acctPacket.InsertByteArray(temp); return len; }
/// <summary> /// Adds the account login proof (for SID_AUTH_ACCOUNTLOGONPROOF) /// to the specified packet. /// </summary> /// <param name="logonProofPacket">The BNCS packet to which to add the account logon data.</param> /// <param name="serverSalt">The salt value, sent from the server /// in SID_AUTH_ACCOUNTLOGON.</param> /// <param name="serverKey">The server key, sent from the server /// in SID_AUTH_ACCOUNTLOGON.</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if /// the salt or server key values are not exactly 32 bytes.</exception> /// <exception cref="InvalidOperationException">Thrown if the object has not /// yet been initialized.</exception> /// <remarks> /// <para>This method should be called after the <see cref="LoginAccount(DataBuffer)">LoginAccount</see> method.</para> /// </remarks> /// <returns>The total number of bytes written to the buffer.</returns> public int LoginProof(DataBuffer logonProofPacket, byte[] serverSalt, byte[] serverKey) { byte[] temp = new byte[20]; int len = LoginProof(temp, 0, 20, serverSalt, serverKey); logonProofPacket.InsertByteArray(temp); return len; }
/// <summary> /// Executes the BnFTP request, downloading the file to where <see cref="BnFtpRequestBase.LocalFileName">LocalFileName</see> /// specifies, and closes the connection. /// </summary> /// <remarks> /// <para>By default, <c>LocalFileName</c> is the same name as the remote file, which will cause the file /// to be saved in the local application path. The desired location of the file must be set before /// <b>ExecuteRequest</b> is called.</para> /// </remarks> /// <exception cref="IOException">Thrown if the local file cannot be written.</exception> /// <exception cref="SocketException">Thrown if the remote host closes the connection prematurely.</exception> public override async Task ExecuteRequest() { using (AsyncConnectionBase connection = new AsyncConnectionBase(Gateway.ServerHost, Gateway.ServerPort, 0, 0)) { byte[] fileNameBytes = Encoding.UTF8.GetBytes(FileName); DataBuffer buffer = new DataBuffer(); buffer.InsertInt16((short)(33 + fileNameBytes.Length)); buffer.InsertInt16(0x0100); buffer.InsertDwordString("IX86"); buffer.InsertDwordString(Product.ProductCode); if (_ad) { buffer.InsertInt32(_adId); buffer.InsertDwordString(_adExt); } else { buffer.InsertInt64(0); } // currently resuming is not supported buffer.InsertInt32(0); if (FileTime.HasValue) { buffer.InsertInt64(FileTime.Value.ToFileTimeUtc()); } else { buffer.InsertInt64(0); } buffer.InsertByteArray(fileNameBytes); buffer.InsertByte(0); bool connected = await connection.ConnectAsync(); if (!connected) throw new IOException("Battle.net refused the connection to FTP."); await connection.SendAsync(new byte[] { 2 }); byte[] byteData = buffer.UnderlyingStream.ToArray(); await connection.SendAsync(byteData); byte[] header = new byte[8]; header = await connection.ReceiveAsync(header, 0, 8); if (header == null) throw new IOException("Battle.net did not respond to the FTP request."); DataReader headerReader = new DataReader(header); ushort headerLength = headerReader.ReadUInt16(); headerReader.Seek(2); int fileSize = headerReader.ReadInt32(); this.FileSize = fileSize; byte[] remainingHeader = new byte[headerLength - 8]; remainingHeader = await connection.ReceiveAsync(remainingHeader, 0, headerLength - 8); if (remainingHeader == null) throw new IOException("Battle.net did not send the complete header."); headerReader = new DataReader(remainingHeader); headerReader.Seek(8); long fileTime = headerReader.ReadInt64(); string name = headerReader.ReadCString(); if (string.Compare(name, FileName, StringComparison.OrdinalIgnoreCase) != 0 || FileSize == 0) { throw new FileNotFoundException("The specified file was not found by Battle.net."); } Debug.WriteLine(fileSize, "File Size"); byte[] fileData = new byte[fileSize]; fileData = await connection.ReceiveAsync(fileData, 0, fileSize); if (fileData == null) throw new IOException("Battle.net did not send the file data."); File.WriteAllBytes(LocalFileName, fileData); DateTime time = DateTime.FromFileTimeUtc(fileTime); File.SetLastWriteTimeUtc(LocalFileName, time); } }