/// <summary>
        /// Retrieves all information about the archive.
        /// </summary>
        /// <exception cref="SevenZip.SevenZipArchiveException"/>
        private void GetArchiveInfo(bool disposeStream)
        {
            if (_archive == null)
            {
                if (!ThrowException(null, new SevenZipArchiveException()))
                {
                    return;
                }
            }
            else
            {
                IInStream archiveStream;
                using ((archiveStream = GetArchiveStream(disposeStream)) as IDisposable)
                {
                    var openCallback = GetArchiveOpenCallback();
                    if (!_opened)
                    {
                        if (!OpenArchive(archiveStream, openCallback))
                        {
                            return;
                        }
                        _opened = !disposeStream;
                    }
                    _filesCount = _archive.GetNumberOfItems();
                    _archiveFileData = new List<ArchiveFileInfo>((int)_filesCount);
                    if (_filesCount != 0)
                    {
                        var data = new PropVariant();
                        try
                        {
                            #region Getting archive items data

                            for (uint i = 0; i < _filesCount; i++)
                            {
                                try
                                {
                                    var fileInfo = new ArchiveFileInfo { Index = (int)i };
                                    _archive.GetProperty(i, ItemPropId.Path, ref data);
                                    fileInfo.FileName = NativeMethods.SafeCast(data, "[no name]");
                                    _archive.GetProperty(i, ItemPropId.LastWriteTime, ref data);
                                    fileInfo.LastWriteTime = NativeMethods.SafeCast(data, DateTime.Now);
                                    _archive.GetProperty(i, ItemPropId.CreationTime, ref data);
                                    fileInfo.CreationTime = NativeMethods.SafeCast(data, DateTime.Now);
                                    _archive.GetProperty(i, ItemPropId.LastAccessTime, ref data);
                                    fileInfo.LastAccessTime = NativeMethods.SafeCast(data, DateTime.Now);
                                    _archive.GetProperty(i, ItemPropId.Size, ref data);
                                    fileInfo.Size = NativeMethods.SafeCast<ulong>(data, 0);
                                    if (fileInfo.Size == 0)
                                    {
                                        fileInfo.Size = NativeMethods.SafeCast<uint>(data, 0);
                                    }
                                    _archive.GetProperty(i, ItemPropId.Attributes, ref data);
                                    fileInfo.Attributes = NativeMethods.SafeCast<uint>(data, 0);
                                    _archive.GetProperty(i, ItemPropId.IsDirectory, ref data);
                                    fileInfo.IsDirectory = NativeMethods.SafeCast(data, false);
                                    _archive.GetProperty(i, ItemPropId.Encrypted, ref data);
                                    fileInfo.Encrypted = NativeMethods.SafeCast(data, false);
                                    _archive.GetProperty(i, ItemPropId.Crc, ref data);
                                    fileInfo.Crc = NativeMethods.SafeCast<uint>(data, 0);
                                    _archive.GetProperty(i, ItemPropId.Comment, ref data);
                                    fileInfo.Comment = NativeMethods.SafeCast(data, "");
                                    _archiveFileData.Add(fileInfo);
                                }
                                catch (InvalidCastException)
                                {
                                    ThrowException(null, new SevenZipArchiveException("probably archive is corrupted."));
                                }
                            }

                            #endregion

                            #region Getting archive properties

                            uint numProps = _archive.GetNumberOfArchiveProperties();
                            var archProps = new List<ArchiveProperty>((int)numProps);
                            for (uint i = 0; i < numProps; i++)
                            {
                                string propName;
                                ItemPropId propId;
                                ushort varType;
                                _archive.GetArchivePropertyInfo(i, out propName, out propId, out varType);
                                _archive.GetArchiveProperty(propId, ref data);
                                if (propId == ItemPropId.Solid)
                                {
                                    _isSolid = NativeMethods.SafeCast(data, true);
                                }
                                // TODO Add more archive properties
                                if (PropIdToName.PropIdNames.ContainsKey(propId))
                                {
                                    archProps.Add(new ArchiveProperty
                                    {
                                        Name = PropIdToName.PropIdNames[propId],
                                        Value = data.Object
                                    });
                                }
                                else
                                {
                                    Debug.WriteLine(
                                        "An unknown archive property encountered (code " +
                                        ((int)propId).ToString(CultureInfo.InvariantCulture) + ')');
                                }
                            }
                            _archiveProperties = new ReadOnlyCollection<ArchiveProperty>(archProps);
                            if (!_isSolid.HasValue && _format == InArchiveFormat.Zip)
                            {
                                _isSolid = false;
                            }
                            if (!_isSolid.HasValue)
                            {
                                _isSolid = true;
                            }

                            #endregion
                        }
                        catch (Exception)
                        {
                            if (openCallback.ThrowException())
                            {
                                throw;
                            }
                        }
                    }
                }
                if (disposeStream)
                {
                    _archive.Close();
                    _archiveStream = null;
                }
                _archiveFileInfoCollection = new ReadOnlyCollection<ArchiveFileInfo>(_archiveFileData);
            }
        }
예제 #2
0
 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;
 }
예제 #3
0
		/// <summary>
		/// Determines whether the specified PropVariant is equal to the current PropVariant.
		/// </summary>
		/// <param name="afi">The PropVariant to compare with the current PropVariant.</param>
		/// <returns>true if the specified PropVariant is equal to the current PropVariant; otherwise, false.</returns>
		private bool Equals(PropVariant afi){
			if (afi.VarType != VarType)
				return false;
			if (VarType != VarEnum.VT_BSTR)
				return afi.Int64Value == Int64Value;
			return afi.Value == Value;
		}
        /// <summary>
        /// Sets the compression properties
        /// </summary>
        private void SetCompressionProperties()
        {
            switch (_archiveFormat)
            {
                case OutArchiveFormat.Tar:
                    break;
                default:
                    ISetProperties setter = CompressionMode == CompressionMode.Create && _updateData.FileNamesToModify == null
                                            ? (ISetProperties)SevenZipLibraryManager.OutArchive(
                                                    _archiveFormat, this)
                                            : (ISetProperties)SevenZipLibraryManager.InArchive(
                                                    Formats.InForOutFormats[_archiveFormat], this);
                    if (setter == null)
                    {
                        if (!ThrowException(null,
                                            new CompressionFailedException(
                                                "The specified archive format is unsupported.")))
                        {
                            return;
                        }
                    }
                    if (_volumeSize > 0 && ArchiveFormat != OutArchiveFormat.SevenZip)
                    {
                        throw new CompressionFailedException("Unfortunately, the creation of multivolume non-7Zip archives is not implemented. It will be one day, though.");
                    }
                    if (CustomParameters.ContainsKey("x") || CustomParameters.ContainsKey("m"))
                    {
                        if (
                            !ThrowException(null,
                                            new CompressionFailedException(
                                                "The specified compression parameters are invalid.")))
                        {
                            return;
                        }
                    }
                    var names = new List<IntPtr>(2 + CustomParameters.Count);
                    var values = new List<PropVariant>(2 + CustomParameters.Count);
#if !WINCE
                    var sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
                    sp.Demand();
#endif
                    #region Initialize compression properties

                    if (_compressionMethod == CompressionMethod.Default)
                    {
                        names.Add(Marshal.StringToBSTR("x"));
                        values.Add(new PropVariant());
                        foreach (var pair in CustomParameters)
                        {
                            names.Add(Marshal.StringToBSTR(pair.Key));
                            var pv = new PropVariant();
                            if (pair.Key == "fb" || pair.Key == "pass" || pair.Key == "d")
                            {
                                pv.VarType = VarEnum.VT_UI4;
                                pv.UInt32Value = Convert.ToUInt32(pair.Value, CultureInfo.InvariantCulture);
                            }
                            else
                            {
                                pv.VarType = VarEnum.VT_BSTR;
                                pv.Value = Marshal.StringToBSTR(pair.Value);
                            }
                            values.Add(pv);
                        }
                    }
                    else
                    {
                        names.Add(Marshal.StringToBSTR("x"));
                        names.Add(_archiveFormat == OutArchiveFormat.Zip
                                      ? Marshal.StringToBSTR("m")
                                      : Marshal.StringToBSTR("0"));
                        values.Add(new PropVariant());
                        var pv = new PropVariant
                        {
                            VarType = VarEnum.VT_BSTR,
                            Value = Marshal.StringToBSTR(Formats.MethodNames[_compressionMethod])
                        };
                        values.Add(pv);
                        foreach (var pair in CustomParameters)
                        {
                            names.Add(Marshal.StringToBSTR(pair.Key));
                            pv = new PropVariant();
                            if (pair.Key == "fb" || pair.Key == "pass" || pair.Key == "d")
                            {
                                pv.VarType = VarEnum.VT_UI4;
                                pv.UInt32Value = Convert.ToUInt32(pair.Value, CultureInfo.InvariantCulture);
                            }
                            else
                            {
                                pv.VarType = VarEnum.VT_BSTR;
                                pv.Value = Marshal.StringToBSTR(pair.Value);
                            }
                            values.Add(pv);
                        }
                    }

                    #endregion

                    #region Set compression level

                    PropVariant clpv = values[0];
                    clpv.VarType = VarEnum.VT_UI4;
                    switch (CompressionLevel)
                    {
                        case CompressionLevel.None:
                            clpv.UInt32Value = 0;
                            break;
                        case CompressionLevel.Fast:
                            clpv.UInt32Value = 1;
                            break;
                        case CompressionLevel.Low:
                            clpv.UInt32Value = 3;
                            break;
                        case CompressionLevel.Normal:
                            clpv.UInt32Value = 5;
                            break;
                        case CompressionLevel.High:
                            clpv.UInt32Value = 7;
                            break;
                        case CompressionLevel.Ultra:
                            clpv.UInt32Value = 9;
                            break;
                    }
                    values[0] = clpv;

                    #endregion

                    #region Encrypt headers

                    if (EncryptHeaders && _archiveFormat == OutArchiveFormat.SevenZip &&
                        !SwitchIsInCustomParameters("he"))
                    {
                        names.Add(Marshal.StringToBSTR("he"));
                        var tmp = new PropVariant { VarType = VarEnum.VT_BSTR, Value = Marshal.StringToBSTR("on") };
                        values.Add(tmp);
                    }

                    #endregion

                    #region Zip Encryption

                    if (_archiveFormat == OutArchiveFormat.Zip && ZipEncryptionMethod != ZipEncryptionMethod.ZipCrypto &&
                        !SwitchIsInCustomParameters("em"))
                    {
                        names.Add(Marshal.StringToBSTR("em"));
                        var tmp = new PropVariant
                        {
                            VarType = VarEnum.VT_BSTR,
                            Value = Marshal.StringToBSTR(
#if !WINCE
Enum.GetName(typeof(ZipEncryptionMethod), ZipEncryptionMethod))
#else
                            OpenNETCF.Enum2.GetName(typeof (ZipEncryptionMethod), ZipEncryptionMethod))
#endif
                        };
                        values.Add(tmp);
                    }

                    #endregion

                    var namesHandle = GCHandle.Alloc(names.ToArray(), GCHandleType.Pinned);
                    var valuesHandle = GCHandle.Alloc(values.ToArray(), GCHandleType.Pinned);
                    try
                    {
                        if (setter != null) //ReSharper
                            setter.SetProperties(namesHandle.AddrOfPinnedObject(), valuesHandle.AddrOfPinnedObject(),
                                                 names.Count);
                    }
                    finally
                    {
                        namesHandle.Free();
                        valuesHandle.Free();
                    }
                    break;
            }
        }
예제 #5
0
        public int GetProperty(uint index, ItemPropId propID, ref PropVariant value)
        {
            index -= _indexOffset;
            try
            {
                switch (propID)
                {
                    case ItemPropId.IsAnti:
                        value.VarType = VarEnum.VT_BOOL;
                        value.UInt64Value = 0;
                        break;
                    case ItemPropId.Path:
                        #region Path

                        value.VarType = VarEnum.VT_BSTR;
                        string val = DefaultItemName;
                        if (_updateData.Mode != InternalCompressionMode.Modify)
                        {
                            if (_files == null)
                            {
                                if (_entries != null)
                                {
                                    val = _entries[index];
                                }
                            }
                            else
                            {
                                if (_directoryStructure)
                                {
                                    if (_rootLength > 0)
                                    {
                                        val = _files[index].FullName.Substring(_rootLength);
                                    }
                                    else
                                    {
                                        val = _files[index].FullName[0] + _files[index].FullName.Substring(2);
                                    }
                                }
                                else
                                {
                                    val = _files[index].Name;
                                }
                            }
                        }
                        else
                        {
                            val = _updateData.FileNamesToModify[(int) index];
                        }
                        value.Value = Marshal.StringToBSTR(val);
                        #endregion
                        break;
                    case ItemPropId.IsDirectory:
                        value.VarType = VarEnum.VT_BOOL;
                        if (_updateData.Mode != InternalCompressionMode.Modify)
                        {
                            if (_files == null)
                            {
                                if (_streams == null)
                                {
                                    value.UInt64Value = 0;
                                }
                                else
                                {
                                    value.UInt64Value = (ulong)(_streams[index] == null ? 1 : 0);
                                }
                            }
                            else
                            {
                                value.UInt64Value = (byte)(_files[index].Attributes & FileAttributes.Directory);
                            }
                        }
                        else
                        {
                            value.UInt64Value = Convert.ToUInt64(_updateData.ArchiveFileData[(int) index].IsDirectory);
                        }
                        break;
                    case ItemPropId.Size:
                        #region Size

												//zero 11-oct-2014 - this doesnt matter, we think it's only used for updating the progress indicator
												value.VarType = VarEnum.VT_UI8;
												//value.UInt64Value = unchecked((ulong)-1);
												break;

                        value.VarType = VarEnum.VT_UI8;
                        UInt64 size;
                        if (_updateData.Mode != InternalCompressionMode.Modify)
                        {
                            if (_files == null)
                            {
                                if (_streams == null)
                                {
                                    size = _bytesCount > 0 ? (ulong) _bytesCount : 0;
                                }
                                else
                                {
                                    size = (ulong) (_streams[index] == null? 0 : _streams[index].Length);
                                }
                            }
                            else
                            {
                                size = (_files[index].Attributes & FileAttributes.Directory) == 0
                                           ? (ulong) _files[index].Length
                                           : 0;
                            }
                        }
                        else
                        {
                            size = _updateData.ArchiveFileData[(int) index].Size;
                        }
                        value.UInt64Value = size;

                        #endregion
                        break;
                    case ItemPropId.Attributes:
                        value.VarType = VarEnum.VT_UI4;
                        if (_updateData.Mode != InternalCompressionMode.Modify)
                        {
                            if (_files == null)
                            {
                                if (_streams == null)
                                {
                                    value.UInt32Value = (uint)FileAttributes.Normal;
                                }
                                else
                                {
                                    value.UInt32Value = (uint)(_streams[index] == null ? FileAttributes.Directory : FileAttributes.Normal);
                                }
                            }
                            else
                            {
                                value.UInt32Value = (uint) _files[index].Attributes;
                            }
                        }
                        else
                        {
                            value.UInt32Value = _updateData.ArchiveFileData[(int) index].Attributes;
                        }
                        break;
                    #region Times
                    case ItemPropId.CreationTime:
                        value.VarType = VarEnum.VT_FILETIME;
                        if (_updateData.Mode != InternalCompressionMode.Modify)
                        {
                            value.Int64Value = _files == null
                                               ? DateTime.Now.ToFileTime()
                                               : _files[index].CreationTime.ToFileTime();
                        }
                        else
                        {
                            value.Int64Value = _updateData.ArchiveFileData[(int) index].CreationTime.ToFileTime();
                        }
                        break;
                    case ItemPropId.LastAccessTime:
                        value.VarType = VarEnum.VT_FILETIME;
                        if (_updateData.Mode != InternalCompressionMode.Modify)
                        {
                            value.Int64Value = _files == null
                                               ? DateTime.Now.ToFileTime()
                                               : _files[index].LastAccessTime.ToFileTime();
                        }
                        else
                        {
                            value.Int64Value = _updateData.ArchiveFileData[(int) index].LastAccessTime.ToFileTime();
                        }
                        break;
                    case ItemPropId.LastWriteTime:
                        value.VarType = VarEnum.VT_FILETIME;
                        if (_updateData.Mode != InternalCompressionMode.Modify)
                        {
                            value.Int64Value = _files == null
                                               ? DateTime.Now.ToFileTime()
                                               : _files[index].LastWriteTime.ToFileTime();
                        }
                        else
                        {
                            value.Int64Value = _updateData.ArchiveFileData[(int) index].LastWriteTime.ToFileTime();
                        }
                        break;
                    #endregion
                    case ItemPropId.Extension:
                        #region Extension

                        value.VarType = VarEnum.VT_BSTR;
                        if (_updateData.Mode != InternalCompressionMode.Modify)
                        {
                            try
                            {
                                val = _files != null
                                      ? _files[index].Extension.Substring(1)
                                      : _entries == null
                                          ? ""
                                          : Path.GetExtension(_entries[index]);
                                value.Value = Marshal.StringToBSTR(val);
                            }
                            catch (ArgumentException)
                            {
                                value.Value = Marshal.StringToBSTR("");
                            }
                        }
                        else
                        {
                            val = Path.GetExtension(_updateData.ArchiveFileData[(int) index].FileName);
                            value.Value = Marshal.StringToBSTR(val);
                        }

                        #endregion
                        break;
                }
            }
            catch (Exception e)
            {
                AddException(e);
            }
            return 0;
        }
        /// <summary>
        /// Sets output stream for writing unpacked data
        /// </summary>
        /// <param name="index">Current file index</param>
        /// <param name="outStream">Output stream pointer</param>
        /// <param name="askExtractMode">Extraction mode</param>
        /// <returns>0 if OK</returns>
        public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
        {
            outStream = null;

            if (Canceled)
            {
                return(-1);
            }
            _currentIndex = (int)index;
            if (askExtractMode == AskMode.Extract)
            {
                var fileName = _directory;
                if (!_fileIndex.HasValue)
                {
                    #region Extraction to a file

                    if (_actualIndexes == null || _actualIndexes.Contains(index))
                    {
                        var data = new PropVariant();
                        _archive.GetProperty(index, ItemPropId.Path, ref data);
                        string entryName = NativeMethods.SafeCast(data, "");

                        #region Get entryName

                        if (String.IsNullOrEmpty(entryName))
                        {
                            if (_filesCount == 1)
                            {
                                var archName = Path.GetFileName(_extractor.FileName);
                                archName = archName.Substring(0, archName.LastIndexOf('.'));
                                if (!archName.EndsWith(".tar", StringComparison.OrdinalIgnoreCase))
                                {
                                    archName += ".tar";
                                }
                                entryName = archName;
                            }
                            else
                            {
                                entryName = "[no name] " + index.ToString(CultureInfo.InvariantCulture);
                            }
                        }

                        #endregion

                        //ExtractionPath - TODO: Allow customization of where file is output to.
                        if (outputFilenameMapping != null)
                        {
                            fileName = outputFilenameMapping.Invoke(_extractor.ArchiveFileData.FirstOrDefault(x => x.Index == index));
                        }
                        else
                        {
                            fileName = Path.Combine(_directory, _directoryStructure ? entryName : Path.GetFileName(entryName));
                        }

                        _archive.GetProperty(index, ItemPropId.IsDirectory, ref data);
                        try
                        {
                            fileName = ValidateFileName(fileName);
                        }
                        catch (Exception e)
                        {
                            AddException(e);
                            goto FileExtractionStartedLabel;
                        }
                        if (!NativeMethods.SafeCast(data, false))
                        {
                            #region Branch

                            _archive.GetProperty(index, ItemPropId.LastWriteTime, ref data);
                            var time = NativeMethods.SafeCast(data, DateTime.MinValue);
                            if (File.Exists(fileName))
                            {
                                var fnea = new FileOverwriteEventArgs(fileName);
                                OnFileExists(fnea);
                                if (fnea.Cancel)
                                {
                                    Canceled = true;
                                    return(-1);
                                }
                                if (String.IsNullOrEmpty(fnea.FileName))
                                {
                                    outStream = _fakeStream;

                                    goto FileExtractionStartedLabel;
                                }
                                fileName = fnea.FileName;
                            }
                            try
                            {
                                if (File.Exists(fileName))
                                {
                                    //Ensure existing file is not read only
                                    FileAttributes attributes = File.GetAttributes(fileName);

                                    if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                                    {
                                        // Make the file RW
                                        attributes = attributes & ~FileAttributes.ReadOnly;
                                        File.SetAttributes(fileName, attributes);
                                    }
                                }
                                _fileStream = new OutStreamWrapper(File.Create(fileName), fileName, time, true);
                            }
                            catch (Exception e)
                            {
                                if (e is FileNotFoundException)
                                {
                                    AddException(
                                        new IOException("The file \"" + fileName +
                                                        "\" was not extracted due to the File.Create fail."));
                                }
                                else
                                {
                                    AddException(e);
                                }
                                outStream = _fakeStream;
                                goto FileExtractionStartedLabel;
                            }
                            _fileStream.BytesWritten += IntEventArgsHandler;
                            outStream = _fileStream;

                            #endregion
                        }
                        else
                        {
                            #region Branch

                            if (!Directory.Exists(fileName))
                            {
                                try
                                {
                                    Directory.CreateDirectory(fileName);
                                }
                                catch (Exception e)
                                {
                                    AddException(e);
                                }
                                outStream = _fakeStream;
                            }

                            #endregion
                        }
                    }
                    else
                    {
                        outStream = _fakeStream;
                    }

                    #endregion
                }
                else
                {
                    #region Extraction to a stream

                    if (index == _fileIndex)
                    {
                        outStream  = _fileStream;
                        _fileIndex = null;
                    }
                    else
                    {
                        outStream = _fakeStream;
                    }

                    #endregion
                }

FileExtractionStartedLabel:
                _doneRate += 1.0f / _filesCount;
                var iea = new FileInfoEventArgs(
                    _extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate));
                OnFileExtractionStarted(iea);
                if (iea.Cancel)
                {
                    if (!String.IsNullOrEmpty(fileName))
                    {
                        _fileStream.Dispose();
                        if (File.Exists(fileName))
                        {
                            try
                            {
                                File.Delete(fileName);
                            }
                            catch (Exception e)
                            {
                                AddException(e);
                            }
                        }
                    }
                    Canceled = true;
                    return(-1);
                }
            }
            return(0);
        }
예제 #7
0
        public int GetProperty(uint index, ItemPropId propID, ref PropVariant value)
        {
            index -= _indexOffset;
            try
            {
                switch (propID)
                {
                case ItemPropId.IsAnti:
                    value.VarType     = VarEnum.VT_BOOL;
                    value.UInt64Value = 0;
                    break;

                case ItemPropId.Path:
                    #region Path

                    value.VarType = VarEnum.VT_BSTR;
                    string val = DefaultItemName;

                    if (_updateData.Mode != InternalCompressionMode.Modify)
                    {
                        if (_files == null)
                        {
                            if (_entries != null)
                            {
                                val = _entries[index];
                            }
                        }
                        else
                        {
                            if (_directoryStructure)
                            {
                                if (_rootLength > 0)
                                {
                                    val = _files[index].FullName.Substring(_rootLength);
                                }
                                else
                                {
                                    val = _files[index].FullName[0] + _files[index].FullName.Substring(2);
                                }
                            }
                            else
                            {
                                val = _files[index].Name;
                            }
                        }
                    }
                    else
                    {
                        val = _updateData.FileNamesToModify[(int)index];
                    }
                    value.Value = Marshal.StringToBSTR(val);
                    #endregion
                    break;

                case ItemPropId.IsDirectory:
                    value.VarType = VarEnum.VT_BOOL;
                    if (_updateData.Mode != InternalCompressionMode.Modify)
                    {
                        if (_files == null)
                        {
                            if (_streams == null)
                            {
                                value.UInt64Value = 0;
                            }
                            else
                            {
                                value.UInt64Value = (ulong)(_streams[index] == null ? 1 : 0);
                            }
                        }
                        else
                        {
                            value.UInt64Value = (byte)(_files[index].Attributes & FileAttributes.Directory);
                        }
                    }
                    else
                    {
                        value.UInt64Value = Convert.ToUInt64(_updateData.ArchiveFileData[(int)index].IsDirectory);
                    }
                    break;

                case ItemPropId.Size:
                    #region Size

                    value.VarType = VarEnum.VT_UI8;
                    UInt64 size;
                    if (_updateData.Mode != InternalCompressionMode.Modify)
                    {
                        if (_files == null)
                        {
                            if (_streams == null)
                            {
                                size = _bytesCount > 0 ? (ulong)_bytesCount : 0;
                            }
                            else
                            {
                                size = (ulong)(_streams[index] == null? 0 : _streams[index].Length);
                            }
                        }
                        else
                        {
                            size = (_files[index].Attributes & FileAttributes.Directory) == 0
                                           ? (ulong)_files[index].Length
                                           : 0;
                        }
                    }
                    else
                    {
                        size = _updateData.ArchiveFileData[(int)index].Size;
                    }
                    value.UInt64Value = size;

                    #endregion
                    break;

                case ItemPropId.Attributes:
                    value.VarType = VarEnum.VT_UI4;
                    if (_updateData.Mode != InternalCompressionMode.Modify)
                    {
                        if (_files == null)
                        {
                            if (_streams == null)
                            {
                                value.UInt32Value = (uint)FileAttributes.Normal;
                            }
                            else
                            {
                                value.UInt32Value = (uint)(_streams[index] == null ? FileAttributes.Directory : FileAttributes.Normal);
                            }
                        }
                        else
                        {
                            value.UInt32Value = (uint)_files[index].Attributes;
                        }
                    }
                    else
                    {
                        value.UInt32Value = _updateData.ArchiveFileData[(int)index].Attributes;
                    }
                    break;

                    #region Times
                case ItemPropId.CreationTime:
                    value.VarType = VarEnum.VT_FILETIME;
                    if (_updateData.Mode != InternalCompressionMode.Modify)
                    {
                        value.Int64Value = _files == null
                                               ? DateTime.Now.ToFileTime()
                                               : _files[index].CreationTime.ToFileTime();
                    }
                    else
                    {
                        value.Int64Value = _updateData.ArchiveFileData[(int)index].CreationTime.ToFileTime();
                    }
                    break;

                case ItemPropId.LastAccessTime:
                    value.VarType = VarEnum.VT_FILETIME;
                    if (_updateData.Mode != InternalCompressionMode.Modify)
                    {
                        value.Int64Value = _files == null
                                               ? DateTime.Now.ToFileTime()
                                               : _files[index].LastAccessTime.ToFileTime();
                    }
                    else
                    {
                        value.Int64Value = _updateData.ArchiveFileData[(int)index].LastAccessTime.ToFileTime();
                    }
                    break;

                case ItemPropId.LastWriteTime:
                    value.VarType = VarEnum.VT_FILETIME;
                    if (_updateData.Mode != InternalCompressionMode.Modify)
                    {
                        value.Int64Value = _files == null
                                               ? DateTime.Now.ToFileTime()
                                               : _files[index].LastWriteTime.ToFileTime();
                    }
                    else
                    {
                        value.Int64Value = _updateData.ArchiveFileData[(int)index].LastWriteTime.ToFileTime();
                    }
                    break;

                    #endregion
                case ItemPropId.Extension:
                    #region Extension

                    value.VarType = VarEnum.VT_BSTR;
                    if (_updateData.Mode != InternalCompressionMode.Modify)
                    {
                        try
                        {
                            val = _files != null
                                      ? _files[index].Extension.Substring(1)
                                      : _entries == null
                                          ? ""
                                          : Path.GetExtension(_entries[index]);
                            value.Value = Marshal.StringToBSTR(val);
                        }
                        catch (ArgumentException)
                        {
                            value.Value = Marshal.StringToBSTR("");
                        }
                    }
                    else
                    {
                        val         = Path.GetExtension(_updateData.ArchiveFileData[(int)index].FileName);
                        value.Value = Marshal.StringToBSTR(val);
                    }

                    #endregion
                    break;
                }
            }
            catch (Exception e)
            {
                AddException(e);
            }
            return(0);
        }
예제 #8
0
        /// <summary>
        /// Sets output stream for writing unpacked data
        /// </summary>
        /// <param name="index">Current file index</param>
        /// <param name="outStream">Output stream pointer</param>
        /// <param name="askExtractMode">Extraction mode</param>
        /// <returns>0 if OK</returns>
        public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
        {
            outStream = null;

            if (Canceled)
            {
                return(-1);
            }

            _currentIndex = (int)index;

            if (askExtractMode == AskMode.Extract)
            {
                var fileName = _directory;

                if (!_fileIndex.HasValue)
                {
                    // Extraction to a file

                    if (_actualIndexes == null || _actualIndexes.Contains(index))
                    {
                        var data = new PropVariant();
                        _archive.GetProperty(index, ItemPropId.Path, ref data);
                        var entryName = NativeMethods.SafeCast(data, "");

                        #region Get entryName

                        if (string.IsNullOrEmpty(entryName))
                        {
                            if (_filesCount == 1)
                            {
                                var archName = Path.GetFileName(_extractor.FileName);
                                archName = archName.Substring(0,
                                                              archName.LastIndexOf('.'));
                                if (!archName.EndsWith(".tar",
                                                       StringComparison.OrdinalIgnoreCase))
                                {
                                    archName += ".tar";
                                }

                                entryName = archName;
                            }
                            else
                            {
                                entryName = "[no name] " + index.ToString(CultureInfo.InvariantCulture);
                            }
                        }

                        #endregion

                        try
                        {
                            fileName = Path.Combine(RemoveIllegalCharacters(_directory, true), RemoveIllegalCharacters(_directoryStructure ? entryName : Path.GetFileName(entryName)));

                            if (string.IsNullOrEmpty(fileName))
                            {
                                throw new SevenZipArchiveException("Some archive name is null or empty.");
                            }
                        }
                        catch (Exception e)
                        {
                            AddException(e);
                            outStream = _fakeStream;

                            return(0);
                        }

                        _archive.GetProperty(index, ItemPropId.IsDirectory, ref data);

                        if (!NativeMethods.SafeCast(data, false))
                        {
                            _archive.GetProperty(index, ItemPropId.LastWriteTime, ref data);
                            var time = NativeMethods.SafeCast(data, DateTime.MinValue);

                            if (File.Exists(fileName))
                            {
                                var fnea = new FileOverwriteEventArgs(fileName);

                                FileExists?.Invoke(this, fnea);

                                if (fnea.Cancel)
                                {
                                    Canceled = true;
                                    return(-1);
                                }

                                if (string.IsNullOrEmpty(fnea.FileName))
                                {
                                    outStream = _fakeStream;
                                }
                                else
                                {
                                    fileName = fnea.FileName;
                                }
                            }

                            _doneRate += 1.0f / _filesCount;
                            var iea = new FileInfoEventArgs(_extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate));

                            FileExtractionStarted?.Invoke(this, iea);

                            if (iea.Cancel)
                            {
                                Canceled = true;
                                return(-1);
                            }

                            if (iea.Skip)
                            {
                                outStream = _fakeStream;
                                return(0);
                            }

                            CreateDirectory(fileName);

                            try
                            {
                                _fileStream = new OutStreamWrapper(File.Create(fileName), fileName, time, true);
                            }
                            catch (Exception e)
                            {
                                AddException(e is FileNotFoundException
                                    ? new IOException($"The file \"{fileName}\" was not extracted due to the File.Create fail.")
                                    : e);

                                outStream = _fakeStream;

                                return(0);
                            }

                            _fileStream.BytesWritten += IntEventArgsHandler;
                            outStream = _fileStream;
                        }
                        else
                        {
                            _doneRate += 1.0f / _filesCount;
                            var iea = new FileInfoEventArgs(_extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate));
                            FileExtractionStarted?.Invoke(this, iea);

                            if (iea.Cancel)
                            {
                                Canceled = true;
                                return(-1);
                            }

                            if (iea.Skip)
                            {
                                outStream = _fakeStream;
                                return(0);
                            }

                            if (!Directory.Exists(fileName))
                            {
                                try
                                {
                                    Directory.CreateDirectory(fileName);
                                }
                                catch (Exception e)
                                {
                                    AddException(e);
                                }

                                outStream = _fakeStream;
                            }
                        }
                    }
                    else
                    {
                        outStream = _fakeStream;
                    }
                }
                else
                {
                    // Extraction to a stream.

                    if (index == _fileIndex)
                    {
                        outStream  = _fileStream;
                        _fileIndex = null;
                    }
                    else
                    {
                        outStream = _fakeStream;
                    }
                }
            }

            return(0);
        }