Channels ▼
RSS

Database

Synchronize Now!

Source Code Accompanies This Article. Download It Now.


FtpWebRequest

Although the S3 fees are not high, if you already have access to an FTP site, you may prefer to host your files there. But beware! Unless your FTP site is running over SSL, your FTP credentials (user ID and password) are transmitted over the Internet in plaintext, and can be intercepted and abused by bad guys. This vulnerability applies to every program that uses the FTP protocol, not just the sample app. You can see this vulnerability with Packetyzer, a freely available network analysis program (http://www.networkchemistry.com/products/packetyzer.php). Start a network capture in Packetyzer. Then use Synchronize Files to download a file from an FTP site. You'll see a trace like the following in Packetyzer:


 USER fredjones
 ..UR..331 Password required for fredjones.
 PASS fredspassword
 ...e..230 User fredjones logged in.
 

Bad guys monitoring packets on any of the machines through which the transfer travels will be able to capture your credentials. Scary! Although the sample app can't prevent this vulnerability, it encrypts your files before uploading them to the FTP site, and decrypts them only after they've been downloaded to your machine. Consequently, there's little risk that bad guys could decrypt your files by intercepting them during transfers, or by downloading them directly from your FTP site.

.NET 2.0 provides native FTP access with FtpWebRequest, but this class is little more than a thin wrapper over the FTP protocol. See FTPDataTransfer for examples of using the FtpWebRequest to synchronize files between the user's machine and an FTP site. FTPDataTransfer.GetFtpWebRequest (Listing One) returns an FtpWebRequest object. The KeepAlive property is set to False to ensure that the connection to the FTP server is closed after every FTP operation. If this isn't done, some FTP operations may fail, depending on the FTP command that was previously executed, and the server's FTP software. Although the KeepAlive = false setting allows arbitrary command sequences to succeed, creating a new FTP connection for each operation is slow. Furthermore, your FTP credentials will be sent to establish each new connection. GetFtpWebRequest includes a Method parameter that specifies the FTP operation that will be performed. There are several FTP operations including UploadFile, DownloadFile, DeleteFile, ListDirectory, and so on. Finally, the UseBinary property should be set to True. Otherwise, binary files will not be correctly transferred.

 ...
class FTPDataTransfer : DataTransfer
{
    ...
    private FtpWebRequest GetFtpWebRequest(string FTPAddress, string Method)
    {
        FtpWebRequest ftpWebRequest = null;
        try
        {
            ftpWebRequest = (FtpWebRequest)WebRequest.Create(FTPAddress);
            // Start a new FTP session.
            ftpWebRequest.KeepAlive   = false;
            // Data will be transferred in binary format.
            ftpWebRequest.UseBinary   = true;
            ftpWebRequest.Credentials = 
                           new NetworkCredential(userID, password);
            ftpWebRequest.Method      = Method;
        }
        catch (UriFormatException ex)
        {
            // Display error message if FTP address is invalid.
            MessageBox.Show(ex.Message, Application.ProductName, 
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        return ftpWebRequest;
    }
    ...
    protected override byte[] DownloadBuffer(string BucketName, 
                                             string FileName)
    {
        WebResponse response = null;
        // Convert bucket and filename into legal FTP folder and filenames.
        BucketName = EncodeName(BucketName);
        FileName   = EncodeName(FileName);

        byte[] result = null;

        try
        {
            string ftpAddress = ftpSite + "/" + ftpHomeDirectory + 


                                "/" + BucketName + "/" + FileName;
            FtpWebRequest 
                ftpWebRequest = GetFtpWebRequest(ftpAddress, 
                        WebRequestMethods.Ftp.DownloadFile);
            response = ftpWebRequest.GetResponse();
            // Prepare to read the file from the response stream.
            Stream responseStream = response.GetResponseStream();
            BinaryReader binaryReader = new BinaryReader(responseStream);
            const int bufferSize = 1024;
            byte[] buffer;
            List<byte> bufferList = new List<byte>();
            // Read the file, one buffer at a time.
            do
            {
                buffer = binaryReader.ReadBytes(bufferSize);

                if (buffer.Length > 0)
                {
                    bufferList.AddRange(buffer);
                }
            } while (buffer.Length == bufferSize);
            result = bufferList.ToArray();
            binaryReader.Close();
        }
        catch (WebException)
        {
            // A WebException will be thrown if file does not exist on server.
        }
        finally
        {
            if (response != null)
            {
                response.Close();
            }
        }

        return result;
    }
    ...
}
Listing One

FTPTransfer.DownloadBuffer calls GetFtpWebRequest to download a file's contents (Listing One). First the EncodeName method is called to convert the bucket name and file name into characters that FTP supports. Then GetFtpWebRequest is called with the FTP address of the file that will be downloaded, and the DownloadFile method. GetResponse is called to access the FtpWebRequest's response stream. The contents of the file are then read from the stream using a BinaryReader. After the stream is closed, the file's contents are returned. When a file is uploaded to an FTP site, its contents are written to the FtpWebRequest's request stream (see FTPTransfer.UploadBuffer for details).


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video