// Copyright (c) 2011, Outercurve Foundation. // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // - Neither the name of the Outercurve Foundation nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Runtime.InteropServices; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Reflection; using Ionic.Zip; using WebsitePanel.Providers.OS; namespace WebsitePanel.Providers.Utils { /// /// Summary description for FileUtils. /// public class FileUtils { public static string EvaluateSystemVariables(string str) { if (String.IsNullOrEmpty(str)) return str; Regex re = new Regex("%(.+)%", RegexOptions.IgnoreCase); return re.Replace(str, new MatchEvaluator(EvaluateSystemVariable)); } public static string GetExecutablePathWithoutParameters(string path) { if (String.IsNullOrEmpty(path)) return path; int idx = -1; int exeIdx = path.ToLower().IndexOf(".exe"); int dllIdx = path.ToLower().IndexOf(".dll"); if (exeIdx != -1) idx = exeIdx; if (dllIdx != -1) idx = dllIdx; if (exeIdx != -1 && dllIdx != -1) { idx = exeIdx; if (dllIdx < exeIdx) idx = dllIdx; } string execPath = path; if (idx != -1) { execPath = path.Substring(0, idx + 4); if (execPath.StartsWith("\"")) execPath = execPath.Substring(1); } return execPath; } public static string CorrectRelativePath(string relativePath) { // clean path string correctedPath = Regex.Replace(relativePath.Replace("/", "\\"), @"\.\\|\.\.|\\\\|\?|\:|\""|\<|\>|\||%|\$", ""); if (correctedPath.StartsWith("\\")) correctedPath = correctedPath.Substring(1); return correctedPath; } private static string EvaluateSystemVariable(Match match) { return Environment.GetEnvironmentVariable(match.Groups[1].Value); } public static bool FileExists(string path) { return File.Exists(path); } public static bool DirectoryExists(string path) { return Directory.Exists(path); } public static string CreatePackageFolder(string initialPath) { // substitute vars initialPath = FileUtils.EvaluateSystemVariables(initialPath); int i = 0; string path = null; while (true) { path = initialPath + ((i == 0) ? "" : i.ToString()); if (!FileUtils.DirectoryExists(path)) { // create directory FileUtils.CreateDirectory(path); break; } i++; } // Set permissions // We decided to inherit NTFS permissions from the parent folder to comply with with the native security schema in Windows, // when a user decides on his own how to implement security practices for NTFS permissions schema and harden the server. SecurityUtils.GrantNtfsPermissionsBySid(path, SystemSID.ADMINISTRATORS, NTFSPermission.FullControl, true, true); SecurityUtils.GrantNtfsPermissionsBySid(path, SystemSID.SYSTEM, NTFSPermission.FullControl, true, true); // return path; } public static SystemFile GetFile(string path) { if (!File.Exists(path)) return null; FileInfo file = new FileInfo(path); return new SystemFile(file.Name, file.FullName, false, file.Length, file.CreationTime, file.LastWriteTime); } public static SystemFile[] GetFiles(string path) { ArrayList items = new ArrayList(); DirectoryInfo root = new DirectoryInfo(path); // get directories DirectoryInfo[] dirs = root.GetDirectories(); foreach (DirectoryInfo dir in dirs) { string fullName = System.IO.Path.Combine(path, dir.Name); SystemFile fi = new SystemFile(dir.Name, fullName, true, 0, dir.CreationTime, dir.LastWriteTime); items.Add(fi); // check if the directory is empty fi.IsEmpty = (Directory.GetFileSystemEntries(fullName).Length == 0); } // get files FileInfo[] files = root.GetFiles(); foreach (FileInfo file in files) { string fullName = System.IO.Path.Combine(path, file.Name); SystemFile fi = new SystemFile(file.Name, fullName, false, file.Length, file.CreationTime, file.LastWriteTime); items.Add(fi); } return (SystemFile[])items.ToArray(typeof(SystemFile)); } public static SystemFile[] GetFilesRecursive(string rootFolder, string path) { return GetFilesRecursiveByPattern(rootFolder, path, "*.*"); } public static SystemFile[] GetFilesRecursiveByPattern(string rootFolder, string path, string pattern) { // parse pattern string[] patterns = new string[] { pattern }; if (pattern.IndexOf("|") != -1 || pattern.IndexOf(";") != -1) patterns = pattern.Split(new char[] { '|', ';' }); // get files ArrayList files = new ArrayList(); foreach (string ptrn in patterns) GetFilesList(files, rootFolder, path, ptrn); return (SystemFile[])files.ToArray(typeof(SystemFile)); } private static void GetFilesList(ArrayList files, string rootFolder, string folder, string pattern) { string fullPath = System.IO.Path.Combine(rootFolder, folder); // add files in the current folder FileInfo[] dirFiles = new DirectoryInfo(fullPath).GetFiles(pattern); foreach (FileInfo file in dirFiles) { SystemFile fi = new SystemFile(folder + "\\" + file.Name, file.Name, false, file.Length, file.CreationTime, file.LastWriteTime); files.Add(fi); } // add children folders DirectoryInfo[] dirs = new DirectoryInfo(fullPath).GetDirectories(); foreach (DirectoryInfo dir in dirs) { GetFilesList(files, rootFolder, System.IO.Path.Combine(folder, dir.Name), pattern); } } public static SystemFile[] GetDirectoriesRecursive(string rootFolder, string path) { ArrayList folders = new ArrayList(); GetDirectoriesRecursive(folders, rootFolder, path); return (SystemFile[])folders.ToArray(typeof(SystemFile)); } private static void GetDirectoriesRecursive(ArrayList folders, string rootFolder, string folder) { // add the current folder SystemFile fi = new SystemFile("\\" + folder, folder, true, 0, DateTime.Now, DateTime.Now); folders.Add(fi); // add children folders string fullPath = System.IO.Path.Combine(rootFolder, folder); DirectoryInfo dir = new DirectoryInfo(fullPath); fi.Created = dir.CreationTime; fi.Changed = dir.LastWriteTime; DirectoryInfo[] subDirs = dir.GetDirectories(); foreach (DirectoryInfo subDir in subDirs) { GetDirectoriesRecursive(folders, rootFolder, System.IO.Path.Combine(folder, subDir.Name)); } } public static byte[] GetFileBinaryContent(string path) { if (!File.Exists(path)) return null; FileStream stream = new FileStream(path, FileMode.Open); if (stream == null) return null; long length = stream.Length; byte[] content = new byte[length]; stream.Read(content, 0, (int)length); stream.Close(); return content; } /// /// Returns file contents trying to read according to file contents /// /// Path to the file. /// Current file encoding. /// Array of bytes. /// /// It uses UTF8 by default, so in case incorrect or not supported encoding name /// UTF8 will be used to read file contents and convert it to the byte array. /// public static byte[] GetFileBinaryContent(string path, string encoding) { if (!File.Exists(path)) return null; Encoding fileEncoding = GetEncodingByNameOrDefault(encoding, Encoding.UTF8); string fileContent = String.Empty; using (StreamReader sr = new StreamReader(path, fileEncoding)) { fileContent = sr.ReadToEnd(); } return fileEncoding.GetBytes(fileContent).Clone() as byte[]; } /// /// Returns from name specified. /// If cannot find , returns . /// /// The name of the encoding to return. /// that will be returned if no will be found. /// /// from the name specified, /// otherwise . /// private static Encoding GetEncodingByNameOrDefault(string encoding, Encoding defaultEncoding) { Encoding currentEncoding = defaultEncoding; try { currentEncoding = Encoding.GetEncoding(encoding); } catch(ArgumentException) { // this encoding is either no supported or incorrect // set to default encoding currentEncoding = defaultEncoding; } return currentEncoding; } public static Stream GetFileBinaryContentStream(string path) { if (!File.Exists(path)) return null; return new FileStream(path, FileMode.Open); } public static byte[] GetFileBinaryChunk(string path, int offset, int length) { if (!File.Exists(path)) return null; FileStream stream = new FileStream(path, FileMode.Open); if (stream == null) return null; if (offset > 0) stream.Seek(offset, SeekOrigin.Begin); byte[] content = new byte[length]; int readBytes = stream.Read(content, 0, length); stream.Close(); if (readBytes < length) { byte[] lastContent = new byte[readBytes]; if (readBytes > 0) { Array.Copy(content, 0, lastContent, 0, readBytes); } // avoiding of getting empty content if (lastContent.Length == 0) { lastContent = new byte[] { 1 }; } return lastContent; } else { return content; } } public static string GetFileTextContent(string path) { StreamReader reader = new StreamReader(path); string content = reader.ReadToEnd(); reader.Close(); return content; } public static void UpdateFileBinaryContent(string path, byte[] content) { FileStream stream = new FileStream(path, FileMode.Create); stream.Write(content, 0, content.Length); stream.Close(); } /// /// Updates file contents using encoding. /// /// Path to the file. /// File contents. /// Current file encoding. /// /// It uses UTF8 by default, so in case incorrect or not supported encoding name is submitted, /// then UTF8 will be used to convert bytes to file contents. /// public static void UpdateFileBinaryContent(string path, byte[] content, string encoding) { Encoding fileEncoding = GetEncodingByNameOrDefault(encoding, Encoding.UTF8); using (StreamWriter sw = new StreamWriter(File.Create(path), fileEncoding)) { sw.Write( fileEncoding.GetString(content) ); } } public static void AppendFileBinaryContent(string path, byte[] chunk) { FileStream stream = new FileStream(path, FileMode.Append, FileAccess.Write); stream.Write(chunk, 0, chunk.Length); stream.Close(); } public static void UpdateFileTextContent(string path, string content) { StreamWriter stream = new StreamWriter(path); stream.Write(content); stream.Close(); } public static void CreateFile(string path) { FileStream stream = File.Create(path); stream.Close(); } public static void ChangeFileAttributes(string path, DateTime createdTime, DateTime changedTime) { if (Directory.Exists(path)) { Directory.SetCreationTime(path, createdTime); Directory.SetLastWriteTime(path, changedTime); } else if (File.Exists(path)) { File.SetCreationTime(path, createdTime); File.SetLastWriteTime(path, changedTime); } } public static void DeleteFile(string path) { if (File.Exists(path)) File.Delete(path); else if (Directory.Exists(path)) Directory.Delete(path, true); } public static void DeleteFiles(string[] files) { foreach (string file in files) DeleteFile(file); } public static void DeleteEmptyDirectories(string[] directories) { foreach (string directory in directories) DeleteEmptyDirectoryRecursive(directory); } private static bool DeleteEmptyDirectoryRecursive(string directory) { if (!Directory.Exists(directory)) return true; // iterate through child folders bool empty = true; string[] dirs = Directory.GetDirectories(directory); foreach (string dir in dirs) { if (!DeleteEmptyDirectoryRecursive(dir)) empty = false; } string[] files = Directory.GetFiles(directory); empty = empty && (files.Length == 0); // try to delete directory if (empty) Directory.Delete(directory); return empty; } public static void MoveFile(string sourcePath, string destinationPath) { if (File.Exists(sourcePath)) { File.Move(sourcePath, destinationPath); } else if (Directory.Exists(sourcePath)) { Directory.Move(sourcePath, destinationPath); } else { throw new Exception("Specified file is not found!"); } // reset NTFS permissions on destination file/folder SecurityUtils.ResetNtfsPermissions(destinationPath); } public static void CopyFile(string sourcePath, string destinationPath) { if (File.Exists(sourcePath)) { File.Copy(sourcePath, destinationPath, true); } else if (Directory.Exists(sourcePath)) { CopyDirectory(sourcePath, destinationPath); } else { throw new Exception("Specified file is not found!"); } // reset NTFS permissions on destination file/folder SecurityUtils.ResetNtfsPermissions(destinationPath); } private static void CopyDirectory(string sourceDir, string destinationDir) { // create directory DirectoryInfo srcDir = new DirectoryInfo(sourceDir); if(!Directory.Exists(destinationDir)) Directory.CreateDirectory(destinationDir); // create subdirectories DirectoryInfo[] dirs = srcDir.GetDirectories(); foreach (DirectoryInfo dir in dirs) { CopyDirectory(System.IO.Path.Combine(sourceDir, dir.Name), System.IO.Path.Combine(destinationDir, dir.Name)); } // copy files FileInfo[] files = srcDir.GetFiles(); foreach (FileInfo file in files) { // copy file file.CopyTo(System.IO.Path.Combine(destinationDir, file.Name), true); } } public static void CreateDirectory(string path) { if (!Directory.Exists(path)) { // create directory structure Directory.CreateDirectory(path); } } public static void ZipFiles(string zipFile, string rootPath, string[] files) { using (ZipFile zip = new ZipFile()) { //use unicode if necessary zip.UseUnicodeAsNecessary = true; zip.UseZip64WhenSaving = Zip64Option.AsNecessary; //skip locked files zip.ZipErrorAction = ZipErrorAction.Skip; foreach (string file in files) { string fullPath = Path.Combine(rootPath, file); if (Directory.Exists(fullPath)) { //add directory with the same directory name zip.AddDirectory(fullPath, file); } else if (File.Exists(fullPath)) { //add file to the root folder zip.AddFile(fullPath, ""); } } zip.Save(zipFile); } } public static string[] UnzipFiles(string zipFile, string destFolder) { using (ZipFile zip = ZipFile.Read(zipFile)) { foreach (ZipEntry e in zip) { // Remove Read-Only attribute from a zip entry if ((e.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) e.Attributes ^= FileAttributes.ReadOnly; // e.Extract(destFolder, ExtractExistingFileAction.OverwriteSilently); } } List files = new List(); foreach(SystemFile systemFile in GetFiles(destFolder)) { files.Add(systemFile.FullName); } return files.ToArray(); } private static void CreateDirectoriesStructure(string path) { string dir = System.IO.Path.GetDirectoryName(path); if (!Directory.Exists(dir)) { // create directory structure Directory.CreateDirectory(dir); } } public static string ExecuteSystemCommand(string cmd, string args) { return ExecuteSystemCommand(cmd, args, null); } public static string ExecuteSystemCommand(string cmd, string args, string outputFile) { // launch system process ProcessStartInfo startInfo = new ProcessStartInfo(cmd, args); startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.RedirectStandardOutput = true; startInfo.StandardOutputEncoding = Encoding.UTF8; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; // get working directory from executable path startInfo.WorkingDirectory = Path.GetDirectoryName(cmd); Process proc = Process.Start(startInfo); // analyze results StreamReader reader = proc.StandardOutput; string results = ""; if (!String.IsNullOrEmpty(outputFile)) { // stream to writer StreamWriter writer = new StreamWriter(outputFile); int BUFFER_LENGTH = 2048; int readBytes = 0; char[] buffer = new char[BUFFER_LENGTH]; while ((readBytes = reader.Read(buffer, 0, BUFFER_LENGTH)) > 0) { writer.Write(buffer, 0, readBytes); } writer.Close(); } else { // return as string results = reader.ReadToEnd(); } reader.Close(); return results; } public static void ExecuteCmdCommand(string command) { ProcessStartInfo ProcessInfo; Process process; ProcessInfo = new ProcessStartInfo("cmd.exe", "/C " + command); ProcessInfo.CreateNoWindow = true; ProcessInfo.UseShellExecute = false; process = Process.Start(ProcessInfo); if (process != null) { process.WaitForExit(500); process.Close(); } } public static void SaveStreamToFile(Stream stream, string path) { try { //Create a file to save to Stream toStream = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); //use the binary reader & writer because //they can work with all formats //i.e images, text files ,avi,mp3.. BinaryReader br = new BinaryReader(stream); BinaryWriter bw = new BinaryWriter(toStream); //copy data from the FromStream to the outStream //convert from long to int bw.Write(br.ReadBytes((int)stream.Length)); //save bw.Flush(); //clean up bw.Close(); br.Close(); } //use Exception e as it can handle any exception catch { //code if u like } } public static long CalculateFolderSize(string path) { int files = 0; int folders = 0; // check directory exists if (!Directory.Exists(path)) return 0; // normalize path path = path.Replace("/", "\\"); // remove trailing slash if (path.EndsWith(@"\")) path = path.Substring(0, path.Length - 1); // calculate folder size return CalculateFolderSize(path, out files, out folders); } private static long CalculateFolderSize(string path, out int files, out int folders) { files = 0; folders = 0; IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); long size = 0; FindData findData = new FindData(); IntPtr findHandle; findHandle = path.StartsWith("\\\\") ? Kernel32.FindFirstFile(path + @"\*", findData) : Kernel32.FindFirstFile(@"\\?\" + path + @"\*", findData); if (findHandle != INVALID_HANDLE_VALUE) { do { if ((findData.fileAttributes & (int)FileAttributes.Directory) != 0) { if (findData.fileName != "." && findData.fileName != "..") { folders++; int subfiles, subfolders; string subdirectory = path + (path.EndsWith(@"\") ? "" : @"\") + findData.fileName; size += CalculateFolderSize(subdirectory, out subfiles, out subfolders); folders += subfolders; files += subfiles; } } else { // File files++; size += (long)findData.nFileSizeLow + (long)findData.nFileSizeHigh * 4294967296; } } while (Kernel32.FindNextFile(findHandle, findData)); Kernel32.FindClose(findHandle); } return size; } public static void CreateAccessDatabase(string databasePath) { if (String.IsNullOrEmpty(databasePath)) throw new ArgumentException("databasePath"); string connectionString = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Jet OLEDB:Engine Type=5;Mode=Share Deny None;Jet OLEDB:Database Locking Mode=0", databasePath); Type adoxType = Type.GetTypeFromProgID("ADOX.Catalog"); object cat = Activator.CreateInstance(adoxType); adoxType.InvokeMember("Create", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, cat, new object[] { connectionString }); object conn = adoxType.InvokeMember("ActiveConnection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, cat, null); adoxType.InvokeMember("Close", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, conn, null); cat = null; } #region Advanced Delete /// /// Deletes the specified file. /// /// The name of the file to be deleted. public static void DeleteFileAdvanced(string fileName) { int attempts = 0; while (true) { try { DeleteFileInternal(fileName); break; } catch (Exception) { if (attempts > 2) throw; attempts++; System.Threading.Thread.Sleep(1000); } } } /// /// Deletes the specified file. /// /// The name of the file to be deleted. private static void DeleteReadOnlyFile(string fileName) { FileInfo info = new FileInfo(fileName); info.Attributes = FileAttributes.Normal; info.Delete(); } /// /// Deletes the specified file. /// /// The name of the file to be deleted. private static void DeleteFileInternal(string fileName) { try { File.Delete(fileName); } catch (UnauthorizedAccessException) { DeleteReadOnlyFile(fileName); } } /// /// Deletes the specified directory. /// /// The name of the directory to be deleted. public static void DeleteDirectoryAdvanced(string directory) { if (!Directory.Exists(directory)) return; // iterate through child folders string[] dirs = Directory.GetDirectories(directory); foreach (string dir in dirs) { DeleteDirectoryAdvanced(dir); } // iterate through child files string[] files = Directory.GetFiles(directory); foreach (string file in files) { DeleteFileAdvanced(file); } //try to delete dir for 3 times int attempts = 0; while (true) { try { DeleteDirectoryInternal(directory); break; } catch (Exception) { if (attempts > 2) throw; attempts++; System.Threading.Thread.Sleep(1000); } } } /// /// Deletes the specified directory. /// /// The name of the directory to be deleted. public static void DeleteDirectoryInternal(string directory) { try { Directory.Delete(directory); } catch (IOException) { DeleteReadOnlyDirectory(directory); } } /// /// Deletes the specified directory. /// /// The name of the directory to be deleted. private static void DeleteReadOnlyDirectory(string directory) { DirectoryInfo info = new DirectoryInfo(directory); info.Attributes = FileAttributes.Normal; info.Delete(); } #endregion } #region File Size Calculation helper classes [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] class FindData { public int fileAttributes; public int creationTime_lowDateTime; public int creationTime_highDateTime; public int lastAccessTime_lowDateTime; public int lastAccessTime_highDateTime; public int lastWriteTime_lowDateTime; public int lastWriteTime_highDateTime; public uint nFileSizeHigh; public uint nFileSizeLow; public int dwReserved0; public int dwReserved1; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public String fileName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public String alternateFileName; } class Kernel32 { [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr FindFirstFile(String fileName, [In, Out] FindData findFileData); [DllImport("kernel32", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FindNextFile(IntPtr hFindFile, [In, Out] FindData lpFindFileData); [DllImport("kernel32", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FindClose(IntPtr hFindFile); } #endregion }