You've already forked linux-packaging-mono
Imported Upstream version 4.8.0.309
Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
This commit is contained in:
parent
ee1447783b
commit
94b2861243
@@ -17,6 +17,7 @@ using MSI = Mono.Security.Interface;
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
@@ -42,6 +43,7 @@ namespace System.Net
|
||||
NetworkCredential credentials;
|
||||
IPHostEntry hostEntry;
|
||||
IPEndPoint localEndPoint;
|
||||
IPEndPoint remoteEndPoint;
|
||||
IWebProxy proxy;
|
||||
int timeout = 100000;
|
||||
int rwTimeout = 300000;
|
||||
@@ -65,7 +67,9 @@ namespace System.Net
|
||||
const string PasswordCommand = "PASS";
|
||||
const string TypeCommand = "TYPE";
|
||||
const string PassiveCommand = "PASV";
|
||||
const string ExtendedPassiveCommand = "EPSV";
|
||||
const string PortCommand = "PORT";
|
||||
const string ExtendedPortCommand = "EPRT";
|
||||
const string AbortCommand = "ABOR";
|
||||
const string AuthCommand = "AUTH";
|
||||
const string RestCommand = "REST";
|
||||
@@ -185,7 +189,7 @@ namespace System.Net
|
||||
}
|
||||
}
|
||||
|
||||
#if !NET_2_1
|
||||
#if !MOBILE
|
||||
[MonoTODO]
|
||||
public static new RequestCachePolicy DefaultCachePolicy
|
||||
{
|
||||
@@ -401,6 +405,7 @@ namespace System.Net
|
||||
State = RequestState.Scheduled;
|
||||
|
||||
Thread thread = new Thread (ProcessRequest);
|
||||
thread.IsBackground = true;
|
||||
thread.Start ();
|
||||
}
|
||||
}
|
||||
@@ -452,6 +457,7 @@ namespace System.Net
|
||||
|
||||
asyncResult = new FtpAsyncResult (callback, state);
|
||||
Thread thread = new Thread (ProcessRequest);
|
||||
thread.IsBackground = true;
|
||||
thread.Start ();
|
||||
|
||||
return asyncResult;
|
||||
@@ -775,14 +781,14 @@ namespace System.Net
|
||||
foreach (IPAddress address in hostEntry.AddressList) {
|
||||
sock = new Socket (address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
IPEndPoint remote = new IPEndPoint (address, requestUri.Port);
|
||||
remoteEndPoint = new IPEndPoint (address, requestUri.Port);
|
||||
|
||||
if (!ServicePoint.CallEndPointDelegate (sock, remote)) {
|
||||
if (!ServicePoint.CallEndPointDelegate (sock, remoteEndPoint)) {
|
||||
sock.Close ();
|
||||
sock = null;
|
||||
} else {
|
||||
try {
|
||||
sock.Connect (remote);
|
||||
sock.Connect (remoteEndPoint);
|
||||
localEndPoint = (IPEndPoint) sock.LocalEndPoint;
|
||||
break;
|
||||
} catch (SocketException exc) {
|
||||
@@ -837,52 +843,19 @@ namespace System.Net
|
||||
}
|
||||
|
||||
// Probably we could do better having here a regex
|
||||
Socket SetupPassiveConnection (string statusDescription)
|
||||
Socket SetupPassiveConnection (string statusDescription, bool ipv6)
|
||||
{
|
||||
// Current response string
|
||||
string response = statusDescription;
|
||||
if (response.Length < 4)
|
||||
throw new WebException ("Cannot open passive data connection");
|
||||
|
||||
// Look for first digit after code
|
||||
int i;
|
||||
for (i = 3; i < response.Length && !Char.IsDigit (response [i]); i++)
|
||||
;
|
||||
if (i >= response.Length)
|
||||
throw new WebException ("Cannot open passive data connection");
|
||||
|
||||
// Get six elements
|
||||
string [] digits = response.Substring (i).Split (new char [] {','}, 6);
|
||||
if (digits.Length != 6)
|
||||
throw new WebException ("Cannot open passive data connection");
|
||||
int port = ipv6 ? GetPortV6 (response) : GetPortV4 (response);
|
||||
|
||||
// Clean non-digits at the end of last element
|
||||
int j;
|
||||
for (j = digits [5].Length - 1; j >= 0 && !Char.IsDigit (digits [5][j]); j--)
|
||||
;
|
||||
if (j < 0)
|
||||
throw new WebException ("Cannot open passive data connection");
|
||||
|
||||
digits [5] = digits [5].Substring (0, j + 1);
|
||||
|
||||
IPAddress ip;
|
||||
try {
|
||||
ip = IPAddress.Parse (String.Join (".", digits, 0, 4));
|
||||
} catch (FormatException) {
|
||||
throw new WebException ("Cannot open passive data connection");
|
||||
}
|
||||
|
||||
// Get the port
|
||||
int p1, p2, port;
|
||||
if (!Int32.TryParse (digits [4], out p1) || !Int32.TryParse (digits [5], out p2))
|
||||
throw new WebException ("Cannot open passive data connection");
|
||||
|
||||
port = (p1 << 8) + p2; // p1 * 256 + p2
|
||||
//port = p1 * 256 + p2;
|
||||
if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
|
||||
throw new WebException ("Cannot open passive data connection");
|
||||
|
||||
IPEndPoint ep = new IPEndPoint (ip, port);
|
||||
IPEndPoint ep = new IPEndPoint (remoteEndPoint.Address, port);
|
||||
Socket sock = new Socket (ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
try {
|
||||
sock.Connect (ep);
|
||||
@@ -894,6 +867,87 @@ namespace System.Net
|
||||
return sock;
|
||||
}
|
||||
|
||||
// GetPortV4, GetPortV6, FormatAddress and FormatAddressV6 are copied from referencesource
|
||||
// TODO: replace FtpWebRequest completely.
|
||||
private int GetPortV4(string responseString)
|
||||
{
|
||||
string [] parsedList = responseString.Split(new char [] {' ', '(', ',', ')'});
|
||||
|
||||
// We need at least the status code and the port
|
||||
if (parsedList.Length <= 7) {
|
||||
throw new FormatException(SR.GetString(SR.net_ftp_response_invalid_format, responseString));
|
||||
}
|
||||
|
||||
int index = parsedList.Length-1;
|
||||
// skip the last non-number token (e.g. terminating '.')
|
||||
#if MONO
|
||||
// the MS code expects \r\n here in parsedList[index],
|
||||
// but we're stripping the EOL off earlier so the array contains
|
||||
// an empty string here which would make Char.IsNumber throw
|
||||
// TODO: this can be removed once we switch FtpWebRequest to referencesource
|
||||
if (parsedList[index] == "" || !Char.IsNumber(parsedList[index], 0))
|
||||
#else
|
||||
if (!Char.IsNumber(parsedList[index], 0))
|
||||
#endif
|
||||
index--;
|
||||
|
||||
int port = Convert.ToByte(parsedList[index--], NumberFormatInfo.InvariantInfo);
|
||||
port = port |
|
||||
(Convert.ToByte(parsedList[index--], NumberFormatInfo.InvariantInfo) << 8);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
private int GetPortV6(string responseString)
|
||||
{
|
||||
int pos1 = responseString.LastIndexOf("(");
|
||||
int pos2 = responseString.LastIndexOf(")");
|
||||
if (pos1 == -1 || pos2 <= pos1)
|
||||
throw new FormatException(SR.GetString(SR.net_ftp_response_invalid_format, responseString));
|
||||
|
||||
// addressInfo will contain a string of format "|||<tcp-port>|"
|
||||
string addressInfo = responseString.Substring(pos1+1, pos2-pos1-1);
|
||||
|
||||
// Although RFC2428 recommends using "|" as the delimiter,
|
||||
// It allows ASCII characters in range 33-126 inclusive.
|
||||
// We should consider allowing the full range.
|
||||
|
||||
string [] parsedList = addressInfo.Split(new char [] {'|'});
|
||||
if (parsedList.Length < 4)
|
||||
throw new FormatException(SR.GetString(SR.net_ftp_response_invalid_format, responseString));
|
||||
|
||||
return Convert.ToInt32(parsedList[3], NumberFormatInfo.InvariantInfo);
|
||||
}
|
||||
|
||||
private String FormatAddress(IPAddress address, int Port )
|
||||
{
|
||||
byte [] localAddressInBytes = address.GetAddressBytes();
|
||||
|
||||
// produces a string in FTP IPAddress/Port encoding (a1, a2, a3, a4, p1, p2), for sending as a parameter
|
||||
// to the port command.
|
||||
StringBuilder sb = new StringBuilder(32);
|
||||
foreach (byte element in localAddressInBytes) {
|
||||
sb.Append(element);
|
||||
sb.Append(',');
|
||||
}
|
||||
sb.Append(Port / 256 );
|
||||
sb.Append(',');
|
||||
sb.Append(Port % 256 );
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private string FormatAddressV6(IPAddress address, int port) {
|
||||
StringBuilder sb = new StringBuilder(43); // based on max size of IPv6 address + port + seperators
|
||||
String addressString = address.ToString();
|
||||
sb.Append("|2|");
|
||||
sb.Append(addressString);
|
||||
sb.Append('|');
|
||||
sb.Append(port.ToString(NumberFormatInfo.InvariantInfo));
|
||||
sb.Append('|');
|
||||
return sb.ToString();
|
||||
}
|
||||
//
|
||||
|
||||
Exception CreateExceptionFromResponse (FtpStatus status)
|
||||
{
|
||||
FtpWebResponse ftpResponse = new FtpWebResponse (this, requestUri, method, status);
|
||||
@@ -932,18 +986,19 @@ namespace System.Net
|
||||
Socket InitDataConnection ()
|
||||
{
|
||||
FtpStatus status;
|
||||
|
||||
bool ipv6 = remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6;
|
||||
|
||||
if (usePassive) {
|
||||
status = SendCommand (PassiveCommand);
|
||||
if (status.StatusCode != FtpStatusCode.EnteringPassive) {
|
||||
status = SendCommand (ipv6 ? ExtendedPassiveCommand : PassiveCommand);
|
||||
if (status.StatusCode != (ipv6 ? (FtpStatusCode)229 : FtpStatusCode.EnteringPassive)) { // FtpStatusCode doesn't contain code 229 for EPSV so we need to cast...
|
||||
throw CreateExceptionFromResponse (status);
|
||||
}
|
||||
|
||||
return SetupPassiveConnection (status.StatusDescription);
|
||||
return SetupPassiveConnection (status.StatusDescription, ipv6);
|
||||
}
|
||||
|
||||
// Open a socket to listen the server's connection
|
||||
Socket sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
Socket sock = new Socket (remoteEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
try {
|
||||
sock.Bind (new IPEndPoint (localEndPoint.Address, 0));
|
||||
sock.Listen (1); // We only expect a connection from server
|
||||
@@ -955,12 +1010,10 @@ namespace System.Net
|
||||
}
|
||||
|
||||
IPEndPoint ep = (IPEndPoint) sock.LocalEndPoint;
|
||||
string ipString = ep.Address.ToString ().Replace ('.', ',');
|
||||
int h1 = ep.Port >> 8; // ep.Port / 256
|
||||
int h2 = ep.Port % 256;
|
||||
|
||||
string portParam = ipString + "," + h1 + "," + h2;
|
||||
status = SendCommand (PortCommand, portParam);
|
||||
var portParam = ipv6 ? FormatAddressV6 (ep.Address, ep.Port) : FormatAddress (ep.Address, ep.Port);
|
||||
|
||||
status = SendCommand (ipv6 ? ExtendedPortCommand : PortCommand, portParam);
|
||||
|
||||
if (status.StatusCode != FtpStatusCode.CommandOK) {
|
||||
sock.Close ();
|
||||
|
Reference in New Issue
Block a user