using System;
using System.IO;
using System.Text.RegularExpressions;
namespace FluentFTP.Proxy {
/// A FTP client with a HTTP 1.1 proxy implementation.
public class FtpClientHttp11Proxy : FtpClientProxy {
/// A FTP client with a HTTP 1.1 proxy implementation
/// Proxy information
public FtpClientHttp11Proxy(ProxyInfo proxy)
: base(proxy) {
ConnectionType = "HTTP 1.1 Proxy";
}
/// Redefine the first dialog: HTTP Frame for the HTTP 1.1 Proxy
protected override void Handshake() {
var proxyConnectionReply = GetReply();
if (!proxyConnectionReply.Success)
throw new FtpException("Can't connect " + Host + " via proxy " + Proxy.Host + ".\nMessage : " +
proxyConnectionReply.ErrorMessage);
}
///
/// Creates a new instance of this class. Useful in FTP proxy classes.
///
protected override FtpClient Create() {
return new FtpClientHttp11Proxy(Proxy);
}
///
/// Connects to the server using an existing
///
/// The existing socket stream
protected override void Connect(FtpSocketStream stream) {
Connect(stream, Host, Port, FtpIpVersion.ANY);
}
///
/// Connects to the server using an existing
///
/// The existing socket stream
/// Host name
/// Port number
/// IP version to use
protected override void Connect(FtpSocketStream stream, string host, int port, FtpIpVersion ipVersions) {
base.Connect(stream);
var writer = new StreamWriter(stream);
writer.WriteLine("CONNECT {0}:{1} HTTP/1.1", host, port);
writer.WriteLine("Host: {0}:{1}", host, port);
if (Proxy.Credentials != null) {
var credentialsHash = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Proxy.Credentials.UserName + ":"+ Proxy.Credentials.Password));
writer.WriteLine("Proxy-Authorization: Basic "+ credentialsHash);
}
writer.WriteLine("User-Agent: custom-ftp-client");
writer.WriteLine();
writer.Flush();
ProxyHandshake(stream);
}
private void ProxyHandshake(FtpSocketStream stream) {
var proxyConnectionReply = GetProxyReply(stream);
if (!proxyConnectionReply.Success)
throw new FtpException("Can't connect " + Host + " via proxy " + Proxy.Host + ".\nMessage : " + proxyConnectionReply.ErrorMessage);
}
private FtpReply GetProxyReply( FtpSocketStream stream ) {
FtpReply reply = new FtpReply();
string buf;
#if !CORE14
lock ( Lock ) {
#endif
if( !IsConnected )
throw new InvalidOperationException( "No connection to the server has been established." );
stream.ReadTimeout = ReadTimeout;
while( ( buf = stream.ReadLine( Encoding ) ) != null ) {
Match m;
FtpTrace.WriteLine(FtpTraceLevel.Info, buf);
if( ( m = Regex.Match( buf, @"^HTTP/.*\s(?[0-9]{3}) (?.*)$" ) ).Success ) {
reply.Code = m.Groups[ "code" ].Value;
reply.Message = m.Groups[ "message" ].Value;
break;
}
reply.InfoMessages += ( buf+"\n" );
}
// fixes #84 (missing bytes when downloading/uploading files through proxy)
while( ( buf = stream.ReadLine( Encoding ) ) != null ) {
FtpTrace.WriteLine(FtpTraceLevel.Info, buf);
if (FtpExtensions.IsNullOrWhiteSpace(buf)) {
break;
}
reply.InfoMessages += ( buf+"\n" );
}
#if !CORE14
}
#endif
return reply;
}
}
}