/* This file is part of SevenZipSharp. SevenZipSharp is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. SevenZipSharp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SevenZipSharp. If not, see . */ #define DOTNET20 #define UNMANAGED #define COMPRESS using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; #if MONO using SevenZip.Mono; using SevenZip.Mono.COM; #endif namespace SevenZip { #if UNMANAGED /// /// Callback to handle the archive opening /// internal sealed class ArchiveOpenCallback : CallbackBase, IArchiveOpenCallback, IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IDisposable { private FileInfo _fileInfo; private Dictionary _wrappers = new Dictionary(); private readonly List _volumeFileNames = new List(); /// /// Gets the list of volume file names. /// public IList VolumeFileNames { get { return _volumeFileNames; } } /// /// Performs the common initialization. /// /// Volume file name. private void Init(string fileName) { if (!String.IsNullOrEmpty(fileName)) { _fileInfo = new FileInfo(fileName); _volumeFileNames.Add(fileName); if (fileName.EndsWith("001")) { int index = 2; var baseName = fileName.Substring(0, fileName.Length - 3); var volName = baseName + (index > 99 ? index.ToString() : index > 9 ? "0" + index : "00" + index); while (File.Exists(volName)) { _volumeFileNames.Add(volName); index++; volName = baseName + (index > 99 ? index.ToString() : index > 9 ? "0" + index : "00" + index); } } } } /// /// Initializes a new instance of the ArchiveOpenCallback class. /// /// The archive file name. public ArchiveOpenCallback(string fileName) { Init(fileName); } /// /// Initializes a new instance of the ArchiveOpenCallback class. /// /// The archive file name. /// Password for the archive. public ArchiveOpenCallback(string fileName, string password) : base(password) { Init(fileName); } #region IArchiveOpenCallback Members public void SetTotal(IntPtr files, IntPtr bytes) {} public void SetCompleted(IntPtr files, IntPtr bytes) {} #endregion #region IArchiveOpenVolumeCallback Members public int GetProperty(ItemPropId propId, ref PropVariant value) { switch (propId) { case ItemPropId.Name: value.VarType = VarEnum.VT_BSTR; value.Value = Marshal.StringToBSTR(_fileInfo.FullName); break; case ItemPropId.IsDirectory: value.VarType = VarEnum.VT_BOOL; value.UInt64Value = (byte) (_fileInfo.Attributes & FileAttributes.Directory); break; case ItemPropId.Size: value.VarType = VarEnum.VT_UI8; value.UInt64Value = (UInt64) _fileInfo.Length; break; case ItemPropId.Attributes: value.VarType = VarEnum.VT_UI4; value.UInt32Value = (uint) _fileInfo.Attributes; break; case ItemPropId.CreationTime: value.VarType = VarEnum.VT_FILETIME; value.Int64Value = _fileInfo.CreationTime.ToFileTime(); break; case ItemPropId.LastAccessTime: value.VarType = VarEnum.VT_FILETIME; value.Int64Value = _fileInfo.LastAccessTime.ToFileTime(); break; case ItemPropId.LastWriteTime: value.VarType = VarEnum.VT_FILETIME; value.Int64Value = _fileInfo.LastWriteTime.ToFileTime(); break; } return 0; } public int GetStream(string name, out IInStream inStream) { if (!File.Exists(name)) { name = Path.Combine(Path.GetDirectoryName(_fileInfo.FullName), name); if (!File.Exists(name)) { inStream = null; AddException(new FileNotFoundException("The volume \"" + name + "\" was not found. Extraction can be impossible.")); return 1; } } _volumeFileNames.Add(name); if (_wrappers.ContainsKey(name)) { inStream = _wrappers[name]; } else { try { var wrapper = new InStreamWrapper( new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), true); _wrappers.Add(name, wrapper); inStream = wrapper; } catch (Exception) { AddException(new FileNotFoundException("Failed to open the volume \"" + name + "\". Extraction is impossible.")); inStream = null; return 1; } } return 0; } #endregion #region ICryptoGetTextPassword Members /// /// Sets password for the archive /// /// Password for the archive /// Zero if everything is OK public int CryptoGetTextPassword(out string password) { password = Password; return 0; } #endregion #region IDisposable Members public void Dispose() { if (_wrappers != null) { foreach (InStreamWrapper wrap in _wrappers.Values) { wrap.Dispose(); } _wrappers = null; } #if MONO libp7zInvokerRaw.FreeObject(Handle); #endif GC.SuppressFinalize(this); } #endregion } #endif }