private static FtpListItem ParseVaxList(string buf, FtpCapability capabilities) { string regex = @"(?<name>.+)\.(?<extension>.+);(?<version>\d+)\s+" + @"(?<size>\d+)\s+" + @"(?<modify>\d+-\w+-\d+\s+\d+:\d+)"; Match m; if ((m = Regex.Match(buf, regex)).Success) { FtpListItem item = new FtpListItem(); item.m_name = string.Format("{0}.{1};{2}", m.Groups["name"].Value, m.Groups["extension"].Value, m.Groups["version"].Value); if (m.Groups["extension"].Value.ToUpper() == "DIR") item.m_type = FtpFileSystemObjectType.Directory; else item.m_type = FtpFileSystemObjectType.File; if (!long.TryParse(m.Groups["size"].Value, out item.m_size)) item.m_size = -1; if ( !DateTime.TryParse(m.Groups["modify"].Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out item.m_modified)) item.m_modified = DateTime.MinValue; return item; } return null; }
/// <summary> /// Parses IIS DOS format listings /// </summary> /// <param name="buf">A line from the listing</param> /// <param name="capabilities">Server capabilities</param> /// <returns>FtpListItem if the item is able to be parsed</returns> private static FtpListItem ParseDosList(string buf, FtpCapability capabilities) { FtpListItem item = new FtpListItem(); string[] datefmt = new string[] { "MM-dd-yy hh:mmtt", "MM-dd-yyyy hh:mmtt" }; Match m; // directory if ( (m = Regex.Match(buf, @"(?<modify>\d+-\d+-\d+\s+\d+:\d+\w+)\s+<DIR>\s+(?<name>.*)$", RegexOptions.IgnoreCase)) .Success) { DateTime modify; item.Type = FtpFileSystemObjectType.Directory; item.Name = m.Groups["name"].Value; //if (DateTime.TryParse(m.Groups["modify"].Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out modify)) if (DateTime.TryParseExact(m.Groups["modify"].Value, datefmt, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out modify)) item.Modified = modify; } // file else if ( (m = Regex.Match(buf, @"(?<modify>\d+-\d+-\d+\s+\d+:\d+\w+)\s+(?<size>\d+)\s+(?<name>.*)$", RegexOptions.IgnoreCase)).Success) { DateTime modify; long size; item.Type = FtpFileSystemObjectType.File; item.Name = m.Groups["name"].Value; if (long.TryParse(m.Groups["size"].Value, out size)) item.Size = size; //if (DateTime.TryParse(m.Groups["modify"].Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out modify)) if (DateTime.TryParseExact(m.Groups["modify"].Value, datefmt, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out modify)) item.Modified = modify; } else return null; return item; }
/// <summary> /// Parses MLS* format listings /// </summary> /// <param name="buf">A line from the listing</param> /// <param name="capabilities">Server capabilities</param> /// <returns>FtpListItem if the item is able to be parsed</returns> private static FtpListItem ParseMachineList(string buf, FtpCapability capabilities) { FtpListItem item = new FtpListItem(); Match m; if (!(m = Regex.Match(buf, "type=(?<type>.+?);", RegexOptions.IgnoreCase)).Success) return null; switch (m.Groups["type"].Value.ToLower()) { case "dir": case "cdir": case "pdir": item.Type = FtpFileSystemObjectType.Directory; break; case "file": item.Type = FtpFileSystemObjectType.File; break; // These are not supported for now. case "link": case "device": default: return null; } if ((m = Regex.Match(buf, "; (?<name>.*)$", RegexOptions.IgnoreCase)).Success) item.Name = m.Groups["name"].Value; else // if we can't parse the file name there is a problem. return null; if ((m = Regex.Match(buf, "modify=(?<modify>.+?);", RegexOptions.IgnoreCase)).Success) item.Modified = m.Groups["modify"].Value.GetFtpDate(DateTimeStyles.AssumeUniversal); if ((m = Regex.Match(buf, "created?=(?<create>.+?);", RegexOptions.IgnoreCase)).Success) item.Created = m.Groups["create"].Value.GetFtpDate(DateTimeStyles.AssumeUniversal); if ((m = Regex.Match(buf, @"size=(?<size>\d+);", RegexOptions.IgnoreCase)).Success) { long size; if (long.TryParse(m.Groups["size"].Value, out size)) item.Size = size; } if ((m = Regex.Match(buf, @"unix.mode=(?<mode>\d+);", RegexOptions.IgnoreCase)).Success) { if (m.Groups["mode"].Value.Length == 4) { item.SpecialPermissions = (FtpSpecialPermissions) int.Parse(m.Groups["mode"].Value[0].ToString()); item.OwnerPermissions = (FtpPermission) int.Parse(m.Groups["mode"].Value[1].ToString()); item.GroupPermissions = (FtpPermission) int.Parse(m.Groups["mode"].Value[2].ToString()); item.OthersPermissions = (FtpPermission) int.Parse(m.Groups["mode"].Value[3].ToString()); } else if (m.Groups["mode"].Value.Length == 3) { item.OwnerPermissions = (FtpPermission) int.Parse(m.Groups["mode"].Value[0].ToString()); item.GroupPermissions = (FtpPermission) int.Parse(m.Groups["mode"].Value[1].ToString()); item.OthersPermissions = (FtpPermission) int.Parse(m.Groups["mode"].Value[2].ToString()); } } return item; }
/// <summary> /// Parses LIST format listings /// </summary> /// <param name="buf">A line from the listing</param> /// <param name="capabilities">Server capabilities</param> /// <returns>FtpListItem if the item is able to be parsed</returns> private static FtpListItem ParseUnixList(string buf, FtpCapability capabilities) { string regex = @"(?<permissions>[dslrwx-]+)\s+" + @"(?<objectcount>\d+)\s+" + @"(?<user>.+?)\s+" + @"(?<group>.+?)\s+" + @"(?<size>\d+)\s+" + @"(?<modify>\w+\s+\d+\s+\d+:\d+|\w+\s+\d+\s+\d+|\d+\-\d+\-\d+\-\d+:\d+)\s+" + @"(?<name>.*)$"; FtpListItem item = new FtpListItem(); Match m; if (!(m = Regex.Match(buf, regex, RegexOptions.IgnoreCase)).Success) return null; // if this field is missing we can't determine // what the object is. if (m.Groups["permissions"].Value.Length == 0) return null; switch (m.Groups["permissions"].Value[0]) { case 'd': item.Type = FtpFileSystemObjectType.Directory; break; case '-': case 's': item.Type = FtpFileSystemObjectType.File; break; case 'l': item.Type = FtpFileSystemObjectType.Link; break; default: return null; } // if we can't determine a file name then // we are not considering this a successful parsing operation. if (m.Groups["name"].Value.Length < 1) return null; item.Name = m.Groups["name"].Value; switch (item.Type) { case FtpFileSystemObjectType.Directory: // ignore these... if (item.Name == "." || item.Name == "..") return null; break; case FtpFileSystemObjectType.Link: if (!item.Name.Contains(" -> ")) return null; item.LinkTarget = item.Name.Remove(0, item.Name.IndexOf("-> ") + 3); item.Name = item.Name.Remove(item.Name.IndexOf(" -> ")); break; } //// // Ignore the Modify times sent in LIST format for files // when the server has support for the MDTM command // because they will never be as accurate as what can be had // by using the MDTM command. MDTM does not work on directories // so if a modify time was parsed from the listing we will try // to convert it to a DateTime object and use it for directories. //// if (((capabilities & FtpCapability.MDTM) != FtpCapability.MDTM || item.Type == FtpFileSystemObjectType.Directory) && m.Groups["modify"].Value.Length > 0) item.Modified = m.Groups["modify"].Value.GetFtpDate(DateTimeStyles.AssumeLocal); if (m.Groups["size"].Value.Length > 0) { long size; if (long.TryParse(m.Groups["size"].Value, out size)) item.Size = size; } if (m.Groups["permissions"].Value.Length > 0) { Match perms = Regex.Match(m.Groups["permissions"].Value, @"[\w-]{1}(?<owner>[\w-]{3})(?<group>[\w-]{3})(?<others>[\w-]{3})", RegexOptions.IgnoreCase); if (perms.Success) { if (perms.Groups["owner"].Value.Length == 3) { if (perms.Groups["owner"].Value[0] == 'r') item.OwnerPermissions |= FtpPermission.Read; if (perms.Groups["owner"].Value[1] == 'w') item.OwnerPermissions |= FtpPermission.Write; if (perms.Groups["owner"].Value[2] == 'x' || perms.Groups["owner"].Value[2] == 's') item.OwnerPermissions |= FtpPermission.Execute; if (perms.Groups["owner"].Value[2] == 's' || perms.Groups["owner"].Value[2] == 'S') item.SpecialPermissions |= FtpSpecialPermissions.SetUserID; } if (perms.Groups["group"].Value.Length == 3) { if (perms.Groups["group"].Value[0] == 'r') item.GroupPermissions |= FtpPermission.Read; if (perms.Groups["group"].Value[1] == 'w') item.GroupPermissions |= FtpPermission.Write; if (perms.Groups["group"].Value[2] == 'x' || perms.Groups["group"].Value[2] == 's') item.GroupPermissions |= FtpPermission.Execute; if (perms.Groups["group"].Value[2] == 's' || perms.Groups["group"].Value[2] == 'S') item.SpecialPermissions |= FtpSpecialPermissions.SetGroupID; } if (perms.Groups["others"].Value.Length == 3) { if (perms.Groups["others"].Value[0] == 'r') item.OthersPermissions |= FtpPermission.Read; if (perms.Groups["others"].Value[1] == 'w') item.OthersPermissions |= FtpPermission.Write; if (perms.Groups["others"].Value[2] == 'x' || perms.Groups["others"].Value[2] == 't') item.OthersPermissions |= FtpPermission.Execute; if (perms.Groups["others"].Value[2] == 't' || perms.Groups["others"].Value[2] == 'T') item.SpecialPermissions |= FtpSpecialPermissions.Sticky; } } } return item; }
private static void PostParse(string path, string buf, Parser parser, FtpListItem item) { // if this is a vax/openvms file listing // there are no slashes in the path name if (parser == (ParseVaxList)) item.FullName = path + item.Name; else { //FtpTrace.WriteLine(item.Name); // remove globbing/wildcard from path if (path.GetFtpFileName().Contains("*")) path = path.GetFtpDirectoryName(); item.FullName = path.GetFtpPath(item.Name); //.GetFtpPathWithoutGlob(); // if a link target is set and it doesn't include an absolute path // then try to resolve it. if (item.LinkTarget != null && !item.LinkTarget.StartsWith("/")) item.LinkTarget = path.GetFtpPath(item.LinkTarget.StartsWith("./") ? item.LinkTarget.Remove(0, 2) : item.LinkTarget); } item.Input = buf; }