From c64b097c072c87cdf2d0891f8d90e4f4f14f48be Mon Sep 17 00:00:00 2001 From: chudov Date: Wed, 12 Nov 2008 05:45:48 +0000 Subject: [PATCH] Password protected archives support --- ArCueDotNet/Program.cs | 8 +- CUETools/CUETools.csproj | 10 ++ CUETools/Settings.cs | 28 +++++ CUETools/frmBatch.cs | 171 ++++++++++++++------------- CUETools/frmCUETools.cs | 35 ++++-- CUETools/frmPassword.Designer.cs | 72 ++++++++++++ CUETools/frmPassword.cs | 18 +++ CUETools/frmPassword.resx | 195 +++++++++++++++++++++++++++++++ CUEToolsLib/Main.cs | 160 ++++++++++++++++++------- UnRarDotNet/RarStream.cs | 40 ++++--- 10 files changed, 584 insertions(+), 153 deletions(-) create mode 100644 CUETools/Settings.cs create mode 100644 CUETools/frmPassword.Designer.cs create mode 100644 CUETools/frmPassword.cs create mode 100644 CUETools/frmPassword.resx diff --git a/ArCueDotNet/Program.cs b/ArCueDotNet/Program.cs index d49bb46..2aade04 100644 --- a/ArCueDotNet/Program.cs +++ b/ArCueDotNet/Program.cs @@ -28,10 +28,11 @@ namespace ArCueDotNet StringWriter sw = new StringWriter(); try { - CUESheet cueSheet = new CUESheet(pathIn, config); + CUESheet cueSheet = new CUESheet(config); + cueSheet.Open(pathIn); cueSheet.GenerateFilenames(OutputAudioFormat.NoAudio, pathIn); cueSheet.AccurateRip = true; - cueSheet.WriteAudioFiles(Path.GetDirectoryName(pathIn), CUEStyle.SingleFile, new SetStatus(ArCueSetStatus)); + cueSheet.WriteAudioFiles(Path.GetDirectoryName(pathIn), CUEStyle.SingleFile); cueSheet.GenerateAccurateRipLog(sw); } catch (Exception ex) @@ -41,8 +42,5 @@ namespace ArCueDotNet sw.Close(); Console.Write(sw.ToString()); } - public static void ArCueSetStatus(string status, uint percentTrack, double percentDisk, string input, string output) - { - } } } diff --git a/CUETools/CUETools.csproj b/CUETools/CUETools.csproj index 05e9f2f..ef01558 100644 --- a/CUETools/CUETools.csproj +++ b/CUETools/CUETools.csproj @@ -96,6 +96,12 @@ frmFilenameCorrector.cs + + Form + + + frmPassword.cs + Form @@ -140,6 +146,10 @@ Designer frmFilenameCorrector.cs + + Designer + frmPassword.cs + Designer frmReport.cs diff --git a/CUETools/Settings.cs b/CUETools/Settings.cs new file mode 100644 index 0000000..1c20b57 --- /dev/null +++ b/CUETools/Settings.cs @@ -0,0 +1,28 @@ +namespace JDP.Properties { + + + // This class allows you to handle specific events on the settings class: + // The SettingChanging event is raised before a setting's value is changed. + // The PropertyChanged event is raised after a setting's value is changed. + // The SettingsLoaded event is raised after the setting values are loaded. + // The SettingsSaving event is raised before the setting values are saved. + internal sealed partial class Settings { + + public Settings() { + // // To add event handlers for saving and changing settings, uncomment the lines below: + // + // this.SettingChanging += this.SettingChangingEventHandler; + // + // this.SettingsSaving += this.SettingsSavingEventHandler; + // + } + + private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + // Add code to handle the SettingChangingEvent event here. + } + + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + // Add code to handle the SettingsSaving event here. + } + } +} diff --git a/CUETools/frmBatch.cs b/CUETools/frmBatch.cs index a9e2cd3..87b62cf 100644 --- a/CUETools/frmBatch.cs +++ b/CUETools/frmBatch.cs @@ -57,39 +57,55 @@ namespace JDP DateTime _startedAt; List _batchPaths; - public string ShortenString(string input, int max) + public static string ShortenString(string input, int max) { if (input.Length < max) return input; return "..." + input.Substring(input.Length - max); } - public void SetStatus(string status, uint percentTrack, double percentDisk, string input, string output) + public void SetStatus(object sender, CUEToolsProgressEventArgs e) { this.BeginInvoke((MethodInvoker)delegate() { - if (percentDisk == 0) + if (e.percentDisk == 0) { _startedAt = DateTime.Now; + Text = e.status; } - else if (percentDisk > 0.02) + else if (e.percentDisk > 0.02) { TimeSpan span = DateTime.Now - _startedAt; - TimeSpan eta = new TimeSpan ((long) (span.Ticks/percentDisk)); - Text = String.Format("{0}, ETA {1}:{2:00}.", status, (int)eta.TotalMinutes, eta.Seconds); + TimeSpan eta = new TimeSpan ((long) (span.Ticks/e.percentDisk)); + Text = String.Format("{0}, ETA {1}:{2:00}.", e.status, (int)eta.TotalMinutes, eta.Seconds); } else - Text = status; - progressBar1.Value = (int)percentTrack; - progressBar2.Value = (int)(percentDisk*100); - string inputSuffix = output != null ? "=>" : ""; - if (input == null) + Text = e.status; + progressBar1.Value = (int)e.percentTrack; + progressBar2.Value = (int)(e.percentDisk*100); + string inputSuffix = e.output != null ? "=>" : ""; + if (e.input == null) txtInputFile.Text = inputSuffix; else - txtInputFile.Text = ShortenString(input, 120) + " " + inputSuffix; - if (output == null) + txtInputFile.Text = ShortenString(e.input, 120) + " " + inputSuffix; + if (e.output == null) txtOutputFile.Text = ""; else - txtOutputFile.Text = ShortenString(output, 120); + txtOutputFile.Text = ShortenString(e.output, 120); + }); + } + + private void PasswordRequired(object sender, ArchivePasswordRequiredEventArgs e) + { + this.Invoke((MethodInvoker)delegate() + { + frmPassword dlg = new frmPassword(); + if (dlg.ShowDialog(this) == DialogResult.OK) + { + e.Password = dlg.txtPassword.Text; + e.ContinueOperation = true; + } + else + e.ContinueOperation = false; }); } @@ -99,7 +115,59 @@ namespace JDP try { - cueSheet.WriteAudioFiles(Path.GetDirectoryName(pathOut), _cueStyle, new SetStatus(this.SetStatus)); + _startedAt = DateTime.Now; + if (_batchPaths.Count != 0) + pathIn = _batchPaths[0]; + + pathIn = Path.GetFullPath(pathIn); + + textBox1.Text += "Processing " + pathIn + ":\r\n"; + textBox1.Select(0, 0); + + string cueName; + if (!File.Exists(pathIn)) + { + if (!Directory.Exists(pathIn)) + throw new Exception("Input CUE Sheet not found."); + if (!pathIn.EndsWith(new string(Path.DirectorySeparatorChar, 1))) + pathIn = pathIn + Path.DirectorySeparatorChar; + cueName = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(pathIn)) + ".cue"; + } + else + cueName = Path.GetFileNameWithoutExtension(pathIn) + ".cue"; + + bool outputAudio = _accurateOffset || !_accurateRip; + cueSheet.Open(pathIn); + if (outputAudio) + { + bool pathFound = false; + for (int i = 0; i < 20; i++) + { + string outDir = Path.Combine(Path.GetDirectoryName(pathIn), "CUEToolsOutput" + (i > 0 ? String.Format("({0})", i) : "")); + if (!Directory.Exists(outDir)) + { + Directory.CreateDirectory(outDir); + pathOut = Path.Combine(outDir, cueName); + pathFound = true; + break; + } + } + if (!pathFound) + throw new Exception("Could not create a folder."); + } + else + pathOut = Path.Combine(Path.GetDirectoryName(pathIn), cueName); + cueSheet.GenerateFilenames(_audioFormat, pathOut); + if (outputAudio) + { + if (_cueStyle == CUEStyle.SingleFileWithCUE) + cueSheet.SingleFilename = Path.ChangeExtension(Path.GetFileName(pathOut), General.FormatExtension(_audioFormat)); + } + + cueSheet.UsePregapForFirstTrackInSingleFile = false; + cueSheet.AccurateRip = _accurateRip; + cueSheet.AccurateOffset = _accurateOffset; + cueSheet.WriteAudioFiles(Path.GetDirectoryName(pathOut), _cueStyle); this.Invoke((MethodInvoker)delegate() { if (_batchPaths.Count == 0) @@ -138,8 +206,10 @@ namespace JDP { Text = "Error: " + ex.Message; textBox1.Show(); - textBox1.Text += "Error: " + ex.Message + "\r\n"; - textBox1.Text += "----------------------------------------------------------\r\n"; + textBox1.Text += "Error"; + for (Exception e = ex; e != null; e = e.InnerException) + textBox1.Text += ": " + e.Message; + textBox1.Text += "\r\n----------------------------------------------------------\r\n"; textBox1.Select(0, 0); }); } @@ -164,62 +234,11 @@ namespace JDP public void StartConvert() { - CUESheet cueSheet; - try { - _startedAt = DateTime.Now; - - _workThread = null; - if (_batchPaths.Count != 0) - pathIn = _batchPaths[0]; - - pathIn = Path.GetFullPath(pathIn); - - textBox1.Text += "Processing " + pathIn + ":\r\n"; - textBox1.Select (0,0); - - string cueName; - if (!File.Exists(pathIn)) - { - if (!Directory.Exists (pathIn)) - throw new Exception("Input CUE Sheet not found."); - if (!pathIn.EndsWith(new string(Path.DirectorySeparatorChar, 1))) - pathIn = pathIn + Path.DirectorySeparatorChar; - cueName = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(pathIn)) + ".cue"; - } else - cueName = Path.GetFileNameWithoutExtension(pathIn) + ".cue"; - - bool outputAudio = _accurateOffset || !_accurateRip; - cueSheet = new CUESheet(pathIn, _config); - if (outputAudio) - { - bool pathFound = false; - for (int i = 0; i < 20; i++) - { - string outDir = Path.Combine(Path.GetDirectoryName (pathIn), "CUEToolsOutput" + (i > 0? String.Format("({0})",i) : "")); - if (!Directory.Exists(outDir)) - { - Directory.CreateDirectory(outDir); - pathOut = Path.Combine(outDir, cueName); - pathFound = true; - break; - } - } - if (!pathFound) - throw new Exception("Could not create a folder."); - } else - pathOut = Path.Combine(Path.GetDirectoryName(pathIn), cueName); - cueSheet.GenerateFilenames(_audioFormat, pathOut); - if (outputAudio) - { - if (_cueStyle == CUEStyle.SingleFileWithCUE) - cueSheet.SingleFilename = Path.ChangeExtension(Path.GetFileName (pathOut), General.FormatExtension (_audioFormat)); - } - - cueSheet.UsePregapForFirstTrackInSingleFile = false; - cueSheet.AccurateRip = _accurateRip; - cueSheet.AccurateOffset = _accurateOffset; + CUESheet cueSheet = new CUESheet(_config); + cueSheet.PasswordRequired += new ArchivePasswordRequiredHandler(PasswordRequired); + cueSheet.CUEToolsProgress += new CUEToolsProgressHandler(SetStatus); _workThread = new Thread(WriteAudioFilesThread); _workClass = cueSheet; @@ -235,16 +254,6 @@ namespace JDP textBox1.Text += "----------------------------------------------------------\r\n"; textBox1.Select(0, 0); } - if ((_workThread == null) && (_batchPaths.Count != 0)) - { - _batchPaths.RemoveAt(0); - if (_batchPaths.Count == 0) - { - Text = "All done."; - } - else - StartConvert(); - } } private void frmBatch_Load(object sender, EventArgs e) diff --git a/CUETools/frmCUETools.cs b/CUETools/frmCUETools.cs index c6e2286..e09205c 100644 --- a/CUETools/frmCUETools.cs +++ b/CUETools/frmCUETools.cs @@ -240,10 +240,11 @@ namespace JDP { } } - cueSheet = new CUESheet(pathIn, _config); - + cueSheet = new CUESheet(_config); + cueSheet.PasswordRequired += new ArchivePasswordRequiredHandler(PasswordRequired); cueSheet.WriteOffset = _writeOffset; - + cueSheet.Open(pathIn); + UpdateOutputPath(cueSheet.Artist != "" ? cueSheet.Artist : "Unknown Artist", cueSheet.Title != "" ? cueSheet.Title : "Unknown Title"); pathOut = txtOutputPath.Text; cueSheet.GenerateFilenames(SelectedOutputAudioFormat, pathOut); @@ -326,6 +327,22 @@ namespace JDP { } } + private void PasswordRequired(object sender, ArchivePasswordRequiredEventArgs e) + { + //if (this.InvokeRequired) + // this.Invoke(this.PasswordRequired, sender, e); + //this.Invoke((MethodInvoker)delegate() + //{ + frmPassword dlg = new frmPassword(); + if (dlg.ShowDialog() == DialogResult.OK) + { + e.Password = dlg.txtPassword.Text; + e.ContinueOperation = true; + } else + e.ContinueOperation = false; + //}); + } + private void WriteAudioFilesThread(object o) { object[] p = (object[])o; @@ -334,7 +351,8 @@ namespace JDP { CUEStyle cueStyle = (CUEStyle)p[2]; try { - cueSheet.WriteAudioFiles(outDir, cueStyle, new SetStatus(this.SetStatus)); + cueSheet.CUEToolsProgress += new CUEToolsProgressHandler(SetStatus); + cueSheet.WriteAudioFiles(outDir, cueStyle); this.Invoke((MethodInvoker)delegate() { if (_batchPaths.Count == 0) { @@ -390,11 +408,12 @@ namespace JDP { } } - public void SetStatus(string status, uint percentTrack, double percentDisk, string input, string output) { + public void SetStatus(object sender, CUEToolsProgressEventArgs e) + { this.BeginInvoke((MethodInvoker)delegate() { - toolStripStatusLabel1.Text = status; - toolStripProgressBar1.Value = (int)percentTrack; - toolStripProgressBar2.Value = (int)(percentDisk*100); + toolStripStatusLabel1.Text = e.status; + toolStripProgressBar1.Value = (int)e.percentTrack; + toolStripProgressBar2.Value = (int)(e.percentDisk*100); }); } diff --git a/CUETools/frmPassword.Designer.cs b/CUETools/frmPassword.Designer.cs new file mode 100644 index 0000000..7125b0c --- /dev/null +++ b/CUETools/frmPassword.Designer.cs @@ -0,0 +1,72 @@ +namespace JDP +{ + partial class frmPassword + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmPassword)); + this.txtPassword = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // txtPassword + // + resources.ApplyResources(this.txtPassword, "txtPassword"); + this.txtPassword.Name = "txtPassword"; + this.txtPassword.UseSystemPasswordChar = true; + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // frmPassword + // + this.AcceptButton = this.button1; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.button1); + this.Controls.Add(this.txtPassword); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "frmPassword"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.TopMost = true; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button1; + public System.Windows.Forms.TextBox txtPassword; + } +} \ No newline at end of file diff --git a/CUETools/frmPassword.cs b/CUETools/frmPassword.cs new file mode 100644 index 0000000..d7c50a1 --- /dev/null +++ b/CUETools/frmPassword.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace JDP +{ + public partial class frmPassword : Form + { + public frmPassword() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/CUETools/frmPassword.resx b/CUETools/frmPassword.resx new file mode 100644 index 0000000..bcd5b3b --- /dev/null +++ b/CUETools/frmPassword.resx @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Left, Right + + + + 12, 12 + + + + 256 + + + 350, 20 + + + 0 + + + txtPassword + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 304, 40 + + + 58, 23 + + + 1 + + + Ok + + + button1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 374, 75 + + + CenterParent + + + Password required + + + frmPassword + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/CUEToolsLib/Main.cs b/CUEToolsLib/Main.cs index c306a83..86cc7e3 100644 --- a/CUEToolsLib/Main.cs +++ b/CUEToolsLib/Main.cs @@ -194,8 +194,6 @@ namespace CUEToolsLib } } - public delegate void SetStatus(string status, uint percentTrack, double percentDisk, string input, string output); - public enum CUEStyle { SingleFileWithCUE, SingleFile, @@ -396,6 +394,24 @@ namespace CUEToolsLib } } + public class CUEToolsProgressEventArgs + { + public string status = string.Empty; + public uint percentTrack = 0; + public double percentDisk = 0.0; + public string input = string.Empty; + public string output = string.Empty; + } + + public class ArchivePasswordRequiredEventArgs + { + public string Password = string.Empty; + public bool ContinueOperation = true; + } + + public delegate void CUEToolsProgressHandler(object sender, CUEToolsProgressEventArgs e); + public delegate void ArchivePasswordRequiredHandler(object sender, ArchivePasswordRequiredEventArgs e); + public class CUESheet { private bool _stop, _pause; private List _attributes; @@ -423,35 +439,23 @@ namespace CUEToolsLib string _cddbDiscIdTag; private bool _isArchive; private string _archivePath; + private string _archivePassword; + private CUEToolsProgressEventArgs _progress; - public CUESheet(string pathIn, CUEConfig config) + public event ArchivePasswordRequiredHandler PasswordRequired; + public event CUEToolsProgressHandler CUEToolsProgress; + + public CUESheet(CUEConfig config) { _config = config; - - hdcdDecoder = null; - if (_config.detectHDCD) - { - try { hdcdDecoder = new HDCDDotNet.HDCDDotNet(2, 44100, _config.decodeHDCD); } - catch { } - } - - string cueDir, lineStr, command, pathAudio, fileType; - CUELine line; - TrackInfo trackInfo; - int tempTimeLength, timeRelativeToFileStart, absoluteFileStartTime; - int fileTimeLengthSamples, fileTimeLengthFrames, i, trackNumber; - bool seenFirstFileIndex, seenDataTrack; - List indexes; - IndexInfo indexInfo; - SourceInfo sourceInfo; - NameValueCollection _trackTags = null; - - _stop = false; - _pause = false; + _progress = new CUEToolsProgressEventArgs(); _attributes = new List(); _tracks = new List(); _sources = new List(); _sourcePaths = new List(); + _albumTags = new NameValueCollection(); + _stop = false; + _pause = false; _cuePath = null; _paddedToFrame = false; _truncated4608 = false; @@ -461,20 +465,37 @@ namespace CUEToolsLib _appliedWriteOffset = false; _dataTrackLength = null; _minDataTrackLength = null; - _albumTags = new NameValueCollection(); + hdcdDecoder = null; + _hasEmbeddedCUESheet = false; + _isArchive = false; + accDisks = new List(); + } + + public void Open(string pathIn) + { + if (_config.detectHDCD) + { + try { hdcdDecoder = new HDCDDotNet.HDCDDotNet(2, 44100, _config.decodeHDCD); } + catch { } + } + + string cueDir, lineStr, command, pathAudio = null, fileType; + CUELine line; + TrackInfo trackInfo; + int tempTimeLength, timeRelativeToFileStart, absoluteFileStartTime; + int fileTimeLengthSamples, fileTimeLengthFrames, i, trackNumber; + bool seenFirstFileIndex = false, seenDataTrack = false; + List indexes = new List(); + IndexInfo indexInfo; + SourceInfo sourceInfo; + NameValueCollection _trackTags = null; + cueDir = Path.GetDirectoryName(pathIn); - pathAudio = null; - indexes = new List(); trackInfo = null; absoluteFileStartTime = 0; fileTimeLengthSamples = 0; fileTimeLengthFrames = 0; trackNumber = 0; - seenFirstFileIndex = false; - seenDataTrack = false; - accDisks = new List(); - _hasEmbeddedCUESheet = false; - _isArchive = false; TextReader sr; @@ -494,6 +515,7 @@ namespace CUEToolsLib else if (Path.GetExtension(pathIn).ToLower() == ".rar") { Unrar _unrar = new Unrar(); + _unrar.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); string cueName = null, cueText = null; _unrar.Open(pathIn, Unrar.OpenMode.List); while (_unrar.ReadHeader()) @@ -508,15 +530,16 @@ namespace CUEToolsLib } _unrar.Close(); if (cueName != null) - try { RarStream rarStream = new RarStream(pathIn, cueName); + rarStream.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); StreamReader cueReader = new StreamReader(rarStream, CUESheet.Encoding); cueText = cueReader.ReadToEnd(); cueReader.Close(); rarStream.Close(); + if (cueText == "") + throw new Exception("Empty cue sheet."); } - catch { } if (cueText == null) throw new Exception("Input archive doesn't contain a cue sheet."); sr = new StringReader(cueText); @@ -864,6 +887,49 @@ namespace CUEToolsLib } } + private void ShowProgress(string status, uint percentTrack, double percentDisk, string input, string output) + { + if (this.CUEToolsProgress == null) + return; + _progress.status = status; + _progress.percentTrack = percentTrack; + _progress.percentDisk = percentDisk; + _progress.input = input; + _progress.output = output; + this.CUEToolsProgress(this, _progress); + } + +#if !MONO + private void unrar_ExtractionProgress(object sender, ExtractionProgressEventArgs e) + { + _progress.percentTrack = (uint) Math.Round(e.PercentComplete); + this.CUEToolsProgress(this, _progress); + } + + private void unrar_PasswordRequired(object sender, PasswordRequiredEventArgs e) + { + if (_archivePassword != null) + { + e.ContinueOperation = true; + e.Password = _archivePassword; + return; + } + if (this.PasswordRequired != null) + { + ArchivePasswordRequiredEventArgs e1 = new ArchivePasswordRequiredEventArgs(); + this.PasswordRequired(this, e1); + if (e1.ContinueOperation && e1.Password != "") + { + _archivePassword = e1.Password; + e.ContinueOperation = true; + e.Password = e1.Password; + return; + } + } + throw new IOException("Password is required for extraction."); + } +#endif + public string GetCommonTag(string tagName) { if (_hasEmbeddedCUESheet || _hasSingleFilename) @@ -1013,10 +1079,13 @@ namespace CUEToolsLib { IAudioSource audioSource; + ShowProgress("Opening source file...", 0, 0.0, path, null); #if !MONO if (_isArchive) { RarStream IO = new RarStream(_archivePath, path); + IO.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); + IO.ExtractionProgress += new ExtractionProgressHandler(unrar_ExtractionProgress); audioSource = AudioReadWrite.GetAudioSource(path, IO); } else #endif @@ -1618,7 +1687,7 @@ namespace CUEToolsLib outTracksMatch = bestTracksMatch; } - public void WriteAudioFiles(string dir, CUEStyle style, SetStatus statusDel) { + public void WriteAudioFiles(string dir, CUEStyle style) { string[] destPaths; int[] destLengths; bool htoaToFile = ((style == CUEStyle.GapsAppended) && _config.preserveHTOA && @@ -1656,7 +1725,7 @@ namespace CUEToolsLib bool SkipOutput = false; if (_accurateRip) { - statusDel((string)"Contacting AccurateRip database...", 0, 0, null, null); + ShowProgress((string)"Contacting AccurateRip database...", 0, 0, null, null); if (!_dataTrackLength.HasValue && _minDataTrackLength.HasValue && _accurateRipId == _accurateRipIdActual && _config.bruteForceDTL) { uint minDTL = _minDataTrackLength.Value; @@ -1667,13 +1736,13 @@ namespace CUEToolsLib ContactAccurateRip(); if (accResult != HttpStatusCode.NotFound) break; - statusDel((string)"Contacting AccurateRip database...", 0, (dtl-minDTL)/75.0, null, null); + ShowProgress((string)"Contacting AccurateRip database...", 0, (dtl - minDTL) / 75.0, null, null); lock (this) { if (_stop) throw new StopException(); if (_pause) { - statusDel("Paused...", 0, 0, null, null); + ShowProgress("Paused...", 0, 0, null, null); Monitor.Wait(this); } else @@ -1714,7 +1783,7 @@ namespace CUEToolsLib else if (_accurateOffset) { _writeOffset = 0; - WriteAudioFilesPass(dir, style, statusDel, destPaths, destLengths, htoaToFile, true); + WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, true); uint tracksMatch; int bestOffset; @@ -1749,12 +1818,12 @@ namespace CUEToolsLib if (style != CUEStyle.SingleFileWithCUE && style != CUEStyle.SingleFile && _config.createM3U) WriteM3U(Path.ChangeExtension(_cuePath, ".m3u"), style); } - WriteAudioFilesPass(dir, style, statusDel, destPaths, destLengths, htoaToFile, verifyOnly); + WriteAudioFilesPass(dir, style, destPaths, destLengths, htoaToFile, verifyOnly); } if (_accurateRip) { - statusDel((string)"Generating AccurateRip report...", 0, 0, null, null); + ShowProgress((string)"Generating AccurateRip report...", 0, 0, null, null); if (!_accurateOffset && _config.writeArTagsOnVerify && _writeOffset == 0 && !_isArchive) { uint tracksMatch; @@ -1930,7 +1999,7 @@ namespace CUEToolsLib audioDest.SetTags(destTags); } - public void WriteAudioFilesPass(string dir, CUEStyle style, SetStatus statusDel, string[] destPaths, int[] destLengths, bool htoaToFile, bool noOutput) + public void WriteAudioFilesPass(string dir, CUEStyle style, string[] destPaths, int[] destLengths, bool htoaToFile, bool noOutput) { const int buffLen = 16384; int iTrack, iIndex; @@ -2024,7 +2093,7 @@ namespace CUEToolsLib diskLength += _tracks[iTrack].IndexLengths[iIndex] * 588; - statusDel(String.Format("{2} track {0:00} ({1:00}%)...", 0, 0, noOutput ? "Verifying" : "Writing"), 0, 0.0, null, null); + ShowProgress(String.Format("{2} track {0:00} ({1:00}%)...", 0, 0, noOutput ? "Verifying" : "Writing"), 0, 0.0, null, null); for (iTrack = 0; iTrack < TrackCount; iTrack++) { track = _tracks[iTrack]; @@ -2111,7 +2180,7 @@ namespace CUEToolsLib trackPercent = (uint)(currentOffset / 0.01 / trackLength); double diskPercent = ((float)diskOffset) / diskLength; if (trackPercent != lastTrackPercent) - statusDel(String.Format("{2} track {0:00} ({1:00}%)...", iIndex > 0 ? iTrack + 1 : iTrack, trackPercent, + ShowProgress(String.Format("{2} track {0:00} ({1:00}%)...", iIndex > 0 ? iTrack + 1 : iTrack, trackPercent, noOutput ? "Verifying" : "Writing"), trackPercent, diskPercent, audioSource.Path, discardOutput ? null : audioDest.Path); lastTrackPercent = trackPercent; @@ -2176,7 +2245,7 @@ namespace CUEToolsLib } if (_pause) { - statusDel ("Paused...", 0, 0, null, null); + ShowProgress("Paused...", 0, 0, null, null); Monitor.Wait(this); } } @@ -2413,6 +2482,7 @@ namespace CUEToolsLib if (_isArchive) { RarStream IO = new RarStream(_archivePath, sourceInfo.Path); + IO.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); audioSource = AudioReadWrite.GetAudioSource(sourceInfo.Path, IO); } else diff --git a/UnRarDotNet/RarStream.cs b/UnRarDotNet/RarStream.cs index deb9d03..f7f466b 100644 --- a/UnRarDotNet/RarStream.cs +++ b/UnRarDotNet/RarStream.cs @@ -25,12 +25,7 @@ namespace UnRarDotNet _pos = 0; _path = path; _fileName = fileName; - _unrar.PasswordRequired += new PasswordRequiredHandler(unrar_PasswordRequired); - _unrar.DataAvailable += new DataAvailableHandler(unrar_DataAvailable); - _workThread = new Thread(Decompress); - _workThread.Priority = ThreadPriority.BelowNormal; - _workThread.IsBackground = true; - _workThread.Start(null); + _workThread = null; } public override bool CanRead { @@ -48,11 +43,14 @@ namespace UnRarDotNet { get { + Go(); lock (this) { while (_size == null && !_close) Monitor.Wait(this); } + if (_ex != null) + throw _ex; if (_size == null) throw new NotSupportedException(); return _size.Value; @@ -93,12 +91,15 @@ namespace UnRarDotNet public override int Read(byte[] array, int offset, int count) { int total = 0; + Go(); while (count > 0) { lock (this) { - while (_buffer == null && !_eof) + while (_buffer == null && !_eof && !_close) Monitor.Wait(this); + if (_close) + throw new IOException("Decompression failed", _ex); if (_buffer == null) return total; if (_seek_to != null) @@ -139,6 +140,7 @@ namespace UnRarDotNet } public override long Seek(long offset, SeekOrigin origin) { + Go(); lock (this) { while (_size == null && !_close) @@ -181,22 +183,28 @@ namespace UnRarDotNet { throw new NotSupportedException(); } + public event PasswordRequiredHandler PasswordRequired; + public event ExtractionProgressHandler ExtractionProgress; private Unrar _unrar; private string _fileName; private Thread _workThread; private bool _close, _rewind, _eof; private byte[] _buffer; + private Exception _ex; int _offset, _length; long? _size; long? _seek_to; long _pos; string _path; - private void unrar_PasswordRequired(object sender, PasswordRequiredEventArgs e) + private void Go() { - e.Password = "PARS"; - e.ContinueOperation = true; + if (_workThread != null) return; + _workThread = new Thread(Decompress); + _workThread.Priority = ThreadPriority.BelowNormal; + _workThread.IsBackground = true; + _workThread.Start(null); } private void unrar_DataAvailable(object sender, DataAvailableEventArgs e) @@ -227,7 +235,10 @@ namespace UnRarDotNet private void Decompress(object o) { - //try + _unrar.DataAvailable += new DataAvailableHandler(unrar_DataAvailable); + _unrar.PasswordRequired += PasswordRequired; + _unrar.ExtractionProgress += ExtractionProgress; + try { do { @@ -264,9 +275,10 @@ namespace UnRarDotNet } } while (true); } - //catch (StopExtractionException) - //{ - //} + catch (Exception ex) + { + _ex = ex; + } lock (this) { _close = true;