public static string tftp_mode_to_string(ETransferMode m) { switch (m) { case ETransferMode.ASCII: { return("netascii"); }; case ETransferMode.BINARY: { return("octet"); }; } return("unknown"); }
/// <summary> /// Set the representation type according to the given parameter /// </summary> /// <param name="transferMode"></param> public void SetTransferMode(ETransferMode transferMode) { TypeCmd(transferMode == ETransferMode.ASCII ? ERepType.A : ERepType.I, null); this.transferMode = transferMode; }
/// <summary> /// Connects to a FTP server using the provided parameters. /// The default representation tipe is set to Binary. /// The text encoding is set to UTF8, if supported by the server via the FEAT command. /// </summary> /// <param name="hostname"></param> /// <param name="port"></param> /// <param name="credential"></param> /// <param name="sslSupportMode"></param> /// <param name="userValidateServerCertificate"></param> /// <param name="x509ClientCert"></param> /// <param name="sslMinKeyExchangeAlgStrength"></param> /// <param name="sslMinCipherAlgStrength"></param> /// <param name="sslMinHashAlgStrength"></param> /// <param name="timeout">Connection timeout in ms. <c>null</c> can be specifiad to keep the default value of 120s.</param> /// <param name="useCtrlEndPointAddressForData"><c>true</c> to use the control channel remote address for data connections instead of the address returned by PASV</param> /// <returns>The text of the \"welcome message\" sent by the server.</returns> public string Connect(string hostname, int port, NetworkCredential credential, ESSLSupportMode sslSupportMode, RemoteCertificateValidationCallback userValidateServerCertificate, X509Certificate x509ClientCert, int sslMinKeyExchangeAlgStrength, int sslMinCipherAlgStrength, int sslMinHashAlgStrength, int? timeout, bool useCtrlEndPointAddressForData) { Close(); // Anonymous authentication if (credential == null) credential = new NetworkCredential(anonUsername, anonPassword); if (timeout != null) this.timeout = timeout.Value; this.sslClientCert = x509ClientCert; this.userValidateServerCertificate = userValidateServerCertificate; this.sslMinKeyExchangeAlgStrength = sslMinKeyExchangeAlgStrength; this.sslMinCipherAlgStrength = sslMinCipherAlgStrength; this.sslMinHashAlgStrength = sslMinHashAlgStrength; this.sslSupportRequestedMode = sslSupportMode; this.sslSupportCurrentMode = sslSupportMode; this.useCtrlEndPointAddressForData = useCtrlEndPointAddressForData; sslInfo = null; features = null; transferMode = ETransferMode.ASCII; textEncoding = ETextEncoding.ASCII; bannerMessage = null; welcomeMessage = null; currDirStack.Clear(); // Ok, member initialization is done. Start with setting up a control connection SetupCtrlConnection(hostname, port, Encoding.ASCII); // Used later for SSL/TLS auth this.hostname = hostname; // Implicit SSL/TLS bool isImplicitSsl = (sslSupportMode & ESSLSupportMode.Implicit) == ESSLSupportMode.Implicit; if (isImplicitSsl) SwitchCtrlToSSLMode(); // Wait fot server message bannerMessage = GetReply().Message; // Explicit SSL/TLS if (!isImplicitSsl) SslControlChannelCheckExplicitEncryptionRequest(sslSupportMode); // Login. Note that a password might not be required // TODO: check if the welcomeMessage is returned by the USER command in case the PASS command is not required. if(UserCmd(credential.UserName)) welcomeMessage = PassCmd(credential.Password); GetFeaturesFromServer(); if (IsControlChannelEncrypted && !isImplicitSsl) { SslDataChannelCheckExplicitEncryptionRequest(); if ((sslSupportMode & ESSLSupportMode.ControlChannelRequested) != ESSLSupportMode.ControlChannelRequested) SSlCtrlChannelCheckRevertToClearText(); } try { // This is required by some FTP servers and must precede any OPTS command if (CheckFeature("CLNT")) ClntCmd(clntName); // Set UTF8 as character encoding, but only if listed among the FEAT features if (CheckFeature("UTF8")) SetTextEncoding(ETextEncoding.UTF8); } catch (Exception ex) { //TODO: add warning info } // Default binary transfers SetTransferMode(ETransferMode.Binary); return welcomeMessage; }
// functions public CTFTPMessageInWriteRequest(byte[] buffer, int buffer_length) { // init vars this.m_options = new Dictionary <string, string>(); this.m_filename = ""; this.m_mode = ETransferMode.UNDEFINED; this.m_block_size = 512; this.m_total_size = 0; this.m_timeout_in_secs = 5; // index into the buffer array and temp string for working int buffer_index = 0; string temp_string = ""; // opcode has already been extracted in main receive function which is how we got here // in the first place, no need to duplicate effor buffer_index += 2; // get the filename while (buffer[buffer_index] != 0) { this.m_filename += Encoding.ASCII.GetString(buffer, buffer_index, 1); ++buffer_index; } // get past the terminating 0 ++buffer_index; // get the mode while (buffer[buffer_index] != 0) { temp_string += Encoding.ASCII.GetString(buffer, buffer_index, 1); ++buffer_index; } // get past the terminating 0 ++buffer_index; this.m_mode = Utilities.string_to_tftp_mode(temp_string); // start pulling out options while (buffer_index < buffer_length) { // extract option string string option = ""; while (buffer[buffer_index] != 0) { option += Encoding.ASCII.GetString(buffer, buffer_index, 1); ++buffer_index; } // get past the terminating 0 ++buffer_index; // get the value string value = ""; while (buffer[buffer_index] != 0) { value += Encoding.ASCII.GetString(buffer, buffer_index, 1); ++buffer_index; } // get past the terminating 0 ++buffer_index; // save the options this.m_options[option] = value; // check which option switch (option) { case "blksize": { this.m_block_size = Convert.ToUInt16(value); } break; case "tsize": { this.m_total_size = Convert.ToUInt32(value); } break; case "timeout": { this.m_timeout_in_secs = Convert.ToUInt16(value); } break; case "windowsize": { this.m_window_size = Convert.ToUInt16(value); } break; case "outoforder": { if (value == "1") { this.m_out_of_order = true; } else { this.m_out_of_order = false; } } break; } } }
// functions public CTFTPMessageOutReadRequest(string filename, ETransferMode mode, ushort block_size, ushort timeout_in_secs, uint tsize, ushort windowsize, bool out_of_order) { // save the passed variables this.m_filename = filename; this.m_mode = mode; this.m_block_size = block_size; this.m_total_size = tsize; this.m_timeout_in_secs = timeout_in_secs; this.m_window_size = windowsize; this.m_out_of_order = out_of_order; // allocate the buffer space...estimate the size needed based on length of the filename // plus room for opcode, mode, blocksize, timeout, extra padding // since this is a one time packet we can "over pad" it without much detriment // the actual final length will be calculated at the end to store in m_buffer_length this.m_buffer = new byte[filename.Length + 256]; // create the buffer for this message and put all the data in it int buffer_index = 0; string temp = ""; // set the opcode ushort opcode = Utilities.htons((ushort)(this.Opcode)); Array.Copy(BitConverter.GetBytes(opcode), 0, this.m_buffer, buffer_index, 2); buffer_index += 2; // set the filename Array.Copy(Encoding.ASCII.GetBytes(this.m_filename), 0, this.m_buffer, buffer_index, this.m_filename.Length); buffer_index += filename.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // set the mode temp = Utilities.tftp_mode_to_string(mode); Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // terminate it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // set a block size // the string blksize temp = "blksize"; Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // now the value temp = block_size.ToString(); Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // tsize option temp = "tsize"; Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // now the value temp = this.m_total_size.ToString(); Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // timeout value temp = "timeout"; Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // now the value temp = timeout_in_secs.ToString(); Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // windowsize value temp = "windowsize"; Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // now the value temp = this.m_window_size.ToString(); Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // buckets value temp = "outoforder"; Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // now the value if (out_of_order == true) { temp = "1"; } else { temp = "0"; } Array.Copy(Encoding.ASCII.GetBytes(temp), 0, this.m_buffer, buffer_index, temp.Length); buffer_index += temp.Length; // termiante it with 0 this.m_buffer[buffer_index] = 0; buffer_index += 1; // now save the buffer length this.m_buffer_length = buffer_index; }
/// <summary> /// Set the representation type according to the given parameter /// </summary> /// <param name="transferMode"></param> public void SetTransferMode(ETransferMode transferMode) { TypeCmd(transferMode == ETransferMode.Ascii ? ERepType.A : ERepType.I, null); _transferMode = transferMode; }