using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using System.Globalization; #if (CORE || NETFX) using System.Diagnostics; #endif #if NET45 using System.Threading.Tasks; using System.Collections; #endif namespace FluentFTP { /// /// Extension methods related to FTP tasks /// public static class FtpExtensions { /// /// Converts the specified path into a valid FTP file system path /// /// The file system path /// A path formatted for FTP public static string GetFtpPath(this string path) { if (String.IsNullOrEmpty(path)) return "./"; path = path.Replace('\\', '/'); path = Regex.Replace(path, "[/]+", "/"); path = path.TrimEnd('/'); if (path.Length == 0) path = "/"; return path; } /// /// Creates a valid FTP path by appending the specified segments to this string /// /// This string /// The path segments to append /// A valid FTP path public static string GetFtpPath(this string path, params string[] segments) { if (String.IsNullOrEmpty(path)) path = "./"; foreach (string part in segments) { if (part != null) { if (path.Length > 0 && !path.EndsWith("/")) path += "/"; path += Regex.Replace(part.Replace('\\', '/'), "[/]+", "/").TrimEnd('/'); } } path = Regex.Replace(path.Replace('\\', '/'), "[/]+", "/").TrimEnd('/'); if (path.Length == 0) path = "/"; /*if (!path.StartsWith("/") || !path.StartsWith("./")) path = "./" + path;*/ return path; } /// /// Gets the parent directory path (formatted for a FTP server) /// /// The path /// The parent directory path public static string GetFtpDirectoryName(this string path) { string tpath = (path == null ? "" : path.GetFtpPath()); if (tpath.Length == 0 || tpath == "/") return "/"; int lastslash = tpath.LastIndexOf('/'); if (lastslash < 0) return "."; if (lastslash == 0) return "/"; return tpath.Substring(0, lastslash); } /*public static string GetFtpDirectoryName(this string path) { if (path == null || path.Length == 0 || path.GetFtpPath() == "/") return "/"; return System.IO.Path.GetDirectoryName(path).GetFtpPath(); }*/ /// /// Gets the file name and extension from the path /// /// The full path to the file /// The file name public static string GetFtpFileName(this string path) { string tpath = (path == null ? null : path); int lastslash = -1; if (tpath == null) return null; lastslash = tpath.LastIndexOf('/'); if (lastslash < 0) return tpath; lastslash += 1; if (lastslash >= tpath.Length) return tpath; return tpath.Substring(lastslash, tpath.Length - lastslash); } /*public static string GetFtpFileName(this string path) { return System.IO.Path.GetFileName(path).GetFtpPath(); }*/ private static string[] FtpDateFormats = { "yyyyMMddHHmmss", "yyyyMMddHHmmss'.'f", "yyyyMMddHHmmss'.'ff", "yyyyMMddHHmmss'.'fff", "MMM dd yyyy","MMM d yyyy","MMM dd HH:mm","MMM d HH:mm" }; /// /// Tries to convert the string FTP date representation into a object /// /// The date /// UTC/Local Time /// A object representing the date, or if there was a problem public static DateTime GetFtpDate(this string date, DateTimeStyles style) { DateTime parsed; if (DateTime.TryParseExact(date, FtpDateFormats, CultureInfo.InvariantCulture, style, out parsed)) { return parsed; } return DateTime.MinValue; } private static string[] sizePostfix = { "bytes", "KB", "MB", "GB", "TB" }; /// /// Converts a file size in bytes to a string representation (eg. 12345 becomes 12.3 KB) /// public static string FileSizeToString(this int bytes) { return ((long)bytes).FileSizeToString(); } /// /// Converts a file size in bytes to a string representation (eg. 12345 becomes 12.3 KB) /// public static string FileSizeToString(this uint bytes) { return ((long)bytes).FileSizeToString(); } /// /// Converts a file size in bytes to a string representation (eg. 12345 becomes 12.3 KB) /// public static string FileSizeToString(this ulong bytes) { return ((long)bytes).FileSizeToString(); } /// /// Converts a file size in bytes to a string representation (eg. 12345 becomes 12.3 KB) /// public static string FileSizeToString(this long bytes) { int order = 0; double len = bytes; while (len >= 1024 && order < sizePostfix.Length - 1) { order++; len = len / 1024; } return String.Format("{0:0.#} {1}", len, sizePostfix[order]); } #if NET45 /// /// This creates a that represents a pair of begin and end methods /// that conform to the Asynchronous Programming Model pattern. This extends the maximum amount of arguments from /// to 4 from a 3. /// /// The type of the first argument passed to the delegate /// The type of the second argument passed to the delegate /// The type of the third argument passed to the delegate /// The type of the forth argument passed to the delegate /// The type of the result. /// The used /// The delegate that begins the asynchronous operation /// The delegate that ends the asynchronous operation /// The first argument passed to the delegate /// The second argument passed to the delegate /// The third argument passed to the delegate /// The forth argument passed to the delegate /// An object containing data to be used by the delegate /// The created that represents the asynchronous operation /// /// beginMethod is null /// or /// endMethod is null /// public static Task FromAsync(this TaskFactory factory, Func beginMethod, Func endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, object state) { if (beginMethod == null) throw new ArgumentNullException("beginMethod"); if (endMethod == null) throw new ArgumentNullException("endMethod"); TaskCompletionSource tcs = new TaskCompletionSource(state, factory.CreationOptions); try { AsyncCallback callback = delegate(IAsyncResult asyncResult) { tcs.TrySetResult(endMethod(asyncResult)); }; beginMethod(arg1, arg2, arg3, arg4, callback, state); } catch { tcs.TrySetResult(default(TResult)); throw; } return tcs.Task; } #endif /// /// Validates that the FtpError flags set are not in an invalid combination. /// /// The error handling options set /// True if a valid combination, otherwise false public static bool IsValidCombination(this FtpError options) { return options != (FtpError.Stop | FtpError.Throw) && options != (FtpError.Throw | FtpError.Stop | FtpError.DeleteProcessed); } /// /// Checks if every character in the string is whitespace, or the string is null. /// public static bool IsNullOrWhiteSpace(string value) { if (value == null) return true; for (int i = 0; i < value.Length; i++) { if (!Char.IsWhiteSpace(value[i])) return false; } return true; } /// /// Checks if the string is null or 0 length. /// public static bool IsBlank(this string value) { return value == null || value.Length == 0; } #if NET45 /// /// Checks if the array is null or 0 length. /// public static bool IsBlank(this IList value) { return value == null || value.Count == 0; } /// /// Checks if the array is null or 0 length. /// public static bool IsBlank(this IEnumerable value) { if (value == null){ return true; } if (value is IList){ return ((IList)value).Count == 0; } if (value is byte[]){ return ((byte[])value).Length == 0; } return false; } #endif /// /// Join the given strings by a delimiter. /// public static string Join(this string[] values, string delimiter) { return string.Join(delimiter, values); } /// /// Join the given strings by a delimiter. /// public static string Join(this List values, string delimiter) { #if NET20 || NET35 return string.Join(delimiter, values.ToArray()); #else return string.Join(delimiter, values); #endif } /// /// Adds a prefix to the given strings, returns a new array. /// public static string[] AddPrefix(this string[] values, string prefix, bool trim = false) { List results = new List(); foreach (string v in values) { string txt = prefix + (trim ? v.Trim() : v); results.Add(txt); } return results.ToArray(); } /// /// Adds a prefix to the given strings, returns a new array. /// public static List AddPrefix(this List values, string prefix, bool trim = false) { List results = new List(); foreach (string v in values) { string txt = prefix + (trim ? v.Trim() : v); results.Add(txt); } return results; } /// /// Adds a prefix to the given strings, returns a new array. /// public static List ItemsToString(this object[] args) { List results = new List(); if (args == null) { return results; } foreach (object v in args) { string txt; if (v == null){ txt = "null"; } else if (v is string) { txt = ("\"" + v as string + "\""); } else { txt = v.ToString(); } results.Add(txt); } return results; } #if NET20 || NET35 public static bool HasFlag(this FtpHashAlgorithm flags, FtpHashAlgorithm flag) { return (flags & flag) == flag; } public static bool HasFlag(this FtpCapability flags, FtpCapability flag) { return (flags & flag) == flag; } public static bool HasFlag(this FtpVerify flags, FtpVerify flag) { return (flags & flag) == flag; } public static bool HasFlag(this FtpError flags, FtpError flag) { return (flags & flag) == flag; } public static void Restart(this Stopwatch watch) { watch.Stop(); watch.Start(); } #endif } }