Sometimes, the built in functions of a framework are good enough for your purpose and there is no point in reinventing the wheel. Fine examples of this are to be found at The Daily WTF, one of my personal faves being The Backup Snippet.
However, sometimes the .NET Framework does a poor job of parsing FTP FastSnap URLs. For instance, ftp://ausername:apassword@IP:port/path. This is especially evident when the IP is given in non-dotted decimal representation.
The following function attempts to parse a FastSnap using the inbuilt Framework. If that fails, it tries a custom procedure that is sometimes able to catch some of the failed entries. It's by no means perfect, but it can give some additional flexibility.
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
// SNIP: namespace and class declarations
/// <summary>
/// Parses an FTP URL into its components
/// </summary>
/// <param name="fastSnap">The input ftp:// URL</param>
/// <returns>A Dictionary containing host, port, username, password and path</returns>
public static Dictionary<string, string> GetFastSnap(string fastSnap)
{
// remove whitespace
fastSnap = fastSnap.Trim();
// check for ftp:// at start
if (!fastSnap.StartsWith("ftp://"))
fastSnap = string.Format("ftp://{0}", fastSnap);
// check for non-existent login information
if (Regex.IsMatch(fastSnap, "^ftp://[^:@]*:[0-9]{1,5}$|^ftp://[^:@]*:[0-9]{1,5}/.*$"))
fastSnap = fastSnap.Replace("ftp://", string.Format("ftp://anonymous:anonymous@{0}", fastSnap));
// remove surplus double slash
if (fastSnap.EndsWith("//"))
fastSnap = fastSnap.TrimEnd('/');
// check for a trailing slash
if (!fastSnap.EndsWith("/"))
fastSnap += "/";
// try and parse using the in-built Framework function
try
{
Uri ftpUri = new Uri(fastSnap);
// construct the return object
Dictionary<string, string> ftpInfoParsed = new Dictionary<string, string>();
if (ftpUri.UserInfo != string.Empty)
{
ftpInfoParsed.Add("username", ftpUri.UserInfo.Split(':')[0]);
ftpInfoParsed.Add("password", ftpUri.UserInfo.Split(':')[1]);
}
else
{
ftpInfoParsed.Add("username", "anonymous");
ftpInfoParsed.Add("password", "anonymous");
}
ftpInfoParsed.Add("host", ftpUri.Host);
ftpInfoParsed.Add("port", ftpUri.Port.ToString());
ftpInfoParsed.Add("path", ftpUri.PathAndQuery);
return ftpInfoParsed;
}
catch (Exception)
{
}
// ascertain various positions within the string
int firstColon = fastSnap.IndexOf(':', 6);
int atSymbol = fastSnap.IndexOf('@', firstColon);
int secondColon = fastSnap.IndexOf(':', atSymbol);
// non-existent port information
if (secondColon == -1)
{
secondColon = firstColon + 1;
}
int forwardSlash = fastSnap.IndexOf('/', secondColon);
// construct the return object
Dictionary<string, string> ftpInfo = new Dictionary<string, string>();
// add the fields
ftpInfo.Add("username", fastSnap.Substring(6, firstColon - 6));
ftpInfo.Add("password", fastSnap.Substring(firstColon + 1, atSymbol - firstColon - 1));
// if no port was specified, we use different offsets
if (secondColon == firstColon + 1)
{
ftpInfo.Add("host", fastSnap.Substring(atSymbol + 1, forwardSlash - atSymbol - 1));
ftpInfo.Add("port", "21");
}
else
{
ftpInfo.Add("host", fastSnap.Substring(atSymbol + 1, secondColon - atSymbol - 1));
ftpInfo.Add("port", fastSnap.Substring(secondColon + 1, forwardSlash - secondColon - 1));
}
if (forwardSlash < fastSnap.Length - 1)
{
ftpInfo.Add("path", fastSnap.Substring(forwardSlash + 1, fastSnap.Length - forwardSlash - 1));
}
else
{
ftpInfo.Add("path", "/");
}
return ftpInfo;
}References
This reference list has been generated, in many cases, through an automated process and may therefore contain errors or incomplete metadata. It is provided purely as assistance for finding the items mentioned within this post.
- Papadimoulis, Alex, ‘The Backup Snippet’, The Daily WTF, 17 December 2008 <http://thedailywtf.com/Articles/The-Backup-Snippet.aspx>
- The Daily WTF: Curious Perversions in Information Technology <http://thedailywtf.com>
- Papadimoulis, A. (2008, December 17). The Backup Snippet. The Daily WTF. http://thedailywtf.com/Articles/The-Backup-Snippet.aspx
- The Daily WTF: Curious Perversions in Information Technology. (n.d.). http://thedailywtf.com
- Papadimoulis, Alex. 2008. “The Backup Snippet.” The Daily WTF, December 17. http://thedailywtf.com/Articles/The-Backup-Snippet.aspx
- The Daily WTF: Curious Perversions in Information Technology. n.d.. http://thedailywtf.com
Martin Paul Eve