1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 17:32:54 +08:00

Merge pull request #6465 from bdach/ignore-macosx-folder-in-archives

Filter out OS-generated files from ZIP archives
This commit is contained in:
Dean Herbert 2019-10-11 18:10:54 +09:00 committed by GitHub
commit 3c5dc6da4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 12 deletions

View File

@ -29,7 +29,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestImportWhenClosed() public async Task TestImportWhenClosed()
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWhenClosed")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportWhenClosed)))
{ {
try try
{ {
@ -46,7 +46,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestImportThenDelete() public async Task TestImportThenDelete()
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenDelete")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportThenDelete)))
{ {
try try
{ {
@ -67,7 +67,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestImportThenImport() public async Task TestImportThenImport()
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImport")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportThenImport)))
{ {
try try
{ {
@ -94,7 +94,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestImportCorruptThenImport() public async Task TestImportCorruptThenImport()
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImport")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportCorruptThenImport)))
{ {
try try
{ {
@ -136,7 +136,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestRollbackOnFailure() public async Task TestRollbackOnFailure()
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestRollbackOnFailure")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestRollbackOnFailure)))
{ {
try try
{ {
@ -213,7 +213,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestImportThenImportDifferentHash() public async Task TestImportThenImportDifferentHash()
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImportDifferentHash")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportThenImportDifferentHash)))
{ {
try try
{ {
@ -244,7 +244,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestImportThenDeleteThenImport() public async Task TestImportThenDeleteThenImport()
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenDeleteThenImport")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportThenDeleteThenImport)))
{ {
try try
{ {
@ -272,7 +272,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestImportThenDeleteThenImportWithOnlineIDMismatch(bool set) public async Task TestImportThenDeleteThenImportWithOnlineIDMismatch(bool set)
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost($"TestImportThenDeleteThenImport-{set}")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost($"{nameof(TestImportThenDeleteThenImportWithOnlineIDMismatch)}-{set}"))
{ {
try try
{ {
@ -306,7 +306,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public async Task TestImportWithDuplicateBeatmapIDs() public async Task TestImportWithDuplicateBeatmapIDs()
{ {
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWithDuplicateBeatmapID")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportWithDuplicateBeatmapIDs)))
{ {
try try
{ {
@ -392,7 +392,7 @@ namespace osu.Game.Tests.Beatmaps.IO
[Test] [Test]
public async Task TestImportWhenFileOpen() public async Task TestImportWhenFileOpen()
{ {
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWhenFileOpen")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportWhenFileOpen)))
{ {
try try
{ {
@ -414,7 +414,7 @@ namespace osu.Game.Tests.Beatmaps.IO
[Test] [Test]
public async Task TestImportNestedStructure() public async Task TestImportNestedStructure()
{ {
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportNestedStructure")) using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportNestedStructure)))
{ {
try try
{ {
@ -456,6 +456,60 @@ namespace osu.Game.Tests.Beatmaps.IO
} }
} }
[Test]
public async Task TestImportWithIgnoredDirectoryInArchive()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportWithIgnoredDirectoryInArchive)))
{
try
{
var osu = loadOsu(host);
var temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted";
string dataFolder = Path.Combine(extractedFolder, "actual_data");
string resourceForkFolder = Path.Combine(extractedFolder, "__MACOSX");
string resourceForkFilePath = Path.Combine(resourceForkFolder, ".extracted");
Directory.CreateDirectory(dataFolder);
Directory.CreateDirectory(resourceForkFolder);
using (var resourceForkFile = File.CreateText(resourceForkFilePath))
{
resourceForkFile.WriteLine("adding content so that it's not empty");
}
try
{
using (var zip = ZipArchive.Open(temp))
zip.WriteToDirectory(dataFolder);
using (var zip = ZipArchive.Create())
{
zip.AddAllFromDirectory(extractedFolder);
zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate));
}
var imported = await osu.Dependencies.Get<BeatmapManager>().Import(temp);
ensureLoaded(osu);
Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("__MACOSX")), "Files contain resource fork folder, which should be ignored");
Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("actual_data")), "Files contain common subfolder");
}
finally
{
Directory.Delete(extractedFolder, true);
}
}
finally
{
host.Exit();
}
}
}
public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null) public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null)
{ {
var temp = path ?? TestResources.GetTestBeatmapForImport(); var temp = path ?? TestResources.GetTestBeatmapForImport();

View File

@ -1,15 +1,30 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using SharpCompress.Archives.Zip; using SharpCompress.Archives.Zip;
using SharpCompress.Common;
namespace osu.Game.IO.Archives namespace osu.Game.IO.Archives
{ {
public sealed class ZipArchiveReader : ArchiveReader public sealed class ZipArchiveReader : ArchiveReader
{ {
/// <summary>
/// List of substrings that indicate a file should be ignored during the import process
/// (usually due to representing no useful data and being autogenerated by the OS).
/// </summary>
private static readonly string[] filename_ignore_list =
{
// Mac-specific
"__MACOSX",
".DS_Store",
// Windows-specific
"Thumbs.db"
};
private readonly Stream archiveStream; private readonly Stream archiveStream;
private readonly ZipArchive archive; private readonly ZipArchive archive;
@ -43,7 +58,9 @@ namespace osu.Game.IO.Archives
archiveStream.Dispose(); archiveStream.Dispose();
} }
public override IEnumerable<string> Filenames => archive.Entries.Select(e => e.Key).ToArray(); private static bool canBeIgnored(IEntry entry) => filename_ignore_list.Any(ignoredName => entry.Key.IndexOf(ignoredName, StringComparison.OrdinalIgnoreCase) >= 0);
public override IEnumerable<string> Filenames => archive.Entries.Where(e => !canBeIgnored(e)).Select(e => e.Key).ToArray();
public override Stream GetUnderlyingStream() => archiveStream; public override Stream GetUnderlyingStream() => archiveStream;
} }