363 lines
12 KiB
C#
363 lines
12 KiB
C#
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 {
|
|
/// <summary>
|
|
/// Extension methods related to FTP tasks
|
|
/// </summary>
|
|
public static class FtpExtensions {
|
|
|
|
/// <summary>
|
|
/// Converts the specified path into a valid FTP file system path
|
|
/// </summary>
|
|
/// <param name="path">The file system path</param>
|
|
/// <returns>A path formatted for FTP</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a valid FTP path by appending the specified segments to this string
|
|
/// </summary>
|
|
/// <param name="path">This string</param>
|
|
/// <param name="segments">The path segments to append</param>
|
|
/// <returns>A valid FTP path</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the parent directory path (formatted for a FTP server)
|
|
/// </summary>
|
|
/// <param name="path">The path</param>
|
|
/// <returns>The parent directory path</returns>
|
|
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();
|
|
}*/
|
|
|
|
/// <summary>
|
|
/// Gets the file name and extension from the path
|
|
/// </summary>
|
|
/// <param name="path">The full path to the file</param>
|
|
/// <returns>The file name</returns>
|
|
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" };
|
|
|
|
/// <summary>
|
|
/// Tries to convert the string FTP date representation into a <see cref="DateTime"/> object
|
|
/// </summary>
|
|
/// <param name="date">The date</param>
|
|
/// <param name="style">UTC/Local Time</param>
|
|
/// <returns>A <see cref="DateTime"/> object representing the date, or <see cref="DateTime.MinValue"/> if there was a problem</returns>
|
|
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" };
|
|
|
|
/// <summary>
|
|
/// Converts a file size in bytes to a string representation (eg. 12345 becomes 12.3 KB)
|
|
/// </summary>
|
|
public static string FileSizeToString(this int bytes) {
|
|
return ((long)bytes).FileSizeToString();
|
|
}
|
|
/// <summary>
|
|
/// Converts a file size in bytes to a string representation (eg. 12345 becomes 12.3 KB)
|
|
/// </summary>
|
|
public static string FileSizeToString(this uint bytes) {
|
|
return ((long)bytes).FileSizeToString();
|
|
}
|
|
/// <summary>
|
|
/// Converts a file size in bytes to a string representation (eg. 12345 becomes 12.3 KB)
|
|
/// </summary>
|
|
public static string FileSizeToString(this ulong bytes) {
|
|
return ((long)bytes).FileSizeToString();
|
|
}
|
|
/// <summary>
|
|
/// Converts a file size in bytes to a string representation (eg. 12345 becomes 12.3 KB)
|
|
/// </summary>
|
|
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
|
|
/// <summary>
|
|
/// This creates a <see cref="System.Threading.Tasks.Task{TResult}"/> 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
|
|
/// <see cref="o:System.Threading.TaskFactory.FromAsync"/> to 4 from a 3.
|
|
/// </summary>
|
|
/// <typeparam name="TArg1">The type of the first argument passed to the <paramref name="beginMethod"/> delegate</typeparam>
|
|
/// <typeparam name="TArg2">The type of the second argument passed to the <paramref name="beginMethod"/> delegate</typeparam>
|
|
/// <typeparam name="TArg3">The type of the third argument passed to the <paramref name="beginMethod"/> delegate</typeparam>
|
|
/// <typeparam name="TArg4">The type of the forth argument passed to the <paramref name="beginMethod"/> delegate</typeparam>
|
|
/// <typeparam name="TResult">The type of the result.</typeparam>
|
|
/// <param name="factory">The <see cref="TaskFactory"/> used</param>
|
|
/// <param name="beginMethod">The delegate that begins the asynchronous operation</param>
|
|
/// <param name="endMethod">The delegate that ends the asynchronous operation</param>
|
|
/// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> delegate</param>
|
|
/// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> delegate</param>
|
|
/// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/> delegate</param>
|
|
/// <param name="arg4">The forth argument passed to the <paramref name="beginMethod"/> delegate</param>
|
|
/// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> delegate</param>
|
|
/// <returns>The created <see cref="System.Threading.Tasks.Task{TResult}"/> that represents the asynchronous operation</returns>
|
|
/// <exception cref="System.ArgumentNullException">
|
|
/// beginMethod is null
|
|
/// or
|
|
/// endMethod is null
|
|
/// </exception>
|
|
public static Task<TResult> FromAsync<TArg1, TArg2, TArg3, TArg4, TResult>(this TaskFactory factory,
|
|
Func<TArg1, TArg2, TArg3, TArg4, AsyncCallback, object, IAsyncResult> beginMethod,
|
|
Func<IAsyncResult, TResult> 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<TResult> tcs = new TaskCompletionSource<TResult>(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
|
|
|
|
/// <summary>
|
|
/// Validates that the FtpError flags set are not in an invalid combination.
|
|
/// </summary>
|
|
/// <param name="options">The error handling options set</param>
|
|
/// <returns>True if a valid combination, otherwise false</returns>
|
|
public static bool IsValidCombination(this FtpError options) {
|
|
return options != (FtpError.Stop | FtpError.Throw) &&
|
|
options != (FtpError.Throw | FtpError.Stop | FtpError.DeleteProcessed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if every character in the string is whitespace, or the string is null.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the string is null or 0 length.
|
|
/// </summary>
|
|
public static bool IsBlank(this string value) {
|
|
return value == null || value.Length == 0;
|
|
}
|
|
|
|
#if NET45
|
|
/// <summary>
|
|
/// Checks if the array is null or 0 length.
|
|
/// </summary>
|
|
public static bool IsBlank(this IList value) {
|
|
return value == null || value.Count == 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the array is null or 0 length.
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Join the given strings by a delimiter.
|
|
/// </summary>
|
|
public static string Join(this string[] values, string delimiter) {
|
|
return string.Join(delimiter, values);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Join the given strings by a delimiter.
|
|
/// </summary>
|
|
public static string Join(this List<string> values, string delimiter) {
|
|
#if NET20 || NET35
|
|
return string.Join(delimiter, values.ToArray());
|
|
#else
|
|
return string.Join(delimiter, values);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a prefix to the given strings, returns a new array.
|
|
/// </summary>
|
|
public static string[] AddPrefix(this string[] values, string prefix, bool trim = false) {
|
|
List<string> results = new List<string>();
|
|
foreach (string v in values) {
|
|
string txt = prefix + (trim ? v.Trim() : v);
|
|
results.Add(txt);
|
|
}
|
|
return results.ToArray();
|
|
}
|
|
/// <summary>
|
|
/// Adds a prefix to the given strings, returns a new array.
|
|
/// </summary>
|
|
public static List<string> AddPrefix(this List<string> values, string prefix, bool trim = false) {
|
|
List<string> results = new List<string>();
|
|
foreach (string v in values) {
|
|
string txt = prefix + (trim ? v.Trim() : v);
|
|
results.Add(txt);
|
|
}
|
|
return results;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a prefix to the given strings, returns a new array.
|
|
/// </summary>
|
|
public static List<string> ItemsToString(this object[] args) {
|
|
List<string> results = new List<string>();
|
|
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
|
|
|
|
|
|
}
|
|
} |