mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-22 23:15:20 +00:00
Merge pull request #460 from itn3000/tar-fix-garbled2
fix filename garbling in tar(#414)
This commit is contained in:
@@ -39,16 +39,17 @@ namespace SharpCompress.Common.Tar.Headers
|
||||
WriteOctalBytes(0, buffer, 116, 8); // group ID
|
||||
|
||||
//ArchiveEncoding.UTF8.GetBytes("magic").CopyTo(buffer, 257);
|
||||
if (Name.Length > 100)
|
||||
var nameByteCount = ArchiveEncoding.GetEncoding().GetByteCount(Name);
|
||||
if (nameByteCount > 100)
|
||||
{
|
||||
// Set mock filename and filetype to indicate the next block is the actual name of the file
|
||||
WriteStringBytes("././@LongLink", buffer, 0, 100);
|
||||
buffer[156] = (byte)EntryType.LongName;
|
||||
WriteOctalBytes(Name.Length + 1, buffer, 124, 12);
|
||||
WriteOctalBytes(nameByteCount + 1, buffer, 124, 12);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteStringBytes(Name, buffer, 0, 100);
|
||||
WriteStringBytes(ArchiveEncoding.Encode(Name), buffer, 0, 100);
|
||||
WriteOctalBytes(Size, buffer, 124, 12);
|
||||
var time = (long)(LastModifiedTime.ToUniversalTime() - EPOCH).TotalSeconds;
|
||||
WriteOctalBytes(time, buffer, 136, 12);
|
||||
@@ -69,10 +70,17 @@ namespace SharpCompress.Common.Tar.Headers
|
||||
|
||||
output.Write(buffer, 0, buffer.Length);
|
||||
|
||||
if (Name.Length > 100)
|
||||
if (nameByteCount > 100)
|
||||
{
|
||||
WriteLongFilenameHeader(output);
|
||||
Name = Name.Substring(0, 100);
|
||||
// update to short name lower than 100 - [max bytes of one character].
|
||||
// subtracting bytes is needed because preventing infinite loop(example code is here).
|
||||
//
|
||||
// var bytes = Encoding.UTF8.GetBytes(new string(0x3042, 100));
|
||||
// var truncated = Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(bytes, 0, 100));
|
||||
//
|
||||
// and then infinite recursion is occured in WriteLongFilenameHeader because truncated.Length is 102.
|
||||
Name = ArchiveEncoding.Decode(ArchiveEncoding.Encode(Name), 0, 100 - ArchiveEncoding.GetEncoding().GetMaxByteCount(1));
|
||||
Write(output);
|
||||
}
|
||||
}
|
||||
@@ -184,6 +192,17 @@ namespace SharpCompress.Common.Tar.Headers
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static void WriteStringBytes(byte[] name, byte[] buffer, int offset, int length)
|
||||
{
|
||||
int i = Math.Min(length, name.Length);
|
||||
Buffer.BlockCopy(name, 0, buffer, offset, i);
|
||||
// if Span<byte>.Fill can be used, it is more efficient
|
||||
for (; i < length; ++i)
|
||||
{
|
||||
buffer[offset + i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteStringBytes(string name, byte[] buffer, int offset, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -5,6 +5,10 @@ using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Writers;
|
||||
using Xunit;
|
||||
using System.Text;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Writers.Tar;
|
||||
using SharpCompress.Readers.Tar;
|
||||
|
||||
namespace SharpCompress.Test.Tar
|
||||
{
|
||||
@@ -26,7 +30,7 @@ namespace SharpCompress.Test.Tar
|
||||
{
|
||||
ArchiveFileRead("Tar.tar");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Tar_FileName_Exactly_100_Characters()
|
||||
{
|
||||
@@ -135,10 +139,17 @@ namespace SharpCompress.Test.Tar
|
||||
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.tar");
|
||||
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar");
|
||||
|
||||
// var aropt = new Ar
|
||||
|
||||
using (var archive = TarArchive.Create())
|
||||
{
|
||||
archive.AddAllFromDirectory(ORIGINAL_FILES_PATH);
|
||||
archive.SaveTo(scratchPath, CompressionType.None);
|
||||
var twopt = new TarWriterOptions(CompressionType.None, true);
|
||||
twopt.ArchiveEncoding = new ArchiveEncoding()
|
||||
{
|
||||
Default = Encoding.GetEncoding(866)
|
||||
};
|
||||
archive.SaveTo(scratchPath, twopt);
|
||||
}
|
||||
CompareArchivesByPath(unmodified, scratchPath);
|
||||
}
|
||||
@@ -195,5 +206,40 @@ namespace SharpCompress.Test.Tar
|
||||
Assert.True(archive.Type == ArchiveType.Tar);
|
||||
}
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(10)]
|
||||
[InlineData(128)]
|
||||
public void Tar_Japanese_Name(int length)
|
||||
{
|
||||
using (var mstm = new MemoryStream())
|
||||
{
|
||||
var enc = new ArchiveEncoding()
|
||||
{
|
||||
Default = Encoding.UTF8
|
||||
};
|
||||
var twopt = new TarWriterOptions(CompressionType.None, true);
|
||||
twopt.ArchiveEncoding = enc;
|
||||
var fname = new string((char)0x3042, length);
|
||||
using (var tw = new TarWriter(mstm, twopt))
|
||||
using (var input = new MemoryStream(new byte[32]))
|
||||
{
|
||||
tw.Write(fname, input, null);
|
||||
}
|
||||
using (var inputMemory = new MemoryStream(mstm.ToArray()))
|
||||
{
|
||||
var tropt = new ReaderOptions()
|
||||
{
|
||||
ArchiveEncoding = enc
|
||||
};
|
||||
using (var tr = TarReader.Open(inputMemory, tropt))
|
||||
{
|
||||
while (tr.MoveToNextEntry())
|
||||
{
|
||||
Assert.Equal(fname, tr.Entry.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user