/// <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(); } } } }
/// <summary> /// Metoda, ki se pokliče, ko kliknemo na gumb Razširi. Odpre saveFileDialog in prebere kam bomo datoteko /// shranili. /// OPOMBA: metoda še ne deluje 100% pravilno. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnExtract_Click(object sender, EventArgs e) { filesList = new StringCollection(); FolderBrowserDialog fbd = new FolderBrowserDialog(); if (fileExplorer.SelectedItems.Count > 0 && fbd.ShowDialog() == DialogResult.OK) { // Pridobi shranjevalno pot string savePath = fbd.SelectedPath; foreach (ListViewItem item in fileExplorer.SelectedItems) { string file = item.SubItems[0].Text; // Preveri katera oblika datoteke je: ZIP, TAR, GZIP ali TAR.BZ2 if (Path.GetExtension(txtPath.Text) == ".zip") { ZipFile zip = Ionic.Zip.ZipFile.Read(txtPath.Text); ZipEntry entry = zip[file]; if (zip[file].UsesEncryption == true) { PasswordPrompt passWin = new PasswordPrompt(); passWin.ShowDialog(); zip.Password = passWin.pass; try { entry.ExtractWithPassword(savePath, passWin.pass); } catch (BadPasswordException) { if (MessageBox.Show("Napačno geslo", "Napaka", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) == DialogResult.Retry) { passWin.ShowDialog(); } } } string enExists = savePath + @"\" + entry.FileName; if (File.Exists(enExists)) { if (MessageBox.Show("Datoteka " + file + " že obstaja. Ali jo želite zamenjati?", "Datoteka obstaja", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) { entry.Extract(savePath, ExtractExistingFileAction.OverwriteSilently); } else { break; } } else { entry.Extract(savePath); } } else if (Path.GetExtension(txtPath.Text) == ".tar") { byte[] outBuffer = new byte[4096]; TarInputStream tar = new TarInputStream(new FileStream(txtPath.Text, FileMode.Open, FileAccess.Read)); TarEntry curEntry = tar.GetNextEntry(); while (curEntry != null) { if (curEntry.Name == file) { FileStream fs = new FileStream(savePath + @"\" + curEntry.Name, FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs); tar.Read(outBuffer, 0, (int)curEntry.Size); bw.Write(outBuffer, 0, outBuffer.Length); bw.Close(); } curEntry = tar.GetNextEntry(); } tar.Close(); } else if (Path.GetExtension(txtPath.Text) == ".bz2") { Stream str = new FileStream(txtPath.Text, FileMode.Open, FileAccess.Read); BZip2InputStream bzStr = new BZip2InputStream(str); TarInputStream tar = new TarInputStream(bzStr); TarEntry curEntry = tar.GetNextEntry(); while (curEntry != null) { if (curEntry.Name == file) { byte[] outBuffer = new byte[curEntry.Size]; FileStream fs = new FileStream(savePath + @"\" + curEntry.Name, FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs); tar.Read(outBuffer, 0, (int)curEntry.Size); bw.Write(outBuffer, 0, outBuffer.Length); bw.Close(); } curEntry = tar.GetNextEntry(); } tar.Close(); } else if (Path.GetExtension(txtPath.Text) == ".tgz") { Stream str = new FileStream(txtPath.Text, FileMode.Open, FileAccess.Read); GZipInputStream gzStr = new GZipInputStream(str); TarInputStream tar = new TarInputStream(gzStr); TarEntry curEntry = tar.GetNextEntry(); while (curEntry != null) { if (curEntry.Name == file) { byte[] outBuffer = new byte[curEntry.Size]; FileStream fs = new FileStream(savePath + @"\" + curEntry.Name, FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs); tar.Read(outBuffer, 0, (int)curEntry.Size); bw.Write(outBuffer, 0, outBuffer.Length); bw.Close(); } curEntry = tar.GetNextEntry(); } tar.Close(); } } } else { MessageBox.Show("Nobena datoteka ni bila izbrana. Prosimo izberite datoteke.", "Napaka", MessageBoxButtons.OK, MessageBoxIcon.Information); } }