/// <summary> /// Create a data stream and send a raw command. /// </summary> /// <param name="rawCommand">The raw command to send.</param> /// <returns>The data stream that was created.</returns> public Stream CreateDataStreamAndSendCommand(String rawCommand) { // Send PASV command and read reply. FtpReply reply = SendCommandAndReadResponse("PASV"); // If not 'Entering PASV mode' response received; if (reply.ResultCode != 227) { // Throw exception. throw new FtpException(reply.Message); } // Get the ip end point from the response message. IPEndPoint endPoint = ParseDataEndPointFromMessage(reply.Message); // Create data socket and connect it. Socket dataSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); dataSocket.Connect(endPoint); // Send provided command and read reply. reply = SendCommandAndReadResponse(rawCommand); // If not in the 1xx range, throw exception. if (reply.ResultCode < 100 || reply.ResultCode > 199) { // throw exception. throw new FtpException(reply.Message); } // Return data stream. return(new NetworkStream(dataSocket, true)); }
/// <summary> /// Creates a remote directory in the current working folder. /// </summary> /// <param name="directoryName">Name of the directory.</param> /// <exception cref="FtpException">Occurs if there where connection problems during the process or the FTP server doesn't support the MMD command. See the Message of the exception for details.</exception> public void MakeDirectory(String directoryName) { // Send make directory command and read reply. FtpReply reply = SendCommandAndReadResponse("MKD", directoryName); // If not 'Pathname created', throw exception. if (reply.ResultCode != 257) { throw new FtpException(reply.Message); } }
/// <summary> /// Changes the working directory. /// </summary> /// <param name="remoteDirectory">The remote directory.</param> /// <exception cref="FtpException">Occurs if there where connection problems during the process or the FTP server doesn't support the CWD command. See the Message of the exception for details.</exception> /// <remarks>Sends the CWD command.</remarks> public void ChangeWorkingDirectory(String remoteDirectory) { // Send change working directory command and read reply. FtpReply reply = SendCommandAndReadResponse("CWD", remoteDirectory); // If no 'okay' reply received, throw exception. if (reply.ResultCode != 250) { throw new FtpException(reply.Message); } }
/// <summary> /// Change to the parent of the current working directory. /// </summary> /// <exception cref="FtpException">Occurs if there where connection problems during the process or the FTP server doesn't support the CDUP command. See the Message of the exception for details.</exception> /// <remarks>Sends the CDUP command.</remarks> public void CdUp() { // Send change directory up command and read reply. FtpReply reply = SendCommandAndReadResponse("CDUP"); // If no 'okay' reply received, throw exception. if (reply.ResultCode != 250) { throw new FtpException(reply.Message); } }
/// <summary> /// Connects this FTP server socket. /// </summary> /// <exception cref="FtpException">Thrown when unable to connect.</exception> public void Connect() { // Make sure the client is not connected. if (Connected) { Close(); } // Create socket to server. IPAddress serverAddress = null; _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { // Resolve server address from server host to connect. IPAddress[] serverAddresses = Dns.GetHostAddresses(ServerHost); serverAddress = serverAddresses[0]; } catch (SocketException caught) { String message = String.Format(Resources.CouldNotResolveServerHostName, ServerHost); CloseAndTrowException(new FtpException(message, caught)); } try { // Connect to endpoint. _clientSocket.Connect(serverAddress, Port); } catch (SecurityException caught) { CloseAndTrowException(new FtpException(Resources.CouldNotConnectToRemoteServer, caught)); } catch (SocketException caught) { CloseAndTrowException(new FtpException(Resources.CouldNotConnectToRemoteServer, caught)); } // Read first reply of the server. FtpReply reply = ReadResponse(); if (reply.ResultCode != 220) { // No OK message received, throw exception because this indicates an error. CloseAndTrowException(new FtpException(reply.Message)); } }
/// <summary> /// Stores the specified localFile. /// </summary> /// <param name="localFile">The localfile.</param> /// <param name="remoteFileName">The remotefile.</param> public void Store(String localFile, String remoteFileName) { // Make sure the file exists. if (!File.Exists(localFile)) { throw new FileNotFoundException("Couldn't find local file.", localFile); } // Create local file stream and data stream to remote server. using (FileStream localFileStream = File.OpenRead(localFile)) { // Send STOR command and create data stream. using (Stream remoteDataStream = CreateDataStreamAndSendCommand("STOR " + remoteFileName)) { // Create and buffer and read the first chunk of the local file. byte[] buffer = new byte[BufferSize]; int bytesReaded = localFileStream.Read(buffer, 0, buffer.Length); // While there a bytes readed from the local file. while (bytesReaded > 0) { // Write readed bytes to the remote data stream. remoteDataStream.Write(buffer, 0, bytesReaded); if (bytesReaded == buffer.Length) { // Read next available bytes from the local file. bytesReaded = localFileStream.Read(buffer, 0, buffer.Length); } else { // No more bytes available, so break. break; } } } } // Read response from the server. FtpReply reply = ReadResponse(); // If not 'Requested file action successful', throw exception. if (reply.ResultCode != 226) { throw new FtpException(reply.Message); } }
/// <summary> /// Determs whether a remote directory exists. /// </summary> /// <param name="remoteDirectory">The remote directory.</param> /// <remarks> /// This method is based on the succeedness of a CWD command, this can give wrong indication at a rare number of FTP server! /// </remarks> /// <exception cref="FtpException">Thrown if the opperation couldn't be executed.</exception> /// <returns><c>true</c> if the directory exists remotely; otherwise <c>false</c></returns> public bool DirectoryExists(String remoteDirectory) { bool exists = false; String workingDirectory = GetWorkingDirectory(); // Send change working directory command and read reply. FtpReply reply = SendCommandAndReadResponse("CWD", remoteDirectory); // If 'okay' if (reply.ResultCode == 250) { exists = true; ChangeWorkingDirectory(workingDirectory); } return(exists); }
/// <summary> /// Gets the working directory. /// </summary> /// <returns>The current working directory.</returns> public String GetWorkingDirectory() { FtpReply reply = SendCommandAndReadResponse("PWD"); if (reply.ResultCode != 257) { throw new FtpException(reply.Message); } Match directoryMath = Regex.Match(reply.Message, "\"(?<directory>[^\"]+)\""); if (!directoryMath.Success) { throw new FtpException("Couldn't find directory in response from server."); } return(directoryMath.Groups["directory"].Value); }
/// <summary> /// Login to the FTP server with the specified credentials. /// </summary> public void Login() { // Send user command and read reply. FtpReply reply = SendCommandAndReadResponse("USER", Username); // If 'login ok, password needed' result is received. if (reply.ResultCode == 331) { // Send password and read reply. reply = SendCommandAndReadResponse("PASS", Password); } // If not 'login ok' nor 'not implemented' is received, throw exception. if (reply.ResultCode != 230 && reply.ResultCode != 202) { CloseAndTrowException(new FtpException(reply.Message)); } }
/// <summary> /// Reads the ftp response from the client socket. /// </summary> /// <returns>The response of the FTP server.</returns> protected FtpReply ReadResponse() { // Read next available reply string from the client socket and // get the result code piece of the reply. String responseString = ReadResponseString(); String resultCodePiece = responseString.Substring(0, 3); // Parse result code and get message piece of the reply. Int32 resultCode = Int32.Parse(resultCodePiece); String message = responseString.Substring(4); // Create FTP reply and set last reply. FtpReply reply = new FtpReply(resultCode, message); _lastReply = reply; // Return result. return(reply); }
/// <summary> /// Determs whether a remote file exists. /// </summary> /// <param name="remoteFile">The remote file.</param> /// <returns></returns> /// <exception cref="FtpException">Occurs if there where connection problems during the operation or if the FTP server doesn't support the SIZE command. See the Message of the exception for details.</exception> public bool FileExists(String remoteFile) { // Send size command and read reply. FtpReply reply = SendCommandAndReadResponse("SIZE ", remoteFile); // 213, is the filesize reply. if (reply.ResultCode == 213) { return(true); } // 550, is the No such file reply. if (reply.ResultCode == 550) { return(false); } throw new FtpException(reply.Message); }
/// <summary> /// Sets the type of file to be transferred. /// </summary> /// <param name="mode">File transfer type: BINARY or ASCII</param> public void SetFileTransferType(String mode) { if (!mode.Equals("binary", StringComparison.InvariantCultureIgnoreCase) && !mode.Equals("ascii", StringComparison.InvariantCultureIgnoreCase)) { CloseAndTrowException(new FtpException("Set file transfer type accepts only following values: 'BINARY' or 'ASCII'.")); } String rawCommand = mode.Equals("binary", StringComparison.InvariantCultureIgnoreCase) ? "TYPE I" : "TYPE A"; // Send user command and read reply. FtpReply reply = SendCommandAndReadResponse(rawCommand); // If setting file transfer mode was not accepted. if (reply.ResultCode != 200) { CloseAndTrowException(new FtpException(reply.Message)); } }
/// <summary> /// Reads the ftp response from the client socket. /// </summary> /// <returns>The response of the FTP server.</returns> protected FtpReply ReadResponse() { // Read next available reply string from the client socket and // get the result code piece of the reply. String responseString = ReadResponseString(); String resultCodePiece = responseString.Substring( 0, 3 ); // Parse result code and get message piece of the reply. Int32 resultCode = Int32.Parse( resultCodePiece ); String message = responseString.Substring( 4 ); // Create FTP reply and set last reply. FtpReply reply = new FtpReply( resultCode, message ); _lastReply = reply; // Return result. return reply; }