#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. */ #endregion using System; using System.Collections.Generic; using System.IO; using System.Linq; using ICSharpCode.SharpZipLib; using ICSharpCode.SharpZipLib.Zip; namespace OpenRA.FileFormats { public static class InstallUtils { static IEnumerable GetEntries(this ZipInputStream z) { for (; ; ) { var e = z.GetNextEntry(); if (e != null) yield return e; else break; } } public static string GetMountedDisk(Func isValidDisk) { var volumes = DriveInfo.GetDrives() .Where(v => v.DriveType == DriveType.CDRom && v.IsReady) .Select(v => v.RootDirectory.FullName); return volumes.FirstOrDefault(v => isValidDisk(v)); } // TODO: The package should be mounted into its own context to avoid name collisions with installed files public static bool ExtractFromPackage(string srcPath, string package, string[] files, string destPath, Action onProgress, Action onError) { if (!Directory.Exists(destPath)) Directory.CreateDirectory(destPath); if (!Directory.Exists(srcPath)) { onError("Cannot find "+package); return false; } FileSystem.Mount(srcPath); if (!FileSystem.Exists(package)) { onError("Cannot find "+package); return false; } FileSystem.Mount(package); foreach (string s in files) { var destFile = Path.Combine(destPath, s); using (var sourceStream = FileSystem.Open(s)) using (var destStream = File.Create(destFile)) { onProgress("Extracting "+s); destStream.Write(sourceStream.ReadAllBytes()); } } return true; } public static bool CopyFiles(string srcPath, string[] files, string destPath, Action onProgress, Action onError) { foreach (var file in files) { var fromPath = Path.Combine(srcPath, file); if (!File.Exists(fromPath)) { onError("Cannot find "+file); return false; } var destFile = Path.GetFileName(file).ToLowerInvariant(); onProgress("Extracting "+destFile); File.Copy(fromPath, Path.Combine(destPath, destFile), true); } return true; } public static bool ExtractZip(string zipFile, string dest, Action onProgress, Action onError) { if (!File.Exists(zipFile)) { onError("Invalid path: "+zipFile); return false; } List extracted = new List(); try { var z = new ZipInputStream(File.OpenRead(zipFile)); z.ExtractZip(dest, extracted, s => onProgress("Extracting "+s)); } catch (SharpZipBaseException) { foreach(var f in extracted) File.Delete(f); onError("Invalid archive"); return false; } return true; } // TODO: this belongs in FileSystem/ZipFile static void ExtractZip(this ZipInputStream z, string destPath, List extracted, Action onProgress) { foreach (var entry in z.GetEntries()) { if (!entry.IsFile) continue; onProgress(entry.Name); Directory.CreateDirectory(Path.Combine(destPath, Path.GetDirectoryName(entry.Name))); var path = Path.Combine(destPath, entry.Name); extracted.Add(path); using (var f = File.Create(path)) { int bufSize = 2048; byte[] buf = new byte[bufSize]; while ((bufSize = z.Read(buf, 0, buf.Length)) > 0) f.Write(buf, 0, bufSize); } } z.Close(); } } }