Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Advanced FTP Server

4.78/5 (26 votes)
24 Oct 2009CPOL7 min read 134.3K   20.2K  
Enables remote access to your files and folders via FTP

Introduction

I always come across situations like I will be outside home and I may need some files or reference materials from my system. So I can ask any body at home to switch on the system through a call. Now the FTP server starts and I will be able to access my files and folders from anywhere. This FTP server is designed using C# .NET which enables full control over the application from remote locations.

Unique Feature

Their are lots of FTP server applications that are available free of cost. But those applications do not provide the facility to control the server remotely and some provide this facility by installing the required software in the remote machine which may not be possible all the times. But this provides a simple, user friendly web interface, where you can connect from a remote machine through a browser. This enables control over the application from remote machines. You can add new Users by setting their root paths remotely. This enables to allow others to use your system with restrictions for certain actions and specific path.

Concept/Code Behind AdvancedFTPServer

As soon windows starts up, a service named AdvFtpSvr starts and it executes FTP Server.exe from the installed path. Once the application is started, the process ends by itself as there is no work to do with the process. Here you may ask why use a Windows Service as the application can be started directly? The reason is the Windows service starts as soon as Windows is started and any process started by a Windows service has full access over the system which enables access to all the files and folders. There is an another way which we can use instead of Windows service which is Windows Scheduled task, but the disadvantage with this is that the scheduled task might had been disabled in some systems and is not the fully automated way of doing things.

Let us first see some of the basic and interesting methods. Most of us know that for FTP server programming, we need to listen on some ports (21) using a listener class. Generally when a listener is started, the firewall installed in the system blocks the application from receiving any incoming connections. So, for the application to work properly, the firewall must be configured to add an exception to the application. Adding exception to the firewall had been automated with the custom action in the installer.

A method from InstallerService.cs is as follows:

C#
void AddToFirewallException(string ApplicationName, string FilePath)
{
    // Add exception to windows firewall after installation
    string RegPath =
        @"SYSTEM\ControlSet001\Services\SharedAccess\Parameters\
		FirewallPolicy\StandardProfile\AuthorizedApplications\List";
    string KeyValue = FilePath + ":*:Enabled:" + ApplicationName;

    RegistryKey Key = Registry.LocalMachine.OpenSubKey(RegPath, true);
    Key.SetValue(FilePath, KeyValue);
    Key.Close();
    Key = null;
}

The above method takes two string params, (i.e. ApplicationName which is displayed in the exceptions list of the Windows firewall and FilePath which is the physical path to the executable).

The settings file (Settings.DAT) is just an encrypted XML file. Both the encryption and decryption are done using a single method described below.

A method from ApplicationSettings class in Settings.cs - A class which stores all the application settings in static methods and properties.

C#
static byte[] Crypt(byte[] Buffer)
{
    for (int i = 0; i < Buffer.Length; i++)
    {
        Buffer[i] ^= 36;
    }
    return Buffer;
}

The above method takes a byte array as input parameter and then processes each byte and then finally returns the encrypted byte array back. This method uses a very silly way of encrypting data but it is more than enough to protect a file from manual access.

Their are lot such petty interesting methods implemented in the application.

Let us now get deep into the implementation. As soon as the application starts first of all, the "Settings.dat" will be decrypted and loaded into memory. Then according to the settings, the FTP and HTTP listener will be started. Once the listener is started, it's now ready to serve the client's request.

First we shall discuss a little bit about FTP implementation.

There are three classes for the FTP server which are:

  • FTPServer in FTPServer.cs - This is the class which holds the listener.
  • FTPClient in FTPClient.cs - This is the class which holds all the methods required to service the FTP client.
  • FTPUser in FTPUser.cs - This is the class which holds the permission settings of all the users.

Now let us discuss about the methods in FTPServer class.

  • Start - This is the method which starts the listener to listen to the specified port for clients and fires the NewFTPClientArrived method whenever a new client arrives.
  • Stop - Stops the listener class from listening to the clients
  • NewFTPClientArrived - This is fired automatically whenever the new client is arrived. This creates a new object of the FTPClient class and stores the object in a local array list.

That's all with the FTPServer class. Let us now start with the methods in FTPClient class.

As soon as the object for the FTPClient class is created in the FTPServer class, it listens for the commands from the clients. There is a huge list of predefined commands for the FTP implementation. View the reference section at the bottom of this article for the links which describe each method and its implementation. Once the client sends the user name and password, the CommandReceived method checks for the username and password in the list and creates an object for the FTPUser class which holds all the rights information of the specific user. That's all to deal with the FTP implementation classes.

Let us now have a small discussion with the ApplicationLog class.

ApplicationLog class is a simple class holding a single static method named Write. This is used to write the application error events into the XML file for bug fixing purposes and for tracking some application changes. This write method is called throughout the project from inside a catch block passing the exception caught over there.

Finally let us have a short discussion on the HTTP implementation classes and then move on with a guide to use the application. The HTTP implementation class is the same as that of the FTP implementation class whereas all the commands used are not pre-defined and were defined by me. Unlink FTP classes instead of dealing with files and folders. This just deals with HTML codes, which is sent as response to each of the commands. All the pages for response are stored in the resource section of the application and are requested whenever needed.

A method from HTTPClient class is given below:

C#
void SendData(byte[] ResponseBody)
{
    if (ClientSocket.Connected)
        ClientSocket.Send(ResponseBody, ResponseBody.Length, SocketFlags.None);
}

The above method sends the response to the clients in byte array.

C#
void SendHeader(int TotalBytes, string StatusCode, string ContentType)
{
    string ResponseHeader = HttpVersion + " " + StatusCode + "\r\n";
    ResponseHeader += "Server: AdvancedFTPServer/2.5\r\n";
    ResponseHeader += "Date: " + DateTime.Now.ToString("r") + "\r\n";
    ResponseHeader += "Content-Type: " + ContentType + "\r\n";
    ResponseHeader += "Accept-Ranges: bytes\r\n";
    ResponseHeader += "Content-Length: " + TotalBytes + "\r\n\r\n";

    SendData(Encoding.ASCII.GetBytes(ResponseHeader));
}

This method sends the client a response header and once the response header is sent, the following bytes must contain the response body (i.e., HTML code). Response body can be sent using the same SendData method which takes a byte array as a parameter.

Now we are done with all the major classes and methods, and let us move on.

Using the Setup

First download and install the Setup from the link provided above, then restart your system. You will find a new icon in your system tray. Right click on the Tray Icon to display the context menu options as shown below. I have added the screen shots of the application. The code is self explanatory and I don't find much time to explain the features or code in detail. The default User Name and Password for the web authentication is "admin" and "admin" and the default port for the HTTP server is 9090. To connect to the web interface from the local system, just click on the Open HTTP menu from the context menu shown below.

Context Menu

Image 1

User Account Screen

Image 2

Add/Edit User Screen

Image 3

Web Interface

Image 4

For more help, just click on the help menu in the above screen after authenticating with the User Name and Password (default is "admin" and "admin").

Reference: List of raw FTP commands

Other Supportive Tools

When you use this from remote locations, you require an External IP Address. In case your External IP is generated dynamically, then you need an automated system to intimate your IP instantly. I use IPMon for this purpose.

Note

  • After the installation of the setup, the system needs to be restarted for the application to work properly.
  • The setup link provided above also installs a service as the server must be started as soon as Windows starts.
  • The installer automatically adds an exception for the application in Windows Firewall. If you had installed any other firewall, you need to manually add an exception or add to allowed/trusted list of the firewall for the application to work properly.
  • All the settings are stored in DAT file with the simple encryption, restricting people from manually viewing the information.

Points of Interest

This source code also contains:

  • A code piece for adding firewall exception
  • Developing Windows Services using C#
  • Deploying Windows Service using MSI
  • Adding Custom actions to MSI
  • A simple way of encryption

History

  • October 24, 2009 - Missing Resource file [Settings.xml] has been added

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)