[C#/WPF] FTP Browser (Beta)

One of my longer term goals is to create a small FTP Upload program that allows me to upload files and, more importantly, integrate FTP functionality into existing programs I write. As a step in that direction, I created a simple FTP Browser that allows you to navigate through your FTP folders:


You can run the above application by clicking here: [U]http://www.kirupafx.com/FTPBrowser/publish.htm[/U] (no installation this time!)

The source code is posted (and attached) below:

using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Windows.Input;
namespace FTPBrowser
{
    //
    // The FTPFolder class allows you to store as well as quickly
    // access a folder's name and path.
    //
    public class FTPFolder
    {
        private string folderPath;
        private string folderName;
        public FTPFolder(string folderPath, string folderName)
        {
            this.folderPath = folderPath;
            this.folderName = folderName;
        }
        public string GetName()
        {
            return folderName;
        }
        public string GetPath()
        {
            return folderPath;
        }
    }
    public partial class Window1
    {
        public Window1()
        {
            this.InitializeComponent();
        }
        //Variables for storing server related information
        private string userName;
        private string passWord;
        public string startingPath;
        //Our FtpWebRequest object
        FtpWebRequest request;
        //
        //Various dictionaries for creating mappings between folders, treeitems, and dockpanels
        //
        private Dictionary<string, TreeViewItem> folderNameToTreeItem = new Dictionary<string, TreeViewItem>();
        private Dictionary<string, TreeViewItem> seekAheadList = new Dictionary<string, TreeViewItem>();
        private Dictionary<TreeViewItem, string> treeItemToFolderName = new Dictionary<TreeViewItem, string>();
        private Dictionary<string, string> namePathDictionary = new Dictionary<string, string>();
        private Dictionary<DockPanel, string> dockPanelContent = new Dictionary<DockPanel, string>();
        //
        // Returns a folder name and strips out any folders with an extension (aka files)
        //
        private string ParseLine(string line, string path)
        {
            string[] parsedLine = line.Split('/');
            string temp;
            if (parsedLine.Length > 1)
            {
                temp = path + "/" + parsedLine[1];
                if (parsedLine[1].Contains("."))
                {
                    return "ERROR";
                }
            }
            else
            {
                temp = path + "/" + parsedLine[0];
                if (parsedLine[0].Contains("."))
                {
                    return "ERROR";
                }
            }
            return temp;
        }
        //
        // Initializes the application
        //
        private void SetupFTP()
        {
            startingPath = ftpBox.Text;
            userName = userNameBox.Text;
            passWord = passwordBox.Password;
            request = (FtpWebRequest)WebRequest.Create(startingPath);
            SetupTree();
        }
        //
        // Returns the folder name without having any path information
        //
        private string SafeFolderName(string path)
        {
            string[] fileParts = path.Split('/');
            return fileParts[fileParts.Length - 1];
        }
        //
        // Responsible for initially drawing the tree
        //
        private void SetupTree()
        {
            TreeViewItem tv = new TreeViewItem();
            DockPanel dock = new DockPanel();
            dock.MouseUp += new MouseButtonEventHandler(TreeViewMouseDown);
            TextBlock textContent = new TextBlock();
            textContent.Text = startingPath;
            dock.Children.Add(GetImage(true));
            dock.Children.Add(textContent);
            dockPanelContent.Add(dock, startingPath);
            tv.Header = dock;
            treeFolderBrowser.Items.Add(tv);
            folderNameToTreeItem.Add(startingPath, tv);
            treeItemToFolderName.Add(tv, startingPath);
            FTPFolder folder = new FTPFolder(startingPath, SafeFolderName(startingPath));
            DrawChildTreeItems(tv, folder, true);
        }
        //
        // Returns an image used by the TreeViewItem to designate a visited Node
        //
        private Image GetImage(bool expanded)
        {
            Image imageContent = new Image();
            string imagePath;
            if (expanded)
            {
                imagePath = "pack://application:,,,/folder_images.gif";
            }
            else
            {
                imagePath = "pack://application:,,,/icon_info.gif";
            }
            imageContent.Source = new BitmapImage(new Uri(imagePath));
            return imageContent;
        }
        //
        // Given a parent TreeViewItem, FTPFolder, and an expand flag, draws the children folders
        // in your directory structure
        //
        private void DrawChildTreeItems(TreeViewItem parentTree, FTPFolder folder, bool expand)
        {
            List<string> childPaths = GetDirectories(folder.GetPath());
            List<TreeViewItem> treeViewItemList = new List<TreeViewItem>();
            foreach (string t in childPaths)
            {
                if (folderNameToTreeItem.ContainsKey(t))
                {
                    continue;
                }
                else
                {
                    TreeViewItem tv = new TreeViewItem();
                    FTPFolder newFolder = new FTPFolder(t, SafeFolderName(t));
                    DockPanel dock = new DockPanel();
                    dock.MouseUp += new MouseButtonEventHandler(TreeViewMouseDown);
                    TextBlock textContent = new TextBlock();
                    textContent.Text = newFolder.GetName();
                    dock.Children.Add(GetImage(false));
                    dock.Children.Add(textContent);
                    dockPanelContent.Add(dock, newFolder.GetPath());
                    treeViewItemList.Add(tv);

                    tv.Header = dock;
                    parentTree.Items.Add(tv);
                    folderNameToTreeItem.Add(t, tv);
                    treeItemToFolderName.Add(tv, t);
                    if (expand)
                    {
                        parentTree.IsExpanded = true;
                    }
                    else
                    {
                        parentTree.IsExpanded = false;
                    }
                }
            }
        }
        //
        // Our event handler for reacting to mousedown events
        //
        private void TreeViewMouseDown(object sender, MouseButtonEventArgs e)
        {
            DockPanel clickedDock = (DockPanel)sender;
            clickedDock.Children.RemoveAt(0);
            clickedDock.Children.Insert(0, GetImage(true));
            string clickedText = dockPanelContent[clickedDock];
            FTPFolder clickedFolder = new FTPFolder(clickedText, SafeFolderName(clickedText));
            DrawChildTreeItems(folderNameToTreeItem[clickedText], clickedFolder, true);
        }
        //
        // Connects to the server and returns a list of directories located at the
        // given path.
        //
        private List<string> GetDirectories(string path)
        {
            request = (FtpWebRequest)WebRequest.Create(path);
            request.Credentials = new NetworkCredential(userName, passWord);
            request.Method = WebRequestMethods.Ftp.ListDirectory;
            List<string> dir = new List<string>();
            try
            {
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream());
                string line = reader.ReadLine();
                while (line != null)
                {
                    string newPath = ParseLine(line, path);
                    if (newPath != "ERROR")
                    {
                        dir.Add(newPath);
                    }
                    line = reader.ReadLine();
                }
            }
            catch (WebException e)
            {
                // Do something interesting.
            }
            return dir;
        }
        private void ConnectClick(object sender, RoutedEventArgs e)
        {
            SetupFTP();
        }
    }
}

This program is very buggy in that if you try to re-enter your server information and press Connect multiple times, the program will crash :stuck_out_tongue:

Cheers!
Kirupa :beam: