Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting an archive entry would create a file that is outside the specified destination directory

When trying to extract a .jar file, I keep getting:

Extracting an archive entry would create a file that is outside the specified destination directory

Can anyone help me? Here is my code:

try
{
    using (ZipArchive archive = ZipFile.Open(jarLocationTXT.Text, ZipArchiveMode.Update))
    {
        archive.ExtractToDirectory(@"C:\Users\Neglekt\Monix Software\MCMI\CurExtract\");
    } 
}
catch (IOException ExtrEx)
{
    MessageBox.Show(ExtrEx.ToString());
    MessageBox.Show("An error occured while processing your data! \n Error code: E:002", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
like image 986
Marooca Avatar asked Oct 19 '25 09:10

Marooca


1 Answers

ZipFile.ExtractToDirectory fails if the zip contains an empty root /

Use ZipFileEx.ExtractToDirectory below instead:

namespace System.IO.Compression {
  public static class ZipFileEx {
    public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName) =>
    ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName, entryNameEncoding: null, overwriteFiles: false);

    public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName, bool overwriteFiles) =>
        ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName, entryNameEncoding: null, overwriteFiles: overwriteFiles);

    public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName, Encoding? entryNameEncoding) =>
        ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName, entryNameEncoding: entryNameEncoding, overwriteFiles: false);

    public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName, Encoding? entryNameEncoding, bool overwriteFiles)
    {
      ArgumentNullException.ThrowIfNull(sourceArchiveFileName);
      ArgumentNullException.ThrowIfNull(destinationDirectoryName);

      using ZipArchive archive = ZipFile.Open(sourceArchiveFileName, ZipArchiveMode.Read, entryNameEncoding);

      foreach (ZipArchiveEntry entry in archive.Entries) {
        DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
        string destinationDirectoryFullPath = di.FullName;
        if (!destinationDirectoryFullPath.EndsWith(Path.DirectorySeparatorChar)) {
          char sep = Path.DirectorySeparatorChar;
          destinationDirectoryFullPath = string.Concat(destinationDirectoryFullPath, new ReadOnlySpan<char>(in sep));
        }

        string entryFullName = entry.FullName;
        if (entryFullName.Length > 0 && entryFullName[0] == '/') entryFullName = entryFullName[1..]; // remove leading root

        string fileDestinationPath = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, entryFullName.Replace('\0', '_')));

        var IsCaseSensitive = !(OperatingSystem.IsWindows() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || OperatingSystem.IsTvOS() || OperatingSystem.IsWatchOS());
        var stringComparison = IsCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;

        if (!fileDestinationPath.StartsWith(destinationDirectoryFullPath,stringComparison)) throw new IOException(@"Extracting Zip entry would have resulted in a file outside the specified destination directory.");

        if (Path.GetFileName(fileDestinationPath).Length == 0) {
          if (entry.Length != 0) throw new IOException(@"Zip entry name ends in directory separator character but contains data.");
          Directory.CreateDirectory(fileDestinationPath);

        } else {
          Directory.CreateDirectory(Path.GetDirectoryName(fileDestinationPath)!);
          entry.ExtractToFile(fileDestinationPath, overwrite: overwriteFiles);
        }
      }
    }
  }
}

Above is an exact copy of ZipFile.ExtractToDirectory except for the line that checks for entryFullName[0] == '/'

like image 160
kofifus Avatar answered Oct 21 '25 21:10

kofifus