WebOpenFileDialog

0
40

Table of Contents

 

The symbol Table of Contents returns the reader to the top of the Table of Contents.

1. Abstract Table of Contents

This short article presents a class that provides a user with the ability to choose a file from a list of files found at a web URL. It also allows the traversal of the directory structure of a web site.

2. Background Table of Contents

During a recent project, I found that I needed the functionality of OpenFileDialog [^], but for web directories. In searching the web, I found some tools that would perform this function, but none that I could drop into an application, especially an application developed with the .Net Framework Version 3.5.

Because it appeared that the resuling tool might have usefulness outside my original project, I present it here.

A note on typography

In the following discussions, properties that are specified by the developer are displayed in

  • bold black
  • bold red are required
  • red are required under some circumstances

Variables, used internally by the software are displayed in italicized text.

3. WebOpenFileDialog Table of Contents

WebOpenFileDialog is a tool that is derived from the .NET Form [^] class and provides the ability to select a file from files on a web site. It incororates its own GUI that, once successfully initialized, allows a user to select a node from a TreeView [^], and indicate (through the OK button) that the selected node is the file of choice.

3.1. Properties Table of Contents

The following properties may be specified.

Property Get/Set Default Description
Anonymous_FTP Set false If true, causes an attempt to establish an anonymous FTP connection; otherwise, a User_Name and Password must be supplied
File_Name Get None If, upon return, the return value is DialogResult.OK, contains the fully qualified file name of the file chosen by the user; otherwise, if, upon return, the return value is DialogResult.Cancel, contains an empty string.
FTP_URL Set None URL of the FTP web site from which the initial directory source will be retrieved (i.e., the topmost directory whose listing is to be retrieved). Akin to “InitialDirectory” in OpenFileDialog. The supplied value must adhere to the FTP schema (i.e., it must begin with either ‘ftp://’ or ‘ftps://’).
Pass_Word Set None The FTP password for the site specified in FTP_URL. If Anonymous_FTP is true, this property may be the empty string or the anonymous FTP password for the site. If Anonymous_FTP is false, the FTP password for the site must be supplied.
Perform_Ping Set true If true, causes an attempt to establish a connection with the web site using Ping; otherwise, no Ping is executed.
Show_Hidden Set false If true, the directory entries that begin with a period will be displayed; otherwise, directory entries that begin with a period will be ignored.
User_Name Set None The FTP username for the site specified in FTP_URL. If Anonymous_FTP is true, this property may be the empty string or the anonymous FTP username for the site. If Anonymous_FTP is false, the FTP username for the site must be supplied.
Window_Title Set None A title to appear in the title area of the dialog. If not supplied, the title “Web Open File Dialog” will be used.

3.2. Invocation Table of Contents

using System;
using System.Text;
using System.Windows.Forms;

using WOFD = WebOpenFileDialog.WebOpenFileDialog;
:
:
 WOFD wofd = new WOFD 
 {
 Anonymous_FTP = <(true|false)>,
 FTP_URL = <URL of the FTP web site topmost node>,
 User_Name = <username for the FTP web site>,
 Pass_Word = <password for the FTP web site>,
 Perform_Ping = <(true|false)>,
 Show_Hidden = <(true|false)>,
 Window_Title = <title for the WebOpenFileDialog form>
 };

 if ( wofd.ShowDialog ( ) == DialogResult.OK )
 {
 filename_TextBox.Text = wofd.File_Name;
 }

4. Implementation Table of Contents

4.1. directories_and_files_to_treeview Table of Contents

The method that actually retrieves and expands FTP directory listings is called directories_and_files_to_treeview. Its signature is

bool directories_and_files_to_treeview ( 
 string ftp_url, 
 NetworkCredential credential,
 ref TreeView tree_view, 
 ref string error_message )

Prior to processing ftp_url, the method determines if ftp_url is the root node of an existing TreeView. If it is, a new TreeNode [^] is created; otherwise a search is made for the node with the name ftp_url. Either case establishes the root note for the current invocation of directories_and_files_to_treeview.

ftp_url = ftp_url.Replace ( @"\", "/" ); if ( tree_view.Nodes.Count == 0 ) { tree_node = new TreeNode ( ftp_url ) { Tag = "DIR" }; tree_view.Nodes.Add ( tree_node ); root_node = tree_view.Nodes [ 0 ]; }
else { root_node = find_tree_node ( tree_view.Nodes [ 0 ], ftp_url ) ; if ( root_node == null ) { error_message = String.Format ( "Unable to locate {0}\n" + "in existing directory tree", ftp_url ); successful = false; return ( successful ); } }

Note that at each invocation of directories_and_files_to_treeview, only the current directory (specified in ftp_url) will be processed. Multiple invocations are required to traverse the directory tree below ftp_url. This restriction is imposed so that a large amount of network traffic is avoided based on the assumption that only a limited number of subdirectories need to be visited.

Retrieving a web site directory is accomplished by using the FtpWebRequest [^] class returned by WebRequest.Create [^] cast to a FtpWebRequest. To obtain a directory of files at a web site, the request Method is set to WebRequestMethods.Ftp.ListDirectoryDetails [^]. This protocol retrieves a detailed listing of the files on an FTP server. The initializing code may take on the following appearance:

FtpWebRequest request; ftp_uri = new Uri ( ftp_url ); request = ( FtpWebRequest ) WebRequest.Create ( ftp_uri );
request.Credentials = credential; request.Method = WebRequestMethods. Ftp.ListDirectoryDetails;
using ( WebResponse response = request. GetResponse ( ) ) { using ( StreamReader stream_reader = new StreamReader ( response. GetResponseStream ( ) ) ) { while ( stream_reader.Peek ( ) > 0 ) { string line = stream_reader.ReadLine ( ); : :

The directory list is composed of lines whose first character distinguishes one entry type from another. Unix file types [^] describes the types of files found in the Unix operating system. An example of a directory listing is:

drwx--x--x 24 amvetspost amvetspost 4096 May 1 09:31 ..
drwx------ 2 amvetspost amvetspost 4096 Jul 14 2016 .HttpRequest
drwx------ 4 amvetspost amvetspost 4096 Jul 14 2016 .MirrorSearch
-rw-r--r-- 1 amvetspost amvetspost 100 May 22 2016 .bash_logout
-rw-r--r-- 1 amvetspost amvetspost 230 May 22 2016 .bash_profile
-rw-r--r-- 1 amvetspost amvetspost 176 Jul 27 2015 .bash_profile.rpmnew
-rw-r--r-- 1 amvetspost amvetspost 124 Sep 22 2015 .bashrc
drwxrwx--x 5 amvetspost amvetspost 4096 Jul 14 2016 .cagefs
drwxr-xr-x 2 amvetspost amvetspost 4096 Apr 26 15:17 .cl.selector
-rw------- 1 amvetspost amvetspost 0 Jul 10 2016 .contactemail
drwxr-xr-x 3 amvetspost amvetspost 4096 Jul 14 2016 .cpan
drwx------ 5 amvetspost amvetspost 4096 Apr 29 08:36 .cpanel
drwx------ 3 amvetspost amvetspost 4096 Jul 14 2016 .cpcpan
drwx------ 4 amvetspost amvetspost 4096 Aug 17 2016 .cphorde
drwx------ 4 amvetspost amvetspost 4096 Jul 14 2016 .cpobjcache
-rw-r--r-- 1 amvetspost amvetspost 145 Jul 10 2016 .gemrc
drwxr-x--- 2 amvetspost 99 4096 Jul 10 2016 .htpasswds
-rw------- 1 amvetspost amvetspost 650 Apr 29 08:36 .lastlogin
-rw-r--r-- 1 amvetspost amvetspost 33 May 22 2016 .md5sum
drwxr-xr-x 2 0 0 4096 Jun 19 12:03 .mysql_backup
drwx------ 2 amvetspost amvetspost 4096 Apr 26 15:58 .subaccounts
drwx------ 2 amvetspost amvetspost 4096 Jul 15 2016 .trash
-rw-r--r-- 1 amvetspost amvetspost 658 Mar 25 2016 .zshrc
drwxr-xr-x 2 amvetspost amvetspost 4096 Jun 13 08:51 AmVetsData
lrwxrwxrwx 1 amvetspost amvetspost 39 Jul 10 2016 access-logs -> /usr/local/apache/domlogs/amvetspost292
drwxr-xr-x 2 amvetspost amvetspost 4096 Aug 17 2016 cache
drwxr-x--- 2 amvetspost 12 4096 Jul 10 2016 etc
drwx------ 2 amvetspost amvetspost 4096 Jun 14 05:20 logs
drwxr-x--- 8 amvetspost amvetspost 4096 Jul 14 2016 mail

The first character of each line determines if it will be processed. For our purposes, only files, whose first character is the hyphen (-), and directories, whose first character is the lowercase letter ‘d’, will be retained. All others will be ignored.

If the directory entry name (last column in the directory listing) starts with a period, the entry is considered to be a “hidden” entry. Unless the Show_Hidden property is set true, hidden entries will be ignored. If the first character of a directory listing line is ‘d’ and the directory entry name ends with a period, then the entry will be ignored. This latter case eliminates the directories ‘.’ (current directory) and ‘..’ (parent directory).

With these first character definitions, the code takes on the following form:

char first_ch = ( char ) 0;
int index = 0;
string name = String.Empty;
string type = String.Empty; first_ch = line [ 0 ];
if ( first_ch == 'd' ) { if ( line.EndsWith ( "." ) ) { continue; } type = "DIR"; }
else if ( first_ch == '-' ) { type = "FILE"; }
else { continue; } index = line.LastIndexOf ( ' ' );
if ( index < 0 ) { continue; } name = line.Substring ( index ).Trim ( );
if ( name.StartsWith ( "." ) ) { if ( !Show_Hidden ) { continue; } } tree_node = new TreeNode ( name ) { Tag = type };
if ( type.Equals ( "DIR" ) ) { tree_node.Nodes.Add ( new TreeNode ( "EMPTY" ) { Tag = "EMPTY" } ); } root_node.Nodes.Add ( tree_node );
}

Each non-ignored directory entry name in the directory listing is assigned to a TreeNode with a type of either “DIR” or “FILE” stored in its Tag. If a new directory node (DIR) is being added, it is given a child node of type “EMPTY” before being added to the TreeView. This empty node causes the TreeView control to place a plus sign (+) before the node, thereby implying that a subtree exists. Note that the expansion of a TreeNode only occurs when that TreeNode is processed as a root (i.e., passed as ftp_url during an invocation of directories_and_files_to_treeview).

4.2. find_tree_node Table of Contents

Of interest may be the TreeNode search method. Its contents are:

TreeNode find_tree_node ( TreeNode root, 
 string name_to_find ) 
 {
 Stack < TreeNode > stack = new Stack < TreeNode > ( );
 bool no_strip = false;

 stack.Push ( root );
 name_to_find = name_to_find.Replace ( @"\", "/" );
 no_strip = name_to_find.EndsWith ( "/" );
 while ( stack.Count > 0 )
 {
 StringBuilder name = new StringBuilder ( );
 TreeNode node = ( TreeNode ) stack.Pop ( );
 
 name.AppendFormat ( "{0}/{1}",
 node.FullPath,
 node.Name );
 name.Replace ( @"\", "/" );
 if ( !no_strip )
 {
 while ( name.ToString ( ).EndsWith ( "/" ) )
 {
 name.Length--;
 }
 }

 if ( name.ToString ( ).Equals ( name_to_find ) )
 {
 return ( node );
 }

 foreach ( TreeNode child in node.Nodes )
 {
 if ( child != null )
 {
 stack.Push( child );
 }
 }
 }

 return ( null );
 }

Given a root node from which to search and the name of a node for which to search, find_tree_node finds a node in the subtree of root that has the name of name_to_find. If the search is successful, returns the TreeNode that contains the name; otherwise, returns null.

I considered using a recursive search but the iterative approach appears to be simple. As a result, the simple beat out the elegant!

5. Using WebOpenFileDialog Table of Contents

As constructed, WebOpenFileDialog is a project containing the WebOpenFileDialog class derived from the Form class. It has the namespace WebOpenFileDialog. To utilize this class in Microsoft Visual Studio [^], simply copy the WebOpenFileDialog project into a containg solution.

6. Demonstration Table of Contents

A demonstration project has been included in the downloads. Upon execution it displayes:

When a file has been chosen, as in the first figure, and the OK button has been clicked, the fully qualified path of the chosen filename appears in the Filename TextBox.

7. References Table of Contents

8. Development Environment Table of Contents

The WebOpenFileDialog was developed in the following environment:

Microsoft Windows 7 Professional Service Pack 1
Microsoft Visual Studio 2008 Professional
Microsoft .Net Framework Version 3.5 SP1
Microsoft Visual C# 2008

9. History Table of Contents

06/27/2017       Original article

LEAVE A REPLY