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;
public static Dictionary<string, string> GetFastSnap(string fastSnap)
{
fastSnap = fastSnap.Trim();
if (!fastSnap.StartsWith("ftp://"))
fastSnap = string.Format("ftp://{0}", fastSnap);
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));
if (fastSnap.EndsWith("//"))
fastSnap = fastSnap.TrimEnd('/');
if (!fastSnap.EndsWith("/"))
fastSnap += "/";
try
{
Uri ftpUri = new Uri(fastSnap);
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)
{
}
int firstColon = fastSnap.IndexOf(':', 6);
int atSymbol = fastSnap.IndexOf('@', firstColon);
int secondColon = fastSnap.IndexOf(':', atSymbol);
if (secondColon == -1)
{
secondColon = firstColon + 1;
}
int forwardSlash = fastSnap.IndexOf('/', secondColon);
Dictionary<string, string> ftpInfo = new Dictionary<string, string>();
ftpInfo.Add("username", fastSnap.Substring(6, firstColon - 6));
ftpInfo.Add("password", fastSnap.Substring(firstColon + 1, atSymbol - firstColon - 1));
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;
}