// (c) 2016 DL2ALF using System; using System.Collections.Generic; using System.Linq; using System.Globalization; using System.Diagnostics; using System.Net; using System.IO; using System.Reflection; using System.Windows.Forms; using System.Text.RegularExpressions; using System.Threading; using Ionic.Zip; using Ionic.BZip2; using System.Runtime.Serialization.Formatters.Binary; using System.Xml; using System.Text; using System.Configuration; using System.Xml.Serialization; using System.Security.Cryptography; namespace RainScout.Core { [System.ComponentModel.DesignerCategory("")] public static class SupportFunctions : Object { public static double TodB(double value) { // calulate dB from linear value return 10.0f * Math.Log10(value); } public static double ToLinear(double value) { // calculate linear value from dB return Math.Pow(10, value / 10.0f); } /// /// Returns true if running under Linux/Mono /// public static bool IsMono { get { int p = (int)Environment.OSVersion.Platform; return (p == 4) || (p == 6) || (p == 128); } } /// /// Returns true if running under a 64bit configuration /// public static bool Is64BitConfiguration() { return System.IntPtr.Size == 8; } [System.ComponentModel.DesignerCategory("")] public static class CPUCounter { static PerformanceCounter cpucounter; static CPUCounter() { cpucounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); } public static double GetLoad() { // returns the current overall CPU load return cpucounter.NextValue(); } } [System.ComponentModel.DesignerCategory("")] public static class MemoryCounter { static PerformanceCounter available; static MemoryCounter() { available = new PerformanceCounter("Memory", "Available MBytes"); } /// /// Get the amount of available memory in MBytes /// /// The amount of memory available in MBytes. public static double GetAvailable() { // returns the current overall CPU load return available.NextValue(); } } /// /// Checks whether a given path would be a vaild path to a directory. /// The path must be fully qualified. /// /// The path. /// True if the path is valid. public static bool ValidateDirectoryPath(string path) { // return false on empty or whitespaced path if (String.IsNullOrEmpty(path)) return false; if (String.IsNullOrWhiteSpace(path)) return false; string root = null; ; string directory = null; try { //throw ArgumentException - The path parameter contains invalid characters, is empty, or contains only white spaces. root = Path.GetPathRoot(path); //throw ArgumentException - path contains one or more of the invalid characters defined in GetInvalidPathChars. // -or- String.Empty was passed to path. directory = Path.GetDirectoryName(path); } catch (ArgumentException) { return false; } //null if path is null, or an empty string if path does not contain root directory information if (String.IsNullOrEmpty(root)) return false; //null if path denotes a root directory or is null. Returns String.Empty if path does not contain directory information if (String.IsNullOrEmpty(directory)) return false; // path is valid at the end return true; } /// /// Checks whether a given path would be a vaild path to a file. /// The path must be fully qualified. /// /// The path. /// True if the path is valid. public static bool ValidateFilePath(string path) { // return false on empty or whitespaced path if (String.IsNullOrEmpty(path)) return false; if (String.IsNullOrWhiteSpace(path)) return false; string root = null; ; string directory = null; string filename = null; try { //throw ArgumentException - The path parameter contains invalid characters, is empty, or contains only white spaces. root = Path.GetPathRoot(path); //throw ArgumentException - path contains one or more of the invalid characters defined in GetInvalidPathChars. // -or- String.Empty was passed to path. directory = Path.GetDirectoryName(path); //path contains one or more of the invalid characters defined in GetInvalidPathChars filename = Path.GetFileName(path); } catch (ArgumentException) { return false; } //null if path is null, or an empty string if path does not contain root directory information if (String.IsNullOrEmpty(root)) return false; //null if path denotes a root directory or is null. Returns String.Empty if path does not contain directory information if (String.IsNullOrEmpty(directory)) return false; // path is valid at the end return true; } /// /// Retrieves drive information about a specific drive /// /// The drive letter, e.g. "C:\" (Windows) or "\" (Linux). /// The DriveInfo object if drive was found, null if not. public static DriveInfo GetDriveInfo(string drive) { DriveInfo[] drives = DriveInfo.GetDrives(); foreach (DriveInfo d in drives) { if (d.IsReady) Console.WriteLine("DriveInfo\n=============\nName=\"" + d.Name + "\"\nFormat=\"" + d.DriveFormat + "\"\nFree=" + d.AvailableFreeSpace); if (d.Name == drive) { return d; } } return null; } /// /// Retrieves file system of a specific drive /// /// The drive letter, e.g. "C:\" (Windows) or "\" (Linux). /// The file system identifier if drive was found, empty string if not. public static string GetDriveFileSystem(string drive) { DriveInfo d = GetDriveInfo(drive); // drive not found --> return 0 if (d == null) return string.Empty; return d.DriveFormat; } /// /// Retrieves available free space of a specific drive /// /// The drive letter, e.g. "C:\" (Windows) or "\" (Linux). /// The available frees space [bytes] if drive was found, 0 if not. public static long GetDriveAvailableFreeSpace(string drive) { DriveInfo d = GetDriveInfo(drive); // drive not found --> return 0 if (d == null) return 0; return d.AvailableFreeSpace; } /// /// Retrieves maxixum allowed file size on a specific file system /// /// The file system identifier. /// The available maximum file size [bytes] if filesystem is found on the list, 0 if not. public static long GetFileSystemGetMaxFileSize(string filesystem) { filesystem = filesystem.ToUpper().Trim(); if (filesystem == "FAT16") return (long)2 * System.Convert.ToInt64(Math.Pow(2, 30)); if (filesystem == "FAT32") return (long)4 * System.Convert.ToInt64(Math.Pow(2, 30)) - (long)1; if (filesystem == "NTFS") return (long)16 * System.Convert.ToInt64(Math.Pow(2, 40)); if (filesystem == "EXT2") return (long)2 * System.Convert.ToInt64(Math.Pow(2, 40)); if (filesystem == "EXT3") return (long)2 * System.Convert.ToInt64(Math.Pow(2, 40)); if (filesystem == "EXT4") return (long)1 * System.Convert.ToInt64(Math.Pow(2, 60)); if (filesystem == "BTRFS") return long.MaxValue; return 0; } /// /// Retrieves maxixum allowed file size on a specific file system /// /// The drive letter, e.g. "C:\" (Windows) or "\" (Linux). /// The available maximum file size [bytes] if drive and file system is found, 0 if not. public static long GetDriveMaxFileSize(string drive) { string filesystem = GetDriveFileSystem(drive).ToUpper().Trim(); if (String.IsNullOrEmpty(filesystem)) return 0; if (filesystem == "FAT16") return (long)2 * System.Convert.ToInt64(Math.Pow(2, 30)); if (filesystem == "FAT32") return (long)4 * System.Convert.ToInt64(Math.Pow(2, 30)) - (long)1; if (filesystem == "NTFS") return (long)16 * System.Convert.ToInt64(Math.Pow(2, 40)); if (filesystem == "EXT2") return (long)2 * System.Convert.ToInt64(Math.Pow(2, 40)); if (filesystem == "EXT3") return (long)2 * System.Convert.ToInt64(Math.Pow(2, 40)); if (filesystem == "EXT4") return (long)1 * System.Convert.ToInt64(Math.Pow(2, 60)); if (filesystem == "BTRFS") return long.MaxValue; return 0; } /// /// Checks whether a given filename would be valid. /// The filename must not contain path information. /// /// The filename. /// True if the filename is valid. public static bool ValidateFileName(string filename) { // return false on empty or whitespaced path if (String.IsNullOrEmpty(filename)) return false; if (String.IsNullOrWhiteSpace(filename)) return false; if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) return false; return true; } /// /// Deletes files from a given directory which are matching a single filter pattern /// /// The directory. /// The filter pattern. /// Nothing. public static void DeleteFilesFromDirectory(string dir, string filter) { string[] files = Directory.GetFiles(dir, filter); foreach (string file in files) { try { File.Delete(file); } catch (Exception ex) { Console.WriteLine("DeleteFilesFromDirectory: " + ex.ToString()); } } } /// /// Deletes files from a given directory which are matching multiple filter patterns /// /// The directory. /// The filter patterns. /// Nothing. public static void DeleteFilesFromDirectory(string dir, string[] filters) { string[] files = filters.SelectMany(f => Directory.GetFiles(dir, f)).ToArray(); foreach (string file in files) { try { File.Delete(file); } catch (Exception ex) { Console.WriteLine("DeleteFilesFromDirectory: " + ex.ToString()); } } } /// /// Writes a string into a file /// /// The string. /// The filename. /// Nothing. public static void WriteStringToFile(string str, string filename) { using (StreamWriter sw = new StreamWriter(filename)) { sw.WriteLine(str); } } /// /// Reads a string from a file /// /// The filename. /// The string. public static string ReadStringFromFile(string filename) { string s = String.Empty; using (StreamReader sr = new StreamReader(File.OpenRead(filename))) { s = sr.ReadToEnd(); } return s; } /// /// Converts an object to an array of bytes. /// /// The object. /// Array of bytes representing the object. public static byte[] ObjectToByteArray(Object obj) { BinaryFormatter bf = new BinaryFormatter(); using (var ms = new MemoryStream()) { bf.Serialize(ms, obj); return ms.ToArray(); } } /// /// Converts an array of bytes into an object. /// /// The array of bytes representing the object. /// The object. public static Object ByteArrayToObject(byte[] arr) { using (var memStream = new MemoryStream()) { var binForm = new BinaryFormatter(); memStream.Write(arr, 0, arr.Length); memStream.Seek(0, SeekOrigin.Begin); var obj = binForm.Deserialize(memStream); return obj; } } /// /// Converts a DateTime into UNIX Epoch time /// Handles MinValue and MaxValue correctly /// /// The DateTime to be converted. /// The UNIX Epoch time. Fractional seconds will be lost. public static int DateTimeToUNIXTime(DateTime dt) { if (dt == DateTime.MinValue) return int.MinValue; else if (dt == DateTime.MaxValue) return int.MaxValue; return (Int32)(dt.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; } /// /// Converts a UNIX Epoch time into DateTime /// Handles MinValue and MaxValue correctly /// /// The UNIX Epoch time to be converted. /// The DateTime (in UTC). public static DateTime UNIXTimeToDateTime(int ut) { if (ut == int.MinValue) return DateTime.MinValue; else if (ut == int.MaxValue) return DateTime.MaxValue; DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); return dt.AddSeconds(ut); } } [System.ComponentModel.DesignerCategory("")] public static class UnitConverter { public static double ft_m(double feet) { return feet / 3.28084; } public static double m_ft(double m) { return m * 3.28084; } public static double kts_kmh(double kts) { return kts * 1.852; } public static double kmh_kts(double kmh) { return kmh / 1.852; } public static double km_mi(double km) { return km * 1.609; } public static double mi_km(double mi) { return mi / 1.609; } } [System.ComponentModel.DesignerCategory("")] public class VarConverter : Dictionary { public readonly char VarSeparator = '%'; public void AddVar(string var, object value) { // adds a new var<>value pair to dictionary object o; if (this.TryGetValue(var, out o)) { // item found --> update value o = value; } else { // item not found --> add new this.Add(var, value); } } public object GetValue(string var) { // finds a var in dictionary and returns its value object o; if (this.TryGetValue(var, out o)) { // item found --> return value return o; } // item not found --> return null return null; } public string ReplaceAllVars(string s) { // check for var separotors first if (s.Contains(VarSeparator)) { // OK, string is containing vars --> crack the string first and replace vars try { string[] a = s.Split(VarSeparator); // as we are always using a pair of separators the length of a[] must be odd if (a.Length % 2 == 0) throw new ArgumentException("Number of separators is not an even number."); // create new string and replace all vars (on odd indices) s = ""; for (int i = 0; i < a.Length; i++) { if (i % 2 == 0) { // cannot be not a var on that position s = s + a[i]; } else { // var identifier: upper the string and try to convert a[i] = a[i].ToUpper(); object o; if (this.TryGetValue(a[i], out o)) { // convert floating points with invariant culture info if (o.GetType() == typeof(double)) s = s + ((double)o).ToString(CultureInfo.InvariantCulture); else if (o.GetType() == typeof(float)) s = s + ((float)o).ToString(CultureInfo.InvariantCulture); else s = s + o.ToString(); } else { throw new ArgumentException("Var identifier not found: " + a[i]); } } } } catch (Exception ex) { // throw an excecption throw new ArgumentException("Error while parsing string for variables [" + ex.Message + "]: " + s); } } return s; } } [System.ComponentModel.DesignerCategory("")] public static class ZIP { public static bool UncompressFile(string filename, int timeout, string password = "") { // unzips a zip file content to the same directory string downloaddir = String.Empty; // get the directory correct under Windows & Linux // don't use Path.GetDirectory under Linux if (filename.IndexOf("\\") >= 0) downloaddir = filename.Substring(0, filename.LastIndexOf("\\")); else if (filename.IndexOf("/") >= 0) downloaddir = filename.Substring(0, filename.LastIndexOf("/")); // set path to calling assembly's path if not otherwise specified if (String.IsNullOrEmpty(downloaddir)) downloaddir = Assembly.GetCallingAssembly().Location; try { Console.WriteLine("[UnzipFile: Trying to unzip file: " + filename); // open the zip file using (ZipFile zip = ZipFile.Read(filename)) { if (!String.IsNullOrEmpty(password)) zip.Password = password; // here, we extract every entry, but we could extract conditionally // based on entry name, size, date, checkbox status, etc. foreach (ZipEntry ze in zip) { ze.Extract(downloaddir, ExtractExistingFileAction.OverwriteSilently); string fname = Path.Combine(downloaddir, ze.FileName); // wait for extraction to finish int i = 0; while (!File.Exists(fname)) { Thread.Sleep(1000); i++; if (i > timeout) throw new TimeoutException("Timeout while waiting for extraction is complete: " + fname); } File.SetLastWriteTime(fname, ze.LastModified); } } return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return false; } public static bool CompressFile(string filename, bool storedirectoryinarchive, int timeout, string password = "") { // unzips a zip file content to the same directory string directory = String.Empty; // get the directory correct under Windows & Linux // don't use Path.GetDirectory under Linux if (filename.IndexOf("\\") >= 0) directory = filename.Substring(0, filename.LastIndexOf("\\")); else if (filename.IndexOf("/") >= 0) directory = filename.Substring(0, filename.LastIndexOf("/")); // set path to calling assembly's path if not otherwise specified if (String.IsNullOrEmpty(directory)) directory = Assembly.GetCallingAssembly().Location; try { Console.WriteLine("[ZipFile: Trying to zip file: " + filename); string zipfilename = Path.GetFileNameWithoutExtension(filename) + ".zip"; // create the zip file using (ZipFile zip = new ZipFile()) { if (!String.IsNullOrEmpty(password)) zip.Password = password; zip.AddFile(filename, storedirectoryinarchive ? directory : ""); zip.Save(Path.Combine(directory, zipfilename)); } // wait for compression to finish int i = 0; while (!File.Exists(Path.Combine(directory, zipfilename))) { Thread.Sleep(1000); i++; if (i > timeout) throw new TimeoutException("Timeout while waiting for compression is complete: " + zipfilename); } return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return false; } } [System.ComponentModel.DesignerCategory("")] public static class BZ2 { private static void Pump(Stream src, Stream dest) { byte[] buffer = new byte[2048]; int n; while ((n = src.Read(buffer, 0, buffer.Length)) > 0) dest.Write(buffer, 0, n); } public static bool UncompressFile(string filename) { // unzips a zip file content to the same directory string downloaddir = String.Empty; // get the directory correct under Windows & Linux // don't use Path.GetDirectory under Linux if (filename.IndexOf("\\") >= 0) downloaddir = filename.Substring(0, filename.LastIndexOf("\\")); else if (filename.IndexOf("/") >= 0) downloaddir = filename.Substring(0, filename.LastIndexOf("/")); // set path to calling assembly's path if not otherwise specified if (String.IsNullOrEmpty(downloaddir)) downloaddir = Assembly.GetCallingAssembly().Location; try { Console.WriteLine("[Unzip BZ2-File: Trying to unzip file: " + filename); // open the zip file var outFname = Path.GetFileNameWithoutExtension(filename); File.Delete(outFname); using (Stream fs = File.OpenRead(filename), output = File.Create(outFname), decompressor = new Ionic.BZip2.BZip2InputStream(fs)) Pump(decompressor, output); return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return false; } public static bool CompressFile(string filename, bool storedirectoryinarchive, int timeout, string password = "") { // unzips a zip file content to the same directory string directory = String.Empty; // get the directory correct under Windows & Linux // don't use Path.GetDirectory under Linux if (filename.IndexOf("\\") >= 0) directory = filename.Substring(0, filename.LastIndexOf("\\")); else if (filename.IndexOf("/") >= 0) directory = filename.Substring(0, filename.LastIndexOf("/")); // set path to calling assembly's path if not otherwise specified if (String.IsNullOrEmpty(directory)) directory = Assembly.GetCallingAssembly().Location; try { Console.WriteLine("[ZipFile: Trying to zip file: " + filename); string zipfilename = Path.GetFileNameWithoutExtension(filename) + ".zip"; // create the zip file using (ZipFile zip = new ZipFile()) { if (!String.IsNullOrEmpty(password)) zip.Password = password; zip.AddFile(filename, storedirectoryinarchive ? directory : ""); zip.Save(Path.Combine(directory, zipfilename)); } // wait for compression to finish int i = 0; while (!File.Exists(Path.Combine(directory, zipfilename))) { Thread.Sleep(1000); i++; if (i > timeout) throw new TimeoutException("Timeout while waiting for compression is complete: " + zipfilename); } return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return false; } } /// /// Derived WebClient class for automatic compression handling. /// Can download files from web resources with compressed content delivery. /// Tries to download various zipped versions from a given , e.g. or /// [System.ComponentModel.DesignerCategory("")] public class AutoDecompressionWebClient : WebClient { public AutoDecompressionWebClient() { // add website compression request Headers.Add("Accept-Encoding: gzip, deflate"); } protected override WebRequest GetWebRequest(Uri address) { // ovverides GetWebRequest to add automatic decompression HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest; request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip; // allow redirect 2017/12/06 DL2ALF request.AllowAutoRedirect = true; return request; } /// /// Gets the creation time of a file /// /// The file name. /// The creation time in UTC if file found. DateTime.MinValue if not. public DateTime GetFileCreationTimeUtc(string filename) { if (File.Exists(filename)) return File.GetCreationTimeUtc(filename); else return DateTime.MinValue; } /// /// Gets the creation time of a web resource. /// /// The address string of web resource. /// Allows redirection of requested source. /// The creation time in UTC if successful. DateTime.MinValue if not. public DateTime GetWebCreationTimeUtc(string address, bool allowredirect = true) { return GetWebCreationTimeUtc(new Uri(address), allowredirect); } /// /// Gets the creation time of a web resource. /// /// The address URI of web/file resource. /// Allows redirection of requested source. /// The creation time in UTC if successful. DateTime.MinValue if not. public DateTime GetWebCreationTimeUtc(Uri address, bool allowredirect = true) { // get the last modified time of the website/file // returns DateTime.MinValue if address not found try { DateTime webcreationtime = DateTime.MinValue; if (address.IsFile) { if (File.Exists(address.LocalPath)) { webcreationtime = File.GetLastWriteTimeUtc(address.LocalPath); } } else { HttpWebRequest req = (HttpWebRequest)WebRequest.Create(address); // allow redirect 2017/12/06 DL2ALF req.AllowAutoRedirect = allowredirect; using (HttpWebResponse res = (HttpWebResponse)req.GetResponse()) { webcreationtime = res.LastModified.ToUniversalTime(); } Console.WriteLine("[GetWebCreationTime] Getting web creation time from address: " + address + " = " + webcreationtime.ToString("yyyy-MM-dd HH:mm:ss")); } return webcreationtime; } catch (Exception ex) { // Console.WriteLine("[GetWebCreationTime] Error while reading address: " + address + "\n" + ex.ToString()); } return DateTime.MinValue; } private bool DownloadFileFromWeb(string address, string filename, bool allowredirect, bool autounzip, string password = "") { // donwloads file from a web/file resource try { Uri uri = new Uri(address); if (uri.IsFile) { if (File.Exists(uri.LocalPath)) { File.Copy(uri.LocalPath, filename, true); if (autounzip && Path.GetExtension(filename).ToLower() == ".zip") { Console.WriteLine("[DownloadFileFromWeb] Trying to unzip downloaded file: " + filename); return ZIP.UncompressFile(filename, 60, password); } Console.WriteLine("[DownloadFileFromWeb] Downloading file from address finished: " + address); return true; } } else { // get web cration time DateTime webcreationtime = GetWebCreationTimeUtc(address, allowredirect); // download file and check for errors and uri identical to request // do not use WebClient.Download for this! var request = (HttpWebRequest)WebRequest.Create(address); // allow redirect 2017/12/06 DL2ALF request.AllowAutoRedirect = allowredirect; request.Method = "GET"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { HttpStatusCode status = response.StatusCode; if ((status == HttpStatusCode.OK) && (response.ResponseUri == new Uri(address))) { using (var responseStream = response.GetResponseStream()) { using (var fileToDownload = new System.IO.FileStream(filename, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite)) { responseStream.CopyTo(fileToDownload); } } } } // set creation time if (File.Exists(filename)) { File.SetCreationTime(filename, webcreationtime); File.SetLastWriteTime(filename, webcreationtime); // unzip the file content if enabled if (autounzip && (Path.GetExtension(filename).ToLower() == ".zip")) { Console.WriteLine("[DownloadFileFromWeb] Trying to unzip downloaded file: " + filename); return ZIP.UncompressFile(filename, 60, password); } Console.WriteLine("[DownloadFileFromWeb] Downloading file from address finished: " + address); return true; } } } catch (Exception ex) { if (ex is WebException ) Console.WriteLine("[DownloadFileFromWeb] WebException while reading address: " + address + "\n" + "URI of orginal request=" + address + "\n" + "URI of responding server=" + "\n" + ex.ToString()); else Console.WriteLine("[DownloadFileFromWeb] Error while reading address: " + address + "\n" + ex.ToString()); } return false; } private DOWNLOADFILESTATUS DownloadFileFromWebIfNewer(string address, string filename, bool allowredirect, bool autounzip, string password = "") { DateTime filecreationtime; DateTime webcreationtime; if (File.Exists(filename)) filecreationtime = File.GetCreationTimeUtc(filename); else filecreationtime = DateTime.MinValue; webcreationtime = GetWebCreationTimeUtc(address, allowredirect); // nothing found on web if (webcreationtime == DateTime.MinValue) return DOWNLOADFILESTATUS.NOTFOUND; if (webcreationtime > filecreationtime) { // web content is newer --> download and do not unzip if (!DownloadFileFromWeb(address, filename, allowredirect, false, password)) return DOWNLOADFILESTATUS.ERROR; } // unzip the file if enabled and content is a ZIP-file if (autounzip && (Path.GetExtension(filename).ToLower() == ".zip")) { if (!ZIP.UncompressFile(filename, 60, password)) return DOWNLOADFILESTATUS.ERROR; } // unzip the file if enabled and content is a ZIP-file else if (autounzip && (Path.GetExtension(filename).ToLower() == ".bz2")) { if (!BZ2.UncompressFile(filename)) return DOWNLOADFILESTATUS.ERROR; } // set the return value if (webcreationtime > filecreationtime) return DOWNLOADFILESTATUS.NEWER; else return DOWNLOADFILESTATUS.NOTNEWER; } /// /// Downloads a file from a web resource. /// Sets local file time stamps according to original after download. /// /// The address of web resource. /// The filename for local store. /// Allows redirection of requested source. /// Try to download a zipped version first. /// True if download was successful. public bool DownloadFile(string address, string filename, bool allowredirect, bool autounzip, string password = "") { string downloadfilename; string downloadaddress; if (autounzip) { // try to download first downloadfilename = filename + ".zip"; downloadaddress = address + ".zip"; if (GetWebCreationTimeUtc(downloadaddress, allowredirect) != DateTime.MinValue) { // resource found --> download the zip file and extract it if (DownloadFileFromWeb(downloadaddress, downloadfilename, true,autounzip, password)) return true; } // try to download downloadfilename = filename.Replace(Path.GetExtension(filename), ".zip"); downloadaddress = address.Substring(0, address.LastIndexOf(".")) + ".zip"; if (GetWebCreationTimeUtc(downloadaddress, allowredirect) != DateTime.MinValue) { // resource found --> download the zip file and extract it if (DownloadFileFromWeb(downloadaddress, downloadfilename, true, autounzip, password)) return true; } } // try to download downloadfilename = filename; downloadaddress = address; if (GetWebCreationTimeUtc(downloadaddress, allowredirect) != DateTime.MinValue) { // resource found --> download the file if (DownloadFileFromWeb(downloadaddress, downloadfilename, allowredirect, true, password)) return true; } // nothing found return false; } /// /// Downloads a file from a web resource only if it is newer or not found locally. /// /// The address of web resource. /// The filename for local store. /// Allows redirection of requested source. /// Try to download a zipped version first. /// A DOWNLOADFILESTATUS object containing status information. public DOWNLOADFILESTATUS DownloadFileIfNewer(string address, string filename, bool allowredirect, bool autounzip, string password = "") { string downloadaddress; string downloadfilename; DOWNLOADFILESTATUS ds = DOWNLOADFILESTATUS.UNKNOWN; try { // downloadaddress = address; downloadfilename = filename; ds = DownloadFileFromWebIfNewer(downloadaddress, downloadfilename, allowredirect, autounzip, password); // return here if successful if ((ds == DOWNLOADFILESTATUS.NEWER) || (ds == DOWNLOADFILESTATUS.NOTNEWER)) return ds; // try to download other extensions if (autounzip) { // downloadaddress = address.Substring(0, address.LastIndexOf(".")) + ".zip"; downloadfilename = filename.Replace(Path.GetExtension(filename), ".zip"); ds = DownloadFileFromWebIfNewer(downloadaddress, downloadfilename, allowredirect, autounzip, password); // return here if successful if ((ds == DOWNLOADFILESTATUS.NEWER) || (ds == DOWNLOADFILESTATUS.NOTNEWER)) return ds; // downloadaddress = address + ".zip"; downloadfilename = filename + ".zip"; ds = DownloadFileFromWebIfNewer(downloadaddress, downloadfilename, allowredirect, autounzip, password); // return here if successful if ((ds == DOWNLOADFILESTATUS.NEWER) || (ds == DOWNLOADFILESTATUS.NOTNEWER)) return ds; } return DOWNLOADFILESTATUS.NOTFOUND; } catch (Exception ex) { if (ex is WebException) Console.WriteLine("[DownloadFileIfNewer] WebException while reading address: " + address + "\n" + "URI of orginal request=" + address + "\n" + "URI of responding server=" + ((WebException)ex).Response.ResponseUri + "\n" + ex.ToString()); else Console.WriteLine("[DownloadFileIfNewer] Error while reading address: " + address + "\n" + ex.ToString()); } return DOWNLOADFILESTATUS.ERROR; } } public class FTPDirectoryItem { public Uri BaseUri; public string AbsolutePath { get { return string.Format("{0}/{1}", BaseUri, Name); } } public DateTime DateCreated; public bool IsDirectory; public string Name; public List Items; } public class FTPDirectorySearcher { public List GetDirectoryInformation(string address, string username, string password) { FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(address); request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; request.Credentials = new NetworkCredential(username, password); request.UsePassive = true; request.UseBinary = true; request.KeepAlive = false; List returnValue = new List(); string[] list = null; using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) using (StreamReader reader = new StreamReader(response.GetResponseStream())) { list = reader.ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); } foreach (string line in list) { // Windows FTP Server Response Format // DateCreated IsDirectory Name string data = line; // Parse date string date = data.Substring(0, 17); DateTime dateTime = DateTime.Parse(date); data = data.Remove(0, 24); // Parse string dir = data.Substring(0, 5); bool isDirectory = dir.Equals("", StringComparison.InvariantCultureIgnoreCase); data = data.Remove(0, 5); data = data.Remove(0, 10); // Parse name string name = data; // Create directory info FTPDirectoryItem item = new FTPDirectoryItem(); item.BaseUri = new Uri(address); item.DateCreated = dateTime; item.IsDirectory = isDirectory; item.Name = name; Debug.WriteLine(item.AbsolutePath); item.Items = item.IsDirectory ? GetDirectoryInformation(item.AbsolutePath, username, password) : null; returnValue.Add(item); } return returnValue; } } public class HTTPDirectoryItem { public Uri BaseUri; public string AbsolutePath { get { return string.Format("{0}/{1}", BaseUri, Name); } } public string Name; } public class HTTPDirectorySearcher { public List GetDirectoryInformation(string address) { if (String.IsNullOrEmpty(address)) return new List(); try { string content; /* HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address); // request.KeepAlive = false; // request.ProtocolVersion = HttpVersion.Version10; // request.Timeout = 10000; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (StreamReader reader = new StreamReader(response.GetResponseStream())) { content = reader.ReadToEnd(); } } */ WebClient client = new WebClient(); // fake a up-to-date user agent client.Headers["User-Agent"] = "Mozilla / 5.0(Windows NT 10.0; WOW64; rv: 50.0) Gecko / 20100101 Firefox / 50.0"; content = client.DownloadString(address); Regex regex = new Regex("(?.*)"); List files = new List(); MatchCollection matches = regex.Matches(content); if (matches.Count > 0) { foreach (Match match in matches) { if (match.Success) { string[] matchData = match.Groups[0].ToString().Split('\"'); // sort out all weblinks and comments HTTPDirectoryItem item = new HTTPDirectoryItem(); item.Name = matchData[1]; item.BaseUri = new Uri(address); files.Add(item); } } } return files; } catch(Exception ex) { } return new List(); } } public enum DOWNLOADFILESTATUS { UNKNOWN = 0, NOTFOUND = 1, NEWER = 2, NOTNEWER = 4, ERROR = 8 } }