public static int CheckExtractExistingFile(this ZipEntry zipEntry, string baseDir, string targetFileName) { return zipEntry.CheckExtractExistingFile(baseDir, targetFileName); }
/// <summary> /// Pass in either basedir or s, but not both. /// In other words, you can extract to a stream or to a directory (filesystem), but not both! /// The Password param is required for encrypted entries. /// </summary> private static void InternalExtractToBaseDir(this ZipEntry zipEntry, string baseDir, string password) { if (baseDir == null) throw new ArgumentNullException("baseDir"); var zipFile = zipEntry.GetZipFile(); // workitem 10355 if (zipFile == null) throw new InvalidOperationException("Use Extract() only with ZipFile."); // get the full filename var f = ZipEntryInternal.NameInArchive(zipEntry.FileName); var targetFileName = zipFile.FlattenFoldersOnExtract ? Path.Combine(baseDir, Path.GetFileName(f)) : Path.Combine(baseDir, f); // workitem 10639 targetFileName = targetFileName.Replace('/', PortablePath.DirectorySeparatorChar); var fullTargetPath = ZipFileExtensions.GetFullPath(targetFileName); var fileExistsBeforeExtraction = false; try { // check if it is a directory if (zipEntry.IsDirectory || zipEntry.FileName.EndsWith("/")) { CreateDirectory(fullTargetPath); goto ExitTry; // all done, caller will return } // it is a file, so start the extraction if (FileSystem.Current.GetFileFromPathAsync(fullTargetPath).ExecuteSync() != null) { fileExistsBeforeExtraction = true; int rc = zipEntry.CheckExtractExistingFile(baseDir, targetFileName); if (rc == 2) goto ExitTry; // cancel if (rc == 1) return; // do not overwrite } // set up the output stream var tmpName = Path.GetRandomFileName(); var tmpPath = Path.Combine(Path.GetDirectoryName(fullTargetPath), tmpName); var dirName = Path.GetDirectoryName(tmpPath); // ensure the target path exists var dir = CreateDirectory(dirName, true); // extract var file = dir.CreateFileAsync(tmpPath, CreationCollisionOption.ReplaceExisting).ExecuteSync(); using (var output = file.OpenAsync(FileAccess.ReadAndWrite).ExecuteSync()) { zipEntry.ExtractWithPassword(output, password); } MoveFileInPlace(fileExistsBeforeExtraction, fullTargetPath, tmpPath); ExitTry:; } catch (Exception) { zipEntry.SetIOOperationCanceled(true); throw; } finally { if (zipEntry.IsIOOperationCanceled() && targetFileName != null) { // An exception has occurred. If the file exists, check // to see if it existed before we tried extracting. If // it did not, attempt to remove the target file. There // is a small possibility that the existing file has // been extracted successfully, overwriting a previously // existing file, and an exception was thrown after that // but before final completion (setting times, etc). In // that case the file will remain, even though some // error occurred. Nothing to be done about it. var file = FileSystem.Current.GetFileFromPathAsync(fullTargetPath).ExecuteSync(); if (file != null && !fileExistsBeforeExtraction) file.DeleteAsync(); } } }