Exemplo n.º 1
0
        /// <summary>
        /// Connect to the server
        /// </summary>
        /// <exception cref="ObjectDisposedException">Thrown if this object has been disposed.</exception>
        public virtual void Connect()
        {
            FtpReply reply;

#if !CORE14
            lock (m_lock) {
#endif

            LogFunc(nameof(Connect));

            if (IsDisposed)
            {
                throw new ObjectDisposedException("This FtpClient object has been disposed. It is no longer accessible.");
            }

            if (m_stream == null)
            {
                m_stream = new FtpSocketStream(this);
                m_stream.ValidateCertificate += new FtpSocketStreamSslValidation(FireValidateCertficate);
            }
            else
            {
                if (IsConnected)
                {
                    Disconnect();
                }
            }

            if (Host == null)
            {
                throw new FtpException("No host has been specified");
            }

            if (m_capabilities == null)
            {
                m_capabilities = new List <FtpCapability>();
            }

            ResetStateFlags();

            m_hashAlgorithms            = FtpHashAlgorithm.NONE;
            m_stream.ConnectTimeout     = m_connectTimeout;
            m_stream.SocketPollInterval = m_socketPollInterval;
            Connect(m_stream);

            m_stream.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_keepAlive);

#if !NO_SSL
            if (EncryptionMode == FtpEncryptionMode.Implicit)
            {
                m_stream.ActivateEncryption(Host, m_clientCerts.Count > 0 ? m_clientCerts : null, m_SslProtocols);
            }
#endif

            Handshake();
            m_serverType = FtpServerSpecificHandler.DetectFtpServer(this, HandshakeReply);

            if (SendHost)
            {
                if (!(reply = Execute("HOST " + (SendHostDomain != null ? SendHostDomain : Host))).Success)
                {
                    throw new FtpException("HOST command failed.");
                }
            }

#if !NO_SSL
            // try to upgrade this connection to SSL if supported by the server
            if (EncryptionMode == FtpEncryptionMode.Explicit || EncryptionMode == FtpEncryptionMode.Auto)
            {
                reply = Execute("AUTH TLS");
                if (!reply.Success)
                {
                    _ConnectionFTPSFailure = true;
                    if (EncryptionMode == FtpEncryptionMode.Explicit)
                    {
                        throw new FtpSecurityNotAvailableException("AUTH TLS command failed.");
                    }
                }
                else if (reply.Success)
                {
                    m_stream.ActivateEncryption(Host, m_clientCerts.Count > 0 ? m_clientCerts : null, m_SslProtocols);
                }
            }
#endif

            if (m_credentials != null)
            {
                Authenticate();
            }

            // configure the default FTPS settings
            if (IsEncrypted && DataConnectionEncryption)
            {
                if (!(reply = Execute("PBSZ 0")).Success)
                {
                    throw new FtpCommandException(reply);
                }

                if (!(reply = Execute("PROT P")).Success)
                {
                    throw new FtpCommandException(reply);
                }
            }

            // if this is a clone these values should have already been loaded
            // so save some bandwidth and CPU time and skip executing this again.
            // otherwise clear the capabilities in case connection is reused to
            // a different server
            if (!m_isClone && m_checkCapabilities)
            {
                m_capabilities.Clear();
            }
            bool assumeCaps = false;
            if (m_capabilities.IsBlank() && m_checkCapabilities)
            {
                if ((reply = Execute("FEAT")).Success && reply.InfoMessages != null)
                {
                    GetFeatures(reply);
                }
                else
                {
                    assumeCaps = true;
                }
            }

            // Enable UTF8 if the encoding is ASCII and UTF8 is supported
            if (m_textEncodingAutoUTF && m_textEncoding == Encoding.ASCII && HasFeature(FtpCapability.UTF8))
            {
                m_textEncoding = Encoding.UTF8;
            }

            LogStatus(FtpTraceLevel.Info, "Text encoding: " + m_textEncoding.ToString());

            if (m_textEncoding == Encoding.UTF8)
            {
                // If the server supports UTF8 it should already be enabled and this
                // command should not matter however there are conflicting drafts
                // about this so we'll just execute it to be safe.
                if ((reply = Execute("OPTS UTF8 ON")).Success)
                {
                    _ConnectionUTF8Success = true;
                }
            }

            // Get the system type - Needed to auto-detect file listing parser
            if ((reply = Execute("SYST")).Success)
            {
                m_systemType = reply.Message;
                m_serverType = FtpServerSpecificHandler.DetectFtpServerBySyst(this);
                m_serverOS   = FtpServerSpecificHandler.DetectFtpOSBySyst(this);
            }

            // Set a FTP server handler if a custom handler has not already been set
            if (ServerHandler == null)
            {
                ServerHandler = FtpServerSpecificHandler.GetServerHandler(m_serverType);
            }

            // Assume the system's capabilities if FEAT command not supported by the server
            if (assumeCaps)
            {
                FtpServerSpecificHandler.AssumeCapabilities(this, ServerHandler, m_capabilities, ref m_hashAlgorithms);
            }

#if !NO_SSL && !CORE
            if (IsEncrypted && PlainTextEncryption)
            {
                if (!(reply = Execute("CCC")).Success)
                {
                    throw new FtpSecurityNotAvailableException("Failed to disable encryption with CCC command. Perhaps your server does not support it or is not configured to allow it.");
                }
                else
                {
                    // close the SslStream and send close_notify command to server
                    m_stream.DeactivateEncryption();

                    // read stale data (server's reply?)
                    ReadStaleData(false, true, false);
                }
            }
#endif

            // Unless a custom list parser has been set,
            // Detect the listing parser and prefer machine listings over any other type
            // FIX : #739 prefer using machine listings to fix issues with GetListing and DeleteDirectory
            if (ListingParser != FtpParser.Custom)
            {
                ListingParser = ServerHandler != null?ServerHandler.GetParser() : FtpParser.Auto;

                if (HasFeature(FtpCapability.MLSD))
                {
                    ListingParser = FtpParser.Machine;
                }
            }

            // Create the parser even if the auto-OS detection failed
            m_listParser.Init(m_serverOS, ListingParser);

            // FIX : #318 always set the type when we create a new connection
            ForceSetDataType = true;

            // Execute server-specific post-connection event
            if (ServerHandler != null)
            {
                ServerHandler.AfterConnected(this);
            }

#if !CORE14
        }
#endif
        }