using System; using System.Reflection; using System.Text.RegularExpressions; using System.Diagnostics; namespace FluentFTP { /// /// Base class for data stream connections /// public class FtpDataStream : FtpSocketStream { FtpReply m_commandStatus; /// /// Gets the status of the command that was used to open /// this data channel /// public FtpReply CommandStatus { get { return m_commandStatus; } set { m_commandStatus = value; } } FtpClient m_control = null; /// /// Gets or sets the control connection for this data stream. Setting /// the control connection causes the object to be clonded and a new /// connection is made to the server to carry out the task. This ensures /// that multiple streams can be opened simultainously. /// public FtpClient ControlConnection { get { return m_control; } set { m_control = value; } } long m_length = 0; /// /// Gets or sets the length of the stream. Only valid for file transfers /// and only valid on servers that support the Size command. /// public override long Length { get { return m_length; } } long m_position = 0; /// /// Gets or sets the position of the stream /// public override long Position { get { return m_position; } set { throw new InvalidOperationException("You cannot modify the position of a FtpDataStream. This property is updated as data is read or written to the stream."); } } /// /// Reads data off the stream /// /// The buffer to read into /// Where to start in the buffer /// Number of bytes to read /// The number of bytes read public override int Read(byte[] buffer, int offset, int count) { int read = base.Read(buffer, offset, count); m_position += read; return read; } /// /// Writes data to the stream /// /// The buffer to write to the stream /// Where to start in the buffer /// The number of bytes to write to the buffer public override void Write(byte[] buffer, int offset, int count) { base.Write(buffer, offset, count); m_position += count; } /// /// Sets the length of this stream /// /// Value to apply to the Length property public override void SetLength(long value) { m_length = value; } /// /// Sets the position of the stream. Inteneded to be used /// internally by FtpControlConnection. /// /// The position public void SetPosition(long pos) { m_position = pos; } /// /// Disconnects (if necessary) and releases associated resources /// /// Disposing protected override void Dispose(bool disposing) { if (disposing) { if (IsConnected) Close(); m_control = null; } base.Dispose(disposing); } /// /// Closes the connection and reads the server's reply /// public new FtpReply Close() { base.Close(); try { if (ControlConnection != null) return ControlConnection.CloseDataStream(this); } finally { m_commandStatus = new FtpReply(); m_control = null; } return new FtpReply(); } /// /// Creates a new data stream object /// /// The control connection to be used for carrying out this operation public FtpDataStream(FtpClient conn) { if (conn == null) throw new ArgumentException("The control connection cannot be null."); ControlConnection = conn; // always accept certficate no matter what because if code execution ever // gets here it means the certificate on the control connection object being // cloned was already accepted. ValidateCertificate += new FtpSocketStreamSslValidation(delegate(FtpSocketStream obj, FtpSslValidationEventArgs e) { e.Accept = true; }); m_position = 0; } /// /// Finalizer /// ~FtpDataStream() { try { Dispose(); } catch (Exception ex) { FtpTrace.WriteLine("[Finalizer] Caught and discarded an exception while disposing the FtpDataStream: {0}", ex.ToString()); } } } }