You've already forked linux-packaging-mono
Imported Upstream version 4.4.2.4
Former-commit-id: 92904c9c5915c37244316e42ba99e7b934ed7ee2
This commit is contained in:
parent
589d484eee
commit
0b4a830db1
@ -82,10 +82,14 @@ namespace SharpCompress.Archive
|
||||
{
|
||||
key = key.Substring(1);
|
||||
}
|
||||
// .NET allows duplicate entries when saving and loading Zip files.
|
||||
// The following lines are disabled from upstream SharpCompress to allow this.
|
||||
#if ZIP_ALLOW_DUPLICATE_KEYS
|
||||
if (DoesKeyMatchExisting(key))
|
||||
{
|
||||
throw new ArchiveException("Cannot add entry with duplicate key: " + key);
|
||||
}
|
||||
#endif
|
||||
var entry = CreateEntry(key, source, size, modified, closeStream);
|
||||
newEntries.Add(entry);
|
||||
RebuildModifiedCollection();
|
||||
@ -101,7 +105,8 @@ namespace SharpCompress.Archive
|
||||
{
|
||||
p = p.Substring(1);
|
||||
}
|
||||
return string.Equals(p, key, StringComparison.OrdinalIgnoreCase);
|
||||
if (string.Equals(p, key, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -32,5 +32,10 @@ namespace SharpCompress.Archive.Zip
|
||||
{
|
||||
get { return (Parts.Single() as SeekableZipFilePart).Comment; }
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Key;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,13 @@ namespace SharpCompress.Common.Zip
|
||||
this.filePart = filePart;
|
||||
lastModifiedTime = Utility.DosDateToDateTime(filePart.Header.LastModifiedDate,
|
||||
filePart.Header.LastModifiedTime);
|
||||
if (lastModifiedTime == default(DateTime))
|
||||
{
|
||||
// On .NET on Windows, for zip entries that don't have a last write time,
|
||||
// the return value for ZipArchiveEntry.LastWriteTime is:
|
||||
// 1/1/1980 12:00:00 AM, Ticks=624511296000000000
|
||||
lastModifiedTime = new DateTime(624511296000000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ namespace SharpCompress.IO
|
||||
{
|
||||
stream.Position = origin.Value;
|
||||
}
|
||||
length = bytesToRead;
|
||||
BytesLeftToRead = bytesToRead;
|
||||
}
|
||||
|
||||
@ -27,6 +28,8 @@ namespace SharpCompress.IO
|
||||
}
|
||||
}
|
||||
|
||||
private long length;
|
||||
|
||||
private long BytesLeftToRead { get; set; }
|
||||
|
||||
public Stream Stream { get; private set; }
|
||||
@ -53,12 +56,12 @@ namespace SharpCompress.IO
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { throw new System.NotImplementedException(); }
|
||||
get { return length; }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { throw new System.NotImplementedException(); }
|
||||
get { return Length - BytesLeftToRead; }
|
||||
set { throw new System.NotImplementedException(); }
|
||||
}
|
||||
|
||||
|
@ -238,6 +238,56 @@ namespace MonoTests.System.IO.Compression
|
||||
File.Delete ("create.zip");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipEnumerateArchiveDefaultLastWriteTime()
|
||||
{
|
||||
using (var archive = new ZipArchive(File.Open("test.nupkg", FileMode.Open),
|
||||
ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = archive.GetEntry("_rels/.rels");
|
||||
Assert.AreEqual(new DateTime(624511296000000000).Ticks, entry.LastWriteTime.Ticks);
|
||||
Assert.IsNotNull(entry);
|
||||
}
|
||||
}
|
||||
|
||||
public void ZipGetArchiveEntryStreamLengthPosition(ZipArchiveMode mode)
|
||||
{
|
||||
File.Copy("test.nupkg", "test2.nupkg", overwrite: true);
|
||||
using (var archive = new ZipArchive(File.Open("test2.nupkg", FileMode.Open), mode))
|
||||
{
|
||||
var entry = archive.GetEntry("_rels/.rels");
|
||||
using (var stream = entry.Open())
|
||||
{
|
||||
Assert.AreEqual(0, stream.Position);
|
||||
Assert.AreEqual(425, stream.Length);
|
||||
}
|
||||
|
||||
// .NET does not support these in Read mode but we do.
|
||||
var entry2 = archive.GetEntry("modernhttpclient.nuspec");
|
||||
using (var stream = entry2.Open())
|
||||
{
|
||||
Assert.AreEqual(857, stream.Length);
|
||||
if (mode == ZipArchiveMode.Update)
|
||||
{
|
||||
Assert.AreEqual(0, stream.Position);
|
||||
}
|
||||
}
|
||||
}
|
||||
File.Delete ("test2.nupkg");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipGetArchiveEntryStreamLengthPositionReadMode()
|
||||
{
|
||||
ZipGetArchiveEntryStreamLengthPosition(ZipArchiveMode.Read);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipGetArchiveEntryStreamLengthPositionUpdateMode()
|
||||
{
|
||||
ZipGetArchiveEntryStreamLengthPosition(ZipArchiveMode.Update);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipEnumerateEntriesReadMode()
|
||||
{
|
||||
@ -258,6 +308,104 @@ namespace MonoTests.System.IO.Compression
|
||||
File.Delete ("test.zip");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipWriteEntriesUpdateMode()
|
||||
{
|
||||
File.Copy("archive.zip", "test.zip", overwrite: true);
|
||||
using (var archive = new ZipArchive(File.Open("test.zip", FileMode.Open),
|
||||
ZipArchiveMode.Update))
|
||||
{
|
||||
var foo = archive.GetEntry("foo.txt");
|
||||
using (var stream = foo.Open())
|
||||
using (var sw = new StreamWriter(stream))
|
||||
{
|
||||
sw.Write("TEST");
|
||||
}
|
||||
}
|
||||
|
||||
using (var archive = new ZipArchive(File.Open("test.zip", FileMode.Open),
|
||||
ZipArchiveMode.Read))
|
||||
{
|
||||
var foo = archive.GetEntry("foo.txt");
|
||||
using (var stream = foo.Open())
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
var line = sr.ReadLine();
|
||||
Assert.AreEqual("TEST", line);
|
||||
}
|
||||
}
|
||||
|
||||
File.Delete ("test.zip");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipWriteEntriesUpdateModeNewEntry()
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
var zipArchive = new ZipArchive(stream, ZipArchiveMode.Update);
|
||||
|
||||
var newEntry = zipArchive.CreateEntry("testEntry");
|
||||
|
||||
using (var newStream = newEntry.Open())
|
||||
{
|
||||
using (var sw = new StreamWriter(newStream))
|
||||
{
|
||||
sw.Write("TEST");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipCreateDuplicateEntriesUpdateMode()
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
using (var zipArchive = new ZipArchive(stream, ZipArchiveMode.Update, true))
|
||||
{
|
||||
var e2 = zipArchive.CreateEntry("BBB");
|
||||
var e3 = zipArchive.CreateEntry("BBB");
|
||||
}
|
||||
|
||||
stream.Position = 0;
|
||||
using (var zipArchive = new ZipArchive(stream, ZipArchiveMode.Read))
|
||||
{
|
||||
Assert.AreEqual(2, zipArchive.Entries.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipWriteEntriesUpdateModeNonZeroPosition()
|
||||
{
|
||||
File.Copy("archive.zip", "test.zip", overwrite: true);
|
||||
using (var archive = new ZipArchive(File.Open("test.zip", FileMode.Open),
|
||||
ZipArchiveMode.Update))
|
||||
{
|
||||
var foo = archive.GetEntry("foo.txt");
|
||||
using (var stream = foo.Open())
|
||||
{
|
||||
var line = stream.ReadByte();
|
||||
using (var sw = new StreamWriter(stream))
|
||||
{
|
||||
sw.Write("TEST");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (var archive = new ZipArchive(File.Open("test.zip", FileMode.Open),
|
||||
ZipArchiveMode.Read))
|
||||
{
|
||||
var entries = archive.Entries;
|
||||
var foo = archive.GetEntry("foo.txt");
|
||||
using (var stream = foo.Open())
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
var line = sr.ReadLine();
|
||||
Assert.AreEqual("fTEST", line);
|
||||
}
|
||||
}
|
||||
|
||||
File.Delete ("test.zip");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipEnumerateEntriesUpdateMode()
|
||||
{
|
||||
@ -307,5 +455,24 @@ namespace MonoTests.System.IO.Compression
|
||||
}
|
||||
File.Delete ("empty.zip");
|
||||
}
|
||||
|
||||
class MyFakeStream : FileStream
|
||||
{
|
||||
public MyFakeStream (string path, FileMode mode) : base(path, mode) {}
|
||||
|
||||
/// <summary>
|
||||
/// Simulate "CanSeek" is false, which is the case when you are retreiving data from web.
|
||||
/// </summary>
|
||||
public override bool CanSeek => false;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipReadNonSeekableStream()
|
||||
{
|
||||
var stream = new MyFakeStream("test.nupkg", FileMode.Open);
|
||||
using (var archive = new ZipArchive (stream, ZipArchiveMode.Read))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ namespace System.IO.Compression
|
||||
internal readonly ZipArchiveMode mode;
|
||||
internal Encoding entryNameEncoding;
|
||||
internal bool disposed;
|
||||
internal Dictionary<string, ZipArchiveEntry> entries;
|
||||
internal List<ZipArchiveEntry> entries;
|
||||
internal SharpCompress.Archive.Zip.ZipArchive zipFile;
|
||||
|
||||
public ZipArchive (Stream stream)
|
||||
@ -49,7 +49,7 @@ namespace System.IO.Compression
|
||||
|
||||
this.stream = stream;
|
||||
mode = ZipArchiveMode.Read;
|
||||
CreateZip(stream, mode);
|
||||
CreateZip(mode);
|
||||
}
|
||||
|
||||
public ZipArchive (Stream stream, ZipArchiveMode mode)
|
||||
@ -59,7 +59,7 @@ namespace System.IO.Compression
|
||||
|
||||
this.stream = stream;
|
||||
this.mode = mode;
|
||||
CreateZip(stream, mode);
|
||||
CreateZip(mode);
|
||||
}
|
||||
|
||||
public ZipArchive (Stream stream, ZipArchiveMode mode, bool leaveOpen)
|
||||
@ -70,7 +70,7 @@ namespace System.IO.Compression
|
||||
this.stream = stream;
|
||||
this.mode = mode;
|
||||
leaveStreamOpen = leaveOpen;
|
||||
CreateZip(stream, mode);
|
||||
CreateZip(mode);
|
||||
}
|
||||
|
||||
public ZipArchive (Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding entryNameEncoding)
|
||||
@ -82,40 +82,59 @@ namespace System.IO.Compression
|
||||
this.mode = mode;
|
||||
leaveStreamOpen = leaveOpen;
|
||||
this.entryNameEncoding = entryNameEncoding;
|
||||
CreateZip(stream, mode);
|
||||
CreateZip(mode);
|
||||
}
|
||||
|
||||
private void CreateZip(Stream stream, ZipArchiveMode mode)
|
||||
private void CreateZip(ZipArchiveMode mode)
|
||||
{
|
||||
if (mode != ZipArchiveMode.Read && mode != ZipArchiveMode.Create && mode != ZipArchiveMode.Update)
|
||||
throw new ArgumentOutOfRangeException("mode");
|
||||
|
||||
// If the mode parameter is set to Read, the stream must support reading.
|
||||
if (mode == ZipArchiveMode.Read && !stream.CanRead)
|
||||
throw new ArgumentException("Stream must support reading for Read archive mode");
|
||||
|
||||
// If the mode parameter is set to Create, the stream must support writing.
|
||||
if (mode == ZipArchiveMode.Create && !stream.CanWrite)
|
||||
throw new ArgumentException("Stream must support writing for Create archive mode");
|
||||
|
||||
// If the mode parameter is set to Update, the stream must support reading, writing, and seeking.
|
||||
if (mode == ZipArchiveMode.Update && (!stream.CanRead || !stream.CanWrite || !stream.CanSeek))
|
||||
throw new ArgumentException("Stream must support reading, writing and seeking for Update archive mode");
|
||||
|
||||
try {
|
||||
zipFile = mode != ZipArchiveMode.Create && stream.Length != 0
|
||||
? SharpCompress.Archive.Zip.ZipArchive.Open(stream)
|
||||
: SharpCompress.Archive.Zip.ZipArchive.Create();
|
||||
} catch (Exception e) {
|
||||
throw new InvalidDataException("The contents of the stream are not in the zip archive format.", e);
|
||||
}
|
||||
if (mode != ZipArchiveMode.Read && mode != ZipArchiveMode.Create && mode != ZipArchiveMode.Update)
|
||||
throw new ArgumentOutOfRangeException("mode");
|
||||
|
||||
entries = new Dictionary<string, ZipArchiveEntry>();
|
||||
if (Mode != ZipArchiveMode.Create) {
|
||||
foreach (var entry in zipFile.Entries) {
|
||||
var zipEntry = new ZipArchiveEntry(this, entry);
|
||||
entries[entry.Key] = zipEntry;
|
||||
// If the mode parameter is set to Read, the stream must support reading.
|
||||
if (mode == ZipArchiveMode.Read && !stream.CanRead)
|
||||
throw new ArgumentException("Stream must support reading for Read archive mode");
|
||||
|
||||
// If the mode parameter is set to Create, the stream must support writing.
|
||||
if (mode == ZipArchiveMode.Create && !stream.CanWrite)
|
||||
throw new ArgumentException("Stream must support writing for Create archive mode");
|
||||
|
||||
// If the mode parameter is set to Update, the stream must support reading, writing, and seeking.
|
||||
if (mode == ZipArchiveMode.Update && (!stream.CanRead || !stream.CanWrite || !stream.CanSeek))
|
||||
throw new ArgumentException("Stream must support reading, writing and seeking for Update archive mode");
|
||||
|
||||
// If the stream is not seekable, then buffer it into memory (same behavior as .NET).
|
||||
if (mode == ZipArchiveMode.Read && !stream.CanSeek)
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
stream.CopyTo(memoryStream);
|
||||
|
||||
if (!leaveStreamOpen)
|
||||
stream.Dispose();
|
||||
|
||||
this.stream = memoryStream;
|
||||
}
|
||||
|
||||
try {
|
||||
zipFile = mode != ZipArchiveMode.Create && stream.Length != 0
|
||||
? SharpCompress.Archive.Zip.ZipArchive.Open(stream)
|
||||
: SharpCompress.Archive.Zip.ZipArchive.Create();
|
||||
} catch (Exception e) {
|
||||
throw new InvalidDataException("The contents of the stream are not in the zip archive format.", e);
|
||||
}
|
||||
|
||||
entries = new List<ZipArchiveEntry>();
|
||||
if (Mode != ZipArchiveMode.Create) {
|
||||
foreach (var entry in zipFile.Entries) {
|
||||
var zipEntry = new ZipArchiveEntry(this, entry);
|
||||
entries.Add(zipEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
if (!leaveStreamOpen)
|
||||
stream.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +152,7 @@ namespace System.IO.Compression
|
||||
if (entries == null)
|
||||
return new ReadOnlyCollection<ZipArchiveEntry>(new List<ZipArchiveEntry>());
|
||||
|
||||
return new ReadOnlyCollection<ZipArchiveEntry>(entries.Values.ToList());
|
||||
return new ReadOnlyCollection<ZipArchiveEntry>(entries);
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +173,14 @@ namespace System.IO.Compression
|
||||
return CreateEntry(entryName, CompressionLevel.Optimal);
|
||||
}
|
||||
|
||||
internal SharpCompress.Archive.Zip.ZipArchiveEntry CreateEntryInternal(string entryName)
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
var entry = zipFile.AddEntry(entryName, memoryStream);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public ZipArchiveEntry CreateEntry (string entryName, CompressionLevel compressionLevel)
|
||||
{
|
||||
if (disposed)
|
||||
@ -171,10 +198,9 @@ namespace System.IO.Compression
|
||||
if (zipFile == null)
|
||||
throw new InvalidDataException("The zip archive is corrupt, and its entries cannot be retrieved.");
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
var entry = zipFile.AddEntry(entryName, memoryStream);
|
||||
var archiveEntry = new ZipArchiveEntry(this, entry);
|
||||
entries[entryName] = archiveEntry;
|
||||
var internalEntry = CreateEntryInternal(entryName);
|
||||
var archiveEntry = new ZipArchiveEntry(this, internalEntry);
|
||||
entries.Add(archiveEntry);
|
||||
|
||||
return archiveEntry;
|
||||
}
|
||||
@ -196,7 +222,7 @@ namespace System.IO.Compression
|
||||
if (zipFile == null)
|
||||
throw new InvalidDataException("The zip archive is corrupt, and its entries cannot be retrieved.");
|
||||
|
||||
return entries.ContainsKey(entryName) ? entries[entryName] : null;
|
||||
return entries.FirstOrDefault(e => e.FullName == entryName);
|
||||
}
|
||||
|
||||
private void Save()
|
||||
|
@ -32,7 +32,7 @@ namespace System.IO.Compression
|
||||
internal class ZipArchiveEntryStream : Stream, IDisposable
|
||||
{
|
||||
private readonly ZipArchiveEntry entry;
|
||||
private readonly Stream stream;
|
||||
private Stream stream;
|
||||
|
||||
public override bool CanRead {
|
||||
get {
|
||||
@ -42,19 +42,19 @@ namespace System.IO.Compression
|
||||
|
||||
public override bool CanSeek {
|
||||
get {
|
||||
return stream.CanSeek;
|
||||
return entry.Archive.Mode != ZipArchiveMode.Read;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanWrite {
|
||||
get {
|
||||
return stream.CanWrite;
|
||||
return entry.Archive.Mode != ZipArchiveMode.Read;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Length {
|
||||
get {
|
||||
return stream.Length;
|
||||
return stream.CanWrite ? stream.Length : entry.Length;
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,6 +98,34 @@ namespace System.IO.Compression
|
||||
stream.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
internal void EnsureWriteable()
|
||||
{
|
||||
if (entry.Archive.Mode == ZipArchiveMode.Update && !stream.CanWrite)
|
||||
{
|
||||
// Replace the read-only stream with a writeable memory stream.
|
||||
SetWriteable();
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetWriteable()
|
||||
{
|
||||
var archive = entry.Archive;
|
||||
|
||||
var internalEntry = entry.entry;
|
||||
var newEntry = archive.CreateEntryInternal(internalEntry.Key);
|
||||
var newStream = newEntry.OpenEntryStream();
|
||||
|
||||
var openStream = stream;
|
||||
openStream.CopyTo(newStream);
|
||||
openStream.Dispose();
|
||||
|
||||
newStream.Position = 0;
|
||||
|
||||
archive.zipFile.RemoveEntry(internalEntry);
|
||||
entry.entry = newEntry;
|
||||
stream = newStream;
|
||||
}
|
||||
|
||||
public new void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
@ -117,8 +145,9 @@ namespace System.IO.Compression
|
||||
|
||||
public class ZipArchiveEntry
|
||||
{
|
||||
readonly SharpCompress.Archive.Zip.ZipArchiveEntry entry;
|
||||
internal SharpCompress.Archive.Zip.ZipArchiveEntry entry;
|
||||
internal ZipArchiveEntryStream openStream;
|
||||
internal bool wasWritten;
|
||||
private bool wasDeleted;
|
||||
|
||||
internal ZipArchiveEntry(ZipArchive archive, SharpCompress.Archive.Zip.ZipArchiveEntry entry)
|
||||
@ -174,7 +203,7 @@ namespace System.IO.Compression
|
||||
if (Archive.disposed)
|
||||
throw new ObjectDisposedException("The zip archive for this entry has been disposed.");
|
||||
|
||||
if (Archive.Mode != ZipArchiveMode.Update)
|
||||
if (Archive.Mode != ZipArchiveMode.Update)
|
||||
throw new NotSupportedException("The zip archive for this entry was opened in a mode other than Update.");
|
||||
|
||||
if (openStream != null)
|
||||
@ -198,9 +227,16 @@ namespace System.IO.Compression
|
||||
if (Archive.Mode == ZipArchiveMode.Create && openStream != null)
|
||||
throw new IOException("The archive for this entry was opened with the Create mode, and this entry has already been written to.");
|
||||
|
||||
openStream = new ZipArchiveEntryStream(this, entry.OpenEntryStream());
|
||||
var entryStream = entry.OpenEntryStream();
|
||||
openStream = new ZipArchiveEntryStream(this, entryStream);
|
||||
openStream.EnsureWriteable();
|
||||
|
||||
return openStream;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return FullName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user