/// <summary>
        /// Sets the data port on the server, i.e. sends a PORT
        /// command
        /// </summary>
        /// <param name="ep">local endpoint
        /// </param>
        internal virtual void SetDataPort(IPEndPoint ep)
        {
            byte[] hostBytes = ep.Address.GetAddressBytes();//BitConverter.GetBytes(ep.Address.Address);

            if (activeIPAddress != null)
            {
                log.Info("Forcing use of fixed IP for PORT command");
                hostBytes = activeIPAddress.GetAddressBytes();// BitConverter.GetBytes(activeIPAddress.Address);
            }

            // This is a .NET 1.1 API
            // byte[] hostBytes = ep.Address.GetAddressBytes();

            byte[] portBytes = ToByteArray((ushort)ep.Port);

            // assemble the PORT command
            string cmd = new StringBuilder("PORT ").
                         Append((short)hostBytes[0]).Append(",").
                         Append((short)hostBytes[1]).Append(",").
                         Append((short)hostBytes[2]).Append(",").
                         Append((short)hostBytes[3]).Append(",").
                         Append((short)portBytes[0]).Append(",").
                         Append((short)portBytes[1]).ToString();

            // send command and check reply
            // CoreFTP returns 250 incorrectly
            FTPReply reply = SendCommand(cmd);

            ValidateReply(reply, "200", "250");
        }
        /// <summary>   Checks that the standard 220 reply is returned
        /// following the initiated connection. Allow 230 as well, some proxy
        /// servers return it.
        /// </summary>
        internal FTPReply ValidateConnection()
        {
            FTPReply reply = ReadReply();

            ValidateReply(reply, "220", "230");
            return(reply);
        }
示例#3
0
        /// <summary>
        /// Validate reply object
        /// </summary>
        /// <param name="reply">               reference to reply object
        /// </param>
        /// <param name="expectedReplyCode">   expect reply code
        /// </param>
        /// <returns> true if valid, false if invalid
        /// </returns>
        private bool ValidateReplyCode(FTPReply reply, string expectedReplyCode)
        {
            string replyCode = reply.ReplyCode;

            if (strictReturnCodes)
            {
                if (replyCode.Equals(expectedReplyCode))
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                // non-strict - match first char
                if (replyCode[0] == expectedReplyCode[0])
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
示例#4
0
        /// <summary>  Validate the response the host has supplied against the
        /// expected reply. If we get an unexpected reply we throw an
        /// exception, setting the message to that returned by the
        /// FTP server
        ///
        /// </summary>
        /// <param name="reply">              reply object
        /// </param>
        /// <param name="expectedReplyCode">  expected reply
        /// </param>
        /// <returns>  reply object
        ///
        /// </returns>
        public virtual FTPReply ValidateReply(FTPReply reply, string expectedReplyCode)
        {
            if (ValidateReplyCode(reply, expectedReplyCode))
            {
                return(reply);
            }

            // got this far, not recognised
            throw new FTPException(reply);
        }
示例#5
0
 /// <summary>  Constructor. Permits setting of reply code
 ///
 /// </summary>
 /// <param name="reply">    reply object
 /// </param>
 public FTPException(FTPReply reply) : base(reply.ReplyText)
 {
     // extract reply code if possible
     try
     {
         this.replyCode = System.Int32.Parse(reply.ReplyCode);
     }
     catch (FormatException)
     {
         this.replyCode = -1;
     }
 }
示例#6
0
        /// <summary>
        /// Validate the response the host has supplied against the
        /// expected reply. If we get an unexpected reply we throw an
        /// exception, setting the message to that returned by the
        /// FTP server
        /// </summary>
        /// <param name="reply">             the entire reply string we received
        /// </param>
        /// <param name="expectedReplyCode"> the reply we expected to receive
        ///
        /// </param>
        internal virtual FTPReply ValidateReply(string reply, string expectedReplyCode)
        {
            FTPReply replyObj = new FTPReply(reply);

            if (ValidateReplyCode(replyObj, expectedReplyCode))
            {
                return(replyObj);
            }

            // if unexpected reply, throw an exception
            throw new FTPException(replyObj);
        }
示例#7
0
        /// <summary>  Validate the response the host has supplied against the
        /// expected reply. If we get an unexpected reply we throw an
        /// exception, setting the message to that returned by the
        /// FTP server
        ///
        /// </summary>
        /// <param name="reply">              reply object
        /// </param>
        /// <param name="expectedReplyCodes"> array of expected replies
        /// </param>
        /// <returns>  reply object
        ///
        /// </returns>
        public virtual FTPReply ValidateReply(FTPReply reply, string[] expectedReplyCodes)
        {
            for (int i = 0; i < expectedReplyCodes.Length; i++)
            {
                if (ValidateReplyCode(reply, expectedReplyCodes[i]))
                {
                    return(reply);
                }
            }

            // got this far, not recognised
            throw new FTPException(reply);
        }
示例#8
0
        internal void SetDataPort(IPEndPoint ep)
        {
            byte[] bytes = BitConverter.GetBytes(ep.Address.Address);
            if (this.activeIPAddress != null)
            {
                this.log.Info("Forcing use of fixed IP for PORT command");
                bytes = BitConverter.GetBytes(this.activeIPAddress.Address);
            }
            byte[]   buffer2 = this.ToByteArray((ushort)ep.Port);
            string   command = new StringBuilder("PORT ").Append((short)bytes[0]).Append(",").Append((short)bytes[1]).Append(",").Append((short)bytes[2]).Append(",").Append((short)bytes[3]).Append(",").Append((short)buffer2[0]).Append(",").Append((short)buffer2[1]).ToString();
            FTPReply reply   = this.SendCommand(command);

            this.ValidateReply(reply, new string[] { "200", "250" });
        }
        protected virtual FTPDataSocket CreateDataSocketPASVInternal()
        {
            // PASSIVE command - tells the server to listen for
            // a connection attempt rather than initiating it
            FTPReply replyObj = SendCommand("PASV");

            ValidateReply(replyObj, "227");
            string reply = replyObj.ReplyText;

            // The reply to PASV is in the form:
            // 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
            // where h1..h4 are the IP address to connect and
            // p1,p2 the port number
            // Example:
            // 227 Entering Passive Mode (128,3,122,1,15,87).
            // NOTE: Some FTP servers miss the brackets out completely
            Regex regEx = new Regex(@"(?<a0>\d{1,3}),(?<a1>\d{1,3}),(?<a2>\d{1,3}),(?<a3>\d{1,3}),(?<p0>\d{1,3}),(?<p1>\d{1,3})");
            Match m1    = regEx.Match(reply);

            // assemble the IP address
            // we try connecting, so we don't bother checking digits etc
            string ipAddress = m1.Groups["a0"].Value + "." + m1.Groups["a1"].Value + "." + m1.Groups["a2"].Value + "." + m1.Groups["a3"].Value;

            log.Debug("Server supplied address=" + ipAddress);

            // assemble the port number
            int[] portParts = new int[2];
            portParts[0] = Int32.Parse(m1.Groups["p0"].Value);
            portParts[1] = Int32.Parse(m1.Groups["p1"].Value);
            int port = (portParts[0] << 8) + portParts[1];

            log.Debug("Server supplied port=" + port);

            string hostIP = ipAddress;

            log.Debug("autoPassiveIPSubstitution=" + autoPassiveIPSubstitution);
            log.Debug("remoteAddr=" + (remoteAddr == null ? "null" : remoteAddr.ToString()));
            if (autoPassiveIPSubstitution && remoteAddr != null)
            {
                hostIP = remoteAddr.ToString();
                log.Debug("Substituting server supplied IP ({0}) with remote host IP ({1})",
                          ipAddress, hostIP);
            }

            // create the socket
            return(NewPassiveDataSocket(hostIP, port));
        }
        /// <summary>
        /// Validate the response the host has supplied against the
        /// expected reply. If we get an unexpected reply we throw an
        /// exception, setting the message to that returned by the
        /// FTP server
        /// </summary>
        /// <param name="reply">reply object</param>
        /// <param name="expectedReplyCodes"> array of expected replies</param>
        /// <returns>reply object</returns>
        public virtual FTPReply ValidateReply(FTPReply reply, params string[] expectedReplyCodes)
        {
            if ("421" == reply.ReplyCode)
            {
                log.Error("Received 421 - throwing exception");
                throw new FTPConnectionClosedException(reply.ReplyText);
            }
            foreach (string expectedReplyCode in expectedReplyCodes)
            {
                if (strictReturnCodes)
                {
                    if (reply.ReplyCode == expectedReplyCode)
                    {
                        return(reply);
                    }
                }
                else
                {
                    // non-strict - match first char
                    if (reply.ReplyCode[0] == expectedReplyCode[0])
                    {
                        return(reply);
                    }
                }
            }

            // got this far, not recognised
            StringBuilder buf = new StringBuilder("[");
            int           i   = 0;

            foreach (string expectedReplyCode in expectedReplyCodes)
            {
                buf.Append(expectedReplyCode);
                if (i + 1 < expectedReplyCodes.Length)
                {
                    buf.Append(",");
                }
                i++;
            }
            buf.Append("]");
            log.Debug("Expected reply codes = " + buf.ToString() + " (strict=" + strictReturnCodes + ")");

            // got this far, not recognised
            throw new FTPException(reply);
        }
示例#11
0
        internal virtual FTPDataSocket CreateDataSocketPASV()
        {
            FTPDataSocket socket;
            bool          synchronizePassiveConnections = this.SynchronizePassiveConnections;
            Mutex         mutex = null;

            if (synchronizePassiveConnections)
            {
                mutex = new Mutex(false, PASV_MUTEX_NAME);
                mutex.WaitOne();
            }
            try
            {
                FTPReply reply = this.SendCommand("PASV");
                this.ValidateReply(reply, new string[] { "227" });
                string replyText = reply.ReplyText;
                Match  match     = new Regex(@"(?<a0>\d{1,3}),(?<a1>\d{1,3}),(?<a2>\d{1,3}),(?<a3>\d{1,3}),(?<p0>\d{1,3}),(?<p1>\d{1,3})").Match(replyText);
                string str2      = match.Groups["a0"].Value + "." + match.Groups["a1"].Value + "." + match.Groups["a2"].Value + "." + match.Groups["a3"].Value;
                this.log.Debug("Server supplied address=" + str2);
                int[] numArray = new int[] { int.Parse(match.Groups["p0"].Value), int.Parse(match.Groups["p1"].Value) };
                int   port     = (numArray[0] << 8) + numArray[1];
                this.log.Debug("Server supplied port=" + port);
                string str3 = str2;
                if (this.autoPassiveIPSubstitution && (this.remoteAddr != null))
                {
                    str3 = this.remoteAddr.ToString();
                    if (this.log.IsEnabledFor(Level.DEBUG))
                    {
                        this.log.Debug(string.Format("Substituting server supplied IP ({0}) with remote host IP ({1})", str2, str3));
                    }
                }
                socket = this.NewPassiveDataSocket(str3, port);
            }
            finally
            {
                if (synchronizePassiveConnections && (mutex != null))
                {
                    mutex.ReleaseMutex();
                    mutex.Close();
                }
            }
            return(socket);
        }
示例#12
0
        /// <summary>
        /// Sets the data port on the server, i.e. sends a PORT
        /// command
        /// </summary>
        /// <param name="ep">local endpoint
        /// </param>
        internal void SetDataPort(IPEndPoint ep)
        {
            byte[] hostBytes = BitConverter.GetBytes(ep.Address.Address);

            // This is a .NET 1.1 API
            // byte[] hostBytes = ep.Address.GetAddressBytes();

            byte[] portBytes = ToByteArray((ushort)ep.Port);

            // assemble the PORT command
            string cmd = new StringBuilder("PORT ").
                         Append((short)hostBytes[0]).Append(",").
                         Append((short)hostBytes[1]).Append(",").
                         Append((short)hostBytes[2]).Append(",").
                         Append((short)hostBytes[3]).Append(",").
                         Append((short)portBytes[0]).Append(",").
                         Append((short)portBytes[1]).ToString();

            // send command and check reply
            FTPReply reply = SendCommand(cmd);

            ValidateReply(reply, "200");
        }
示例#13
0
        public virtual FTPReply ValidateReply(FTPReply reply, params string[] expectedReplyCodes)
        {
            if ("421" == reply.ReplyCode)
            {
                this.log.Error("Received 421 - throwing exception");
                throw new FTPConnectionClosedException(reply.ReplyText);
            }
            foreach (string str in expectedReplyCodes)
            {
                if (this.strictReturnCodes)
                {
                    if (reply.ReplyCode == str)
                    {
                        return(reply);
                    }
                }
                else if (reply.ReplyCode[0] == str[0])
                {
                    return(reply);
                }
            }
            StringBuilder builder = new StringBuilder("[");
            int           num2    = 0;

            foreach (string str2 in expectedReplyCodes)
            {
                builder.Append(str2);
                if ((num2 + 1) < expectedReplyCodes.Length)
                {
                    builder.Append(",");
                }
                num2++;
            }
            builder.Append("]");
            this.log.Info(string.Concat(new object[] { "Expected reply codes = ", builder.ToString(), " (strict=", this.strictReturnCodes, ")" }));
            throw new FTPException(reply);
        }
示例#14
0
 /// <summary>
 /// Validate an FTPReply 
 /// </summary>
 /// <param name="reply">reply object</param>
 /// <param name="expectedReplyCodes">expected codes</param>
 internal void ValidateReply(FTPReply reply, string[] expectedReplyCodes) 
 {
     control.ValidateReply(reply, expectedReplyCodes);
 }      
示例#15
0
		/// <summary>Quit the FTP session by sending a <c>QUIT</c> command before closing the socket.</summary>
		public virtual void Quit()
        {            
            CheckConnection(true);
            
            if (fileFactory != null)
                fileFactory.System = null;
            try
            {
                FTPReply reply = control.SendCommand("QUIT");
                lastValidReply = control.ValidateReply(reply, "221", "226");
            }
            finally
            {
                CloseDataSocket();

                // ensure we clean up the connection
                control.Logout();
                control = null;      
            }
        }
示例#16
0
 /// <summary>  Get the help text for the specified command
 /// 
 /// </summary>
 /// <param name="command"> name of the command to get help on
 /// </param>
 /// <returns> help text from the server for the supplied command
 /// </returns>
 public virtual string Help(string command)
 {            
     CheckConnection(true);
     
     FTPReply reply = control.SendCommand("HELP " + command);
     lastValidReply = control.ValidateReply(reply, "211", "214");
     return lastValidReply.ReplyText;
 }
示例#17
0
 /// <summary> 
 /// Validate reply object
 /// </summary>
 /// <param name="reply">               reference to reply object
 /// </param>
 /// <param name="expectedReplyCode">   expect reply code
 /// </param>
 /// <returns> true if valid, false if invalid
 /// </returns>
 private bool ValidateReplyCode(FTPReply reply, string expectedReplyCode)
 {
     string replyCode = reply.ReplyCode;
     if (strictReturnCodes)
     {
         if (replyCode.Equals(expectedReplyCode))
             return true;
         else
             return false;
     }
     else
     {
         // non-strict - match first char
         if (replyCode[0] == expectedReplyCode[0])
             return true;
         else
             return false;
     }
 }
示例#18
0
		/// <summary>Request to the server that the get is set up.</summary>
		/// <param name="remoteFile">Name of remote file in current directory.</param>
		private void InitGet(string remoteFile)
        {
            CheckConnection(true);
            
            // reset the cancel flag
            cancelTransfer = false;
            
            bool close = false;
            data = null;
            try
            {
                // set up data channel
                data = control.CreateDataSocket(connectMode);
                data.Timeout = timeout;
                
                // if resume is requested, we must issue REST
                if (resume)
                {
                    if (transferType.Equals(FTPTransferType.ASCII))
                        throw new FTPException("Resume only supported for BINARY transfers");
                    try
                    {
                        Restart(resumeMarker);
                    }
                    catch (FTPException ex)
                    {
                        resumeMarker = 0;
                        resume = false;
                        log.Warn("REST failed - resume will not be used (" + ex.Message + ")");
                    }
                }
                else
                    resumeMarker = 0;

                // send the retrieve command
                FTPReply reply = control.SendCommand("RETR " + remoteFile);
                
                // Can get a 125 or a 150
                lastValidReply = control.ValidateReply(reply, "125", "150");
            }
            catch (SystemException)
            {
                close = true;
                throw;
            }
            catch (FTPException)
            {
                close = true;
                throw;
            }
            finally
            {
                if (close)
                {
                    resume = false;
                    resumeMarker = 0;
                    CloseDataSocket();
                }
            }
        }
示例#19
0
		/// <summary>Validate that the Put() or get() was successful.</summary>
		/// <remarks>This method is not for general use. If it is called explicitly after
        /// a transfer, the connection will hang.</remarks>
		public void ValidateTransfer()
        {            
            CheckConnection(true);

            FTPReply reply = null;
            Exception ex1 = null;
            try
            {
                reply = control.ReadReply();
            }
            catch (Exception ex)
            {
                ex1 = ex;
                log.Warn("ReadReply failed", ex);
            }
            if (cancelTransfer)
            {
                if (reply != null)
                {
                    lastValidReply = reply;
                }
                log.Warn("Transfer cancelled");
                throw new FTPTransferCancelledException("Transfer cancelled.", lastBytesTransferred);
            }
            else if (ex1 != null)
                throw ex1;

            lastValidReply = control.ValidateReply(reply, "225", "226", "250");
        }
示例#20
0
        private string[] Dir(string dirname, bool full, LineCallback lineCallback, object state)
        {
            CheckConnection(true);
            
            try
            {
                // set up data channel
                data = control.CreateDataSocket(connectMode);
                data.Timeout = timeout;
                
                // send the retrieve command
                string command = full ? "LIST ":"NLST ";
                if (showHiddenFiles)
                    command += "-a ";
                if (dirname != null)
                    command += dirname;
                
                // some FTP servers bomb out if NLST has whitespace appended
                command = command.Trim();
                FTPReply reply = control.SendCommand(command);
                
                // check the control response. wu-ftp returns 550 if the
                // directory is empty, so we handle 550 appropriately. Similarly
                // proFTPD returns 450. If dir is empty, some servers return 226 Transfer complete
                lastValidReply = control.ValidateReply(reply, "125", "226", "150", "450", "550");
                
                // an empty array of files for 450/550
                string[] result = new string[0];
                
                // a normal reply ... extract the file list
                string replyCode = lastValidReply.ReplyCode;
                if (!replyCode.Equals("450") && !replyCode.Equals("550") && !replyCode.Equals("226"))
                {
                    // get a character input stream to read data from
                    Encoding enc = controlEncoding == null ? Encoding.ASCII : controlEncoding;
                    ArrayList lines = null;
                    // reset the cancel flag
                    cancelTransfer = false;
                    try
                    {
                        if (enc.Equals(Encoding.ASCII))
                        {
                            lines = ReadASCIIListingData(dirname, lineCallback, state);
                        }
                        else
                        {
                            lines = ReadListingData(dirname, enc, lineCallback, state);
                        }

                        // check the control response
                        reply = control.ReadReply();
                        lastValidReply = control.ValidateReply(reply, "226", "250");
                    }
                    catch (SystemException ex)
                    {
                        ValidateTransferOnError();
                        log.Error("SystemException in directory listing", ex);
                        throw;
                    }
                    
                    // empty array is default
                    if (!(lines.Count == 0))
                    {
                        log.Debug("Found " + lines.Count + " listing lines");
                        result = new string[lines.Count];
                        lines.CopyTo(result);
                    }
                    else
                        log.Debug("No listing data found");
                }
                else { // throw exception if not a "no files" message or transfer complete
					string replyText = lastValidReply.ReplyText.ToUpper();
                    if (!dirEmptyStrings.Matches(replyText)
                        && !transferCompleteStrings.Matches(replyText))
                        throw new FTPException(reply);
                }
                return result;
            }
            finally
            {
                CloseDataSocket();
            }
        }
示例#21
0
        internal void ValidateConnection()
        {
            FTPReply reply = this.ReadReply();

            this.ValidateReply(reply, new string[] { "220", "230" });
        }
示例#22
0
        /// <summary>  Validate the response the host has supplied against the
        /// expected reply. If we get an unexpected reply we throw an
        /// exception, setting the message to that returned by the
        /// FTP server
        ///
        /// </summary>
        /// <param name="reply">              the entire reply string we received
        /// </param>
        /// <param name="expectedReplyCodes"> array of expected replies
        /// </param>
        /// <returns>  an object encapsulating the server's reply
        ///
        /// </returns>
        public virtual FTPReply ValidateReply(string reply, string[] expectedReplyCodes)
        {
            FTPReply replyObj = new FTPReply(reply);

            return(ValidateReply(replyObj, expectedReplyCodes));
        }
示例#23
0
        /// <summary>  Validate the response the host has supplied against the
        /// expected reply. If we get an unexpected reply we throw an
        /// exception, setting the message to that returned by the
        /// FTP server
        /// 
        /// </summary>
        /// <param name="reply">              reply object
        /// </param>
        /// <param name="expectedReplyCode">  expected reply
        /// </param>
        /// <returns>  reply object
        /// 
        /// </returns>
        public virtual FTPReply ValidateReply(FTPReply reply, string expectedReplyCode)
        {
            if (ValidateReplyCode(reply, expectedReplyCode))
                return reply;

            // got this far, not recognised
            throw new FTPException(reply);
        }
示例#24
0
        /// <summary>
        /// Request a data socket be created on the
        /// server, connect to it and return our
        /// connected socket.
        /// </summary>
        /// <returns>  connected data socket
        /// </returns>
        internal virtual FTPDataSocket CreateDataSocketPASV()
        {
            // PASSIVE command - tells the server to listen for
            // a connection attempt rather than initiating it
            FTPReply replyObj = SendCommand("PASV");

            ValidateReply(replyObj, "227");
            string reply = replyObj.ReplyText;

            // The reply to PASV is in the form:
            // 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
            // where h1..h4 are the IP address to connect and
            // p1,p2 the port number
            // Example:
            // 227 Entering Passive Mode (128,3,122,1,15,87).
            // NOTE: PASV command in IBM/Mainframe returns the string
            // 227 Entering Passive Mode 128,3,122,1,15,87	(missing
            // brackets)

            // extract the IP data string from between the brackets
            int startIP = reply.IndexOf((System.Char) '(');
            int endIP   = reply.IndexOf((System.Char) ')');

            // allow for IBM missing brackets around IP address
            if (startIP < 0 && endIP < 0)
            {
                startIP = reply.ToUpper().LastIndexOf("MODE") + 4;
                endIP   = reply.Length;
            }

            string ipData = reply.Substring(startIP + 1, (endIP) - (startIP + 1));

            int[] parts = new int[6];

            int           len       = ipData.Length;
            int           partCount = 0;
            StringBuilder buf       = new StringBuilder();

            // loop thru and examine each char
            for (int i = 0; i < len && partCount <= 6; i++)
            {
                char ch = ipData[i];
                if (System.Char.IsDigit(ch))
                {
                    buf.Append(ch);
                }
                else if (ch != ',')
                {
                    throw new FTPException("Malformed PASV reply: " + reply);
                }

                // get the part
                if (ch == ',' || i + 1 == len)
                {
                    // at end or at separator
                    try
                    {
                        parts[partCount++] = System.Int32.Parse(buf.ToString());
                        buf.Length         = 0;
                    }
                    catch (FormatException)
                    {
                        throw new FTPException("Malformed PASV reply: " + reply);
                    }
                }
            }

            // assemble the IP address
            // we try connecting, so we don't bother checking digits etc
            string ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3];

            // assemble the port number
            int port = (parts[4] << 8) + parts[5];

            // create the socket
            return(NewPassiveDataSocket(ipAddress, port));
        }
示例#25
0
        /// <summary>   Checks that the standard 220 reply is returned
        /// following the initiated connection
        /// </summary>
        internal void ValidateConnection()
        {
            FTPReply reply = ReadReply();

            ValidateReply(reply, "220");
        }
示例#26
0
		/// <summary>
		/// Get the size of a remote file. 
		/// </summary>
		/// <remarks>
		/// This is not a standard FTP command, it is defined in "Extensions to FTP", a draft RFC 
		/// (draft-ietf-ftpext-mlst-16.txt).
		/// </remarks>
		/// <param name="remoteFile">Name or path of remote file in current directory.</param>
		/// <returns>Size of file in bytes.</returns>
		public virtual long Size(string remoteFile)
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("SIZE " + remoteFile);
            lastValidReply = control.ValidateReply(reply, "213");
            
            // parse the reply string .
            string replyText = lastValidReply.ReplyText;
            
            // trim off any trailing characters after a space, e.g. webstar
            // responds to SIZE with 213 55564 bytes
            int spacePos = replyText.IndexOf((System.Char) ' ');
            if (spacePos >= 0)
                replyText = replyText.Substring(0, (spacePos) - (0));
            
            // parse the reply
            try
            {
                return Int64.Parse(replyText);
            }
            catch (FormatException)
            {
                throw new FTPException("Failed to parse reply: " + replyText);
            }
        }
示例#27
0
		/// <summary>Set the REST marker so that the next transfer doesn't start at the beginning of the remote file</summary>
		/// <remarks>
		/// Issue the RESTart command to the remote server. This indicates the byte
        /// position that REST is performed at. For put, bytes start at this point, while
        /// for get, bytes are fetched from this point.
		/// </remarks>
		/// <param name="size">the REST param, the mark at which the restart is performed on the remote file. 
		/// For STOR, this is retrieved by SIZE</param>
		/// <throws>SystemException </throws>
		/// <throws>FTPException </throws>
		public void Restart(long size)
        {
            FTPReply reply = control.SendCommand("REST " + size);
            lastValidReply = control.ValidateReply(reply, "350");
        }
示例#28
0
		/// <summary>Rename a file or directory.</summary>
		/// <param name="from">Name of file or directory to rename.</param>
		/// <param name="to">Intended name.</param>
		public virtual void Rename(string from, string to)
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("RNFR " + from);
            lastValidReply = control.ValidateReply(reply, "350");
            
            reply = control.SendCommand("RNTO " + to);
            lastValidReply = control.ValidateReply(reply, "250");
        }
示例#29
0
		/// <summary>Request the server to set up the put.</summary>
		/// <param name="remoteFile">Name of remote file in current directory.</param>
		/// <param name="append"><c>true</c> if appending, <c>false</c> otherwise.</param>
		private void InitPut(string remoteFile, bool append)
        {    
            CheckConnection(true);
            
            // reset the cancel flag
            cancelTransfer = false;
            
            bool close = false;
            data = null;
            try
            {
                resumeMarker = 0;

                // if resume is requested, we must obtain the size of the
                // remote file
                if (resume)
                {
                    if (transferType.Equals(FTPTransferType.ASCII))
                        throw new FTPException("Resume only supported for BINARY transfers");
                    try
                    {
                        resumeMarker = Size(remoteFile);
                    }
                    catch (FTPException ex)
                    {
                        resumeMarker = 0;
                        resume = false;
                        log.Warn("SIZE failed '" + remoteFile + "' - resume will not be used (" + ex.Message + ")");
                    }
                }

                // set up data channel
                data = control.CreateDataSocket(connectMode);
                data.Timeout = timeout;
                
                // issue REST
                if (resume)
                {
                    try
                    {
                        Restart(resumeMarker);
                    }
                    catch (FTPException ex)
                    {
                        resumeMarker = 0;
                        resume = false;
                        log.Warn("REST failed - resume will not be used (" + ex.Message + ")");
                    }
                }
                
                // send the command to store
                string cmd = append?"APPE ":"STOR ";
                FTPReply reply = control.SendCommand(cmd + remoteFile);
                
                // Can get a 125 or a 150, also allow 350 (for Global eXchange Services server)
                // JScape returns 151
                lastValidReply = control.ValidateReply(reply, "125", "150", "151", "350");
            }
            catch (SystemException)
            {
                close = true;
                throw;
            }
            catch (FTPException)
            {
                close = true;
                throw;
            }
            finally
            {
                if (close)
                {
                    resume = false;
                    resumeMarker = 0;
                    CloseDataSocket();
                }
            }
        }
示例#30
0
		/// <summary>Change the remote working directory to that supplied.</summary>
		/// <param name="dir">Name of remote directory to change to.</param>
		public virtual void ChDir(string dir)
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("CWD " + dir);
            lastValidReply = control.ValidateReply(reply, "200", "250");
        }
示例#31
0
		/// <summary>Run a site-specific command on the server.</summary>
		/// <remarks>
		/// Support for commands is dependent on the server.
		/// </remarks>
		/// <param name="command">The site command to run</param>
		/// <returns><c>true</c> if command ok, <c>false</c> if command not implemented.</returns>
		public virtual bool Site(string command)
        {            
            CheckConnection(true);
            
            // send the retrieve command
            FTPReply reply = control.SendCommand("SITE " + command);
            
            // Can get a 200 (ok) or 202 (not impl). Some
            // FTP servers return 502 (not impl)
            lastValidReply = control.ValidateReply(reply, "200", "202", "250", "502"); // 250 for leitch media server
            
            // return true or false? 200 is ok, 202/502 not
            // implemented
            if (reply.ReplyCode.Equals("200"))
                return true;
            else
                return false;
        }
示例#32
0
        /// <summary>  
        /// Validate the response the host has supplied against the
        /// expected reply. If we get an unexpected reply we throw an
        /// exception, setting the message to that returned by the
        /// FTP server
        /// </summary>
        /// <param name="reply">             the entire reply string we received
        /// </param>
        /// <param name="expectedReplyCode"> the reply we expected to receive
        /// 
        /// </param>
        internal virtual FTPReply ValidateReply(string reply, string expectedReplyCode)
        {
            FTPReply replyObj = new FTPReply(reply);

            if (ValidateReplyCode(replyObj, expectedReplyCode))
                return replyObj;

            // if unexpected reply, throw an exception
            throw new FTPException(replyObj);
        }
示例#33
0
		/// <summary>Delete the specified remote file.</summary>
		/// <param name="remoteFile">Name of remote file to delete.</param>
		public virtual void Delete(string remoteFile)
        {            
            CheckConnection(true);
            FTPReply reply = control.SendCommand("DELE " + remoteFile);
            lastValidReply = control.ValidateReply(reply, "200", "250");
        }
示例#34
0
		/// <summary>Get modification time for a remote file.</summary>
		/// <param name="remoteFile">Name of remote file.</param>
		/// <returns>Modification time of file as a <c>DateTime</c>.</returns>
		public virtual DateTime ModTime(string remoteFile)
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("MDTM " + remoteFile);
            lastValidReply = control.ValidateReply(reply, "213");
            
            // parse the reply string, which returns UTC
            DateTime ts = 
                DateTime.ParseExact(lastValidReply.ReplyText, modtimeFormats, 
                                    null, DateTimeStyles.None);
            
            // return the equivalent in local time
            return TimeZone.CurrentTimeZone.ToLocalTime(ts);
        }
示例#35
0
		/// <summary>Create the specified remote working directory.</summary>
		/// <param name="dir">Name of remote directory to create.</param>
		public virtual void MkDir(string dir)
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("MKD " + dir);
            
            // some servers return 200,257, technically incorrect but
            // we cater for it ...
            lastValidReply = control.ValidateReply(reply, "200", "250", "257");
        }
示例#36
0
		/// <summary>Get the current remote working directory.</summary>
		/// <returns>The current working directory.</returns>
		public virtual string Pwd()
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("PWD");
            lastValidReply = control.ValidateReply(reply, "257");
            
            // get the reply text and extract the dir
            // listed in quotes, if we can find it. Otherwise
            // just return the whole reply string
            string text = lastValidReply.ReplyText;
            int start = text.IndexOf((System.Char) '"');
            int end = text.LastIndexOf((System.Char) '"');
            if (start >= 0 && end > start)
                return text.Substring(start + 1, (end) - (start + 1));
            else
                return text;
        }
示例#37
0
		/// <summary>Change the remote working directory to the parent directory.</summary>
		public virtual void CdUp()
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("CDUP");
            lastValidReply = control.ValidateReply(reply, "200", "250");
        }
示例#38
0
		/// <summary>Get the type of the OS at the server.</summary>
		/// <returns>The type of server OS.</returns>
		public virtual string GetSystem()
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("SYST");
            lastValidReply = control.ValidateReply(reply, "200", "213", "215", "250"); // added 250 for leitch
            return lastValidReply.ReplyText;
        }
示例#39
0
        /// <summary>Sets the modification time of a remote file.</summary>
        /// <remarks>
        /// Although times are passed to the server with second precision, some
        /// servers may ignore seconds and only provide minute precision.  
        /// May not be supported by some FTP servers.
        /// </remarks>
        /// <param name="remoteFile">Name of remote file.</param>
        /// <param name="modTime">Desired modification-time to set in local time.</param>
        public virtual void SetModTime(string remoteFile, DateTime modTime)
        {
            CheckConnection(true);

            DateTime univTime = TimeZone.CurrentTimeZone.ToUniversalTime(modTime);
            string timeStr = univTime.ToString(DEFAULT_TIME_FORMAT);
            FTPReply reply = control.SendCommand("MFMT " + timeStr + " " + remoteFile);
            lastValidReply = control.ValidateReply(reply, "213");
        }
示例#40
0
		/// <summary>Login into an account on the FTP server using the user-name and password provided.</summary>
		/// <remarks>This
		/// call completes the entire login process. Note that
		/// <see cref="Connect()"/> must be called first.</remarks>
		/// <param name="user">User-name.</param>
		/// <param name="password">Password.</param>
		public virtual void Login(string user, string password)
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("USER " + user);
            
            // we allow for a site with no password - 230 and 232 (RFC4217) response
            lastValidReply = control.ValidateReply(reply, "230", "232", "331");
            if (lastValidReply.ReplyCode.Equals("230") || lastValidReply.ReplyCode.Equals("232"))
                return ;
            else
            {
                Password(password);
            }
        }
示例#41
0
		/// <summary>Get the server supplied features.</summary>
		/// <returns>
		/// <c>string</c>-array containing server features, or <c>null</c> if no features or not supported.
		/// </returns>
		public virtual string[] Features()
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("FEAT");
            lastValidReply = control.ValidateReply(reply, "211", "500", "502");
            if (lastValidReply.ReplyCode == "211")
            {
                string[] features = null;
                if (lastValidReply.ReplyData != null && lastValidReply.ReplyData.Length > 2)
                {
                    features = new string[lastValidReply.ReplyData.Length-2];
                    for (int i = 0; i < lastValidReply.ReplyData.Length-2; i++)
                        features[i] = lastValidReply.ReplyData[i+1].Trim();
                }
                else // no features but command supported
                {
                    features = new string[0];
                }
                return features;
            }
            else
                throw new FTPException(reply);
        }
示例#42
0
		/// <summary>
		/// Supply the user-name to log into an account on the FTP server. 
		/// Must be followed by the <see cref="Password(string)"/> method.
		/// Note that <see cref="Connect()"/> must be called first. 
		/// </summary>
		/// <param name="user">User-name.</param>
		public virtual void User(string user)
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("USER " + user);

            // we allow for a site with no password - 230 and 232 (RFC4217) response
            lastValidReply = control.ValidateReply(reply, "230", "232", "331");
        }
示例#43
0
 /// <summary>  
 /// Send a "no operation" message that does nothing, which can
 /// be called periodically to prevent the connection timing out.
 /// </summary>
 public void NoOperation()
 {
     CheckConnection(true);
     
     FTPReply reply = control.SendCommand("NOOP");
     lastValidReply = control.ValidateReply(reply, "200", "250"); // added 250 for leitch
 }
示例#44
0
		/// <summary>
		/// Supplies the password for a previously supplied
		/// user-name to log into the FTP server. Must be
		/// preceeded by the <see cref="User(string)"/> method
		/// </summary>
		/// <param name="password">Password.</param>
		public virtual void Password(string password)
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("PASS " + password);
            
            // we allow for a site with no passwords (202)
            try
            {
                lastValidReply = control.ValidateReply(reply, "230", "202", "332");
            }
            catch (FTPException ex)
            {
                throw new FTPAuthenticationException(ex.Message, ex.ReplyCode);
            }
        }
示例#45
0
		/// <summary>Abort the current action.</summary>
		/// <remarks>
		/// This does not close the FTP session.
		/// </remarks>
		protected virtual void Abort()
        {            
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("ABOR");
            lastValidReply = control.ValidateReply(reply, "426", "226");
        }
示例#46
0
        /// <summary>
        /// Supply account information string to the server. 
        /// </summary>
        /// <remarks>
        /// This can be used for a variety of purposes - for example, the server could
        /// indicate that a password has expired (by sending 332 in reply to
        /// PASS) and a new password automatically supplied via ACCT. It
        /// is up to the server how it uses this string.
        /// </remarks>
        /// <param name="accountInfo">account information</param>
        public virtual void Account(string accountInfo)
        {
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand("ACCT " + accountInfo);

            // ok or not implemented
            try
            {
                lastValidReply = control.ValidateReply(reply, "230", "202");
            }
            catch (FTPException ex)
            {
                throw new FTPAuthenticationException(ex.Message);
            }
        }
示例#47
0
 public FTPException(FTPReply reply) : base(reply.ReplyText, reply.ReplyCode)
 {
 }
示例#48
0
		/// <summary>Issue arbitrary ftp commands to the FTP server.</summary>
		/// <param name="command">FTP command to be sent to server.</param>
		/// <param name="validCodes">Valid return codes for this command.</param>
		/// <returns>The text returned by the FTP server.</returns>
		public virtual string Quote(string command, string[] validCodes)
        {        
            CheckConnection(true);
            
            FTPReply reply = control.SendCommand(command);
            
            // allow for no validation to be supplied
            if (validCodes != null && validCodes.Length>0)
            {
                lastValidReply = control.ValidateReply(reply, validCodes);
                
            }
            else // not doing any validation
            {
                lastValidReply = reply;
            }
            return lastValidReply.ReplyText;
        }