using Sarand.Net.Standard.Base.App;
using System;
using System.Text.RegularExpressions;
namespace Sarand.Net.Standard.Base.Utils
{
//=======================================================================
public static class FtpUtil
{
//-------------------------------------------------------------------
/// Cleanse the folder name - delimit with '/', remove duplicate, leading and trailing delimiters.
public static String CleansePath (String path)
{
return path.ReplaceAll("\\", "/").ReplaceAll("//", "/").TrimStart('/').TrimEnd('/');
}
//-------------------------------------------------------------------
/// Retrieve parent folder for folder. Parent for top level folder is blank.
public static String GetParentFolder (String folder)
{
String parentFolder = "";
String[] folders = CleansePath(folder).Split('/');
if (folders.Length > 0)
parentFolder = String.Join("/", folders, 0, folders.Length - 1);
return parentFolder;
}
//-------------------------------------------------------------------
/// Retrieve bottom level item name from path. Parent for top level folder is blank.
public static String GetItemName (String folder)
{
String[] folders = CleansePath(folder).Split('/');
if (folders.Length >= 0)
return folders[folders.Length - 1];
return "";
}
//-------------------------------------------------------------------
public class FtpDirectoryItem
{
public String Attr { get; set; } = "";
public bool IsDirectory { get; set; }
public String Owner { get; set; } = "";
public String Group { get; set; } = "";
public int Links { get; set; }
public long Size { get; set; }
public int Day { get; set; }
public int Month { get; set; }
public String MonthName { get; set; } = "";
public int Year { get; set; }
public String Time { get; set; } = "";
public DateTime Modified { get; set; }
public String Name { get; set; } = "";
}
// YangMing (Unix?) format:
// 08-03-18 10:10AM
SolentInboundTest
// 08-03-18 10:10AM SolentOutboundTest
// 08-03-18 11:23AM 8507075 testDataWithRatherLongFilename.zip
// 08-03-18 11:17AM 22 test.txt
public static readonly Regex DirectoryListPattern_Unix = new Regex(@"^"+
// 1. Month.
@"(\d{2})-"+
// 2. Day of month.
@"(\d{2})-"+
// 3. Year.
@"(\d{2})\s+"+
// 4. Time.
@"(\d{2}:\d{2})"+
// 5. Time period.
@"(\w{2})\s+"+
// 6. Directory indicator or Filesize.
@"(|\d+)\s+"+
// Name.
@"([^\s]+)$",
RegexOptions.IgnoreCase);
// Windows/DOS format:
// drwx------ 3 user group 0 Apr 10 07:47 test
// -rw - r--r-- 1 ftp ftp 5592560 Feb 26 18:53 DamonJenkinsA_84_C_CTS.dds
// Update date format:
// MMM dd HH:mm if the file was modified in the last six months
// MMM dd yyyy otherwise.
public static readonly Regex DirectoryListPattern_Windows = new Regex(@"^"+
// 1. Attributes.
// 1st Character: '-' file. 'b' Block special file. 'c' Character special file. 'd' directory. 'l' link. 'n' Network file. 'p' FIFO. 's' Socket.
// Attributes: r Permission to read file. w Permission to write to file. x Permission to execute file. a Archive bit is on (file has not been backed up).
// c Compressed file. s System file. h Hidden file. t Temporary file.
@"([abcdhlnprstwx-]{10})\s+" +
// 2. Number of links to ths file.
@"(\d+)\s+"+
// 3. Owner.
@"([^\s]+)\s+"+
// 4. Group.
@"([^\s]+)\s+"+
// 5. Size.
@"(\d+)\s+"+
// 6. Month.
@"(\w{3})\s+"+
// 7. Day of month.
@"(\d{1,2})\s+"+
// 8. Time or Year.
@"(\d{4}|\d\d:\d\d)\s+"+
// Name.
@"(.+)$",
RegexOptions.IgnoreCase);
/// Extract details from Directory detail list item.
public static FtpDirectoryItem GetDirectoryItem (String directoryItemData)
{
if (StringUtil.IsEmpty(StringUtil.EmptyOnNull(directoryItemData).Trim())) return null;
// Check for Unix directory listing pattern.
Match match = DirectoryListPattern_Unix.Match(directoryItemData);
if (match.Success && match.Groups.Count == 8)
{
FtpDirectoryItem directoryItem = new FtpDirectoryItem();
directoryItem.Month = StringUtil.ToInt(match.Groups[1].Value);
directoryItem.Day = StringUtil.ToInt(match.Groups[2].Value);
directoryItem.Year = StringUtil.ToInt(match.Groups[3].Value);
String directoryOrFileSize = match.Groups[6].Value;
if (directoryOrFileSize.EqualsCI(""))
directoryItem.IsDirectory = true;
else
directoryItem.Size = StringUtil.ToLong(directoryOrFileSize);
directoryItem.Name = match.Groups[7].Value;
return directoryItem;
}
// Check for Windows directory listing pattern.
match = DirectoryListPattern_Windows.Match(directoryItemData);
if (match.Success && match.Groups.Count == 10)
{
FtpDirectoryItem directoryItem = new FtpDirectoryItem();
directoryItem.Attr = match.Groups[1].Value;
directoryItem.IsDirectory = StringUtil.Left(directoryItem.Attr, 1).EqualsCI("d");
directoryItem.Links = StringUtil.ToInt(match.Groups[2].Value);
directoryItem.Owner = match.Groups[3].Value;
directoryItem.Group = match.Groups[4].Value;
directoryItem.Size = StringUtil.ToInt(match.Groups[5].Value);
directoryItem.MonthName = match.Groups[6].Value;
directoryItem.Day = StringUtil.ToInt(match.Groups[7].Value);
String timeYear = match.Groups[8].Value;
if (StringUtil.IsNumeric(timeYear))
directoryItem.Year = StringUtil.ToInt(timeYear);
directoryItem.Name = match.Groups[9].Value;
return directoryItem;
}
// Log failure.
SaLogger.Warn("FtpUtils.GetDirectoryItem Parse Failed: '" + directoryItemData + "'", true);
return null;
}
//-------------------------------------------------------------------
}
//=======================================================================
}