Files
NewsCrawler/FluentFTP/Utils/FtpExtensions.cs
2018-01-02 01:11:53 +09:00

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
}
}