Skip to content

System.IO.Packaging should perform case-insensitive matching when determining part media types #112783

Open
@impact-merlinzerbe

Description

@impact-merlinzerbe

Description

I am trying to use System.IO.Packaging with a package that uses lowercase part names but all caps names for content type overrides.

This is my package:

.
├── [Content_Types].xml
└── part

The file part is an empty file.

This is the content of [Content_Types].xml:

<?xml version="1.0" encoding="UTF-8"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
    <Override PartName="/PART" ContentType="text/plain"></Override>
</Types>

I use the following C# program to access the part:

using System;
using System.IO;
using System.IO.Packaging;

string zipFilePath = "minimal.zip";

var package = Package.Open(zipFilePath, FileMode.Open, FileAccess.Read);
package.GetPart(new Uri("/part", UriKind.Relative));

Running this program throws the following exception:

$ dotnet run
Unhandled exception. System.InvalidOperationException: Specified part does not exist in the package.
   at System.IO.Packaging.Package.GetPart(Uri partUri)
   at Program.<Main>$(String[] args) in /Program.cs:line 8

The Zip package tries to determine the content type here:

ContentType? contentType = _contentTypeHelper.GetContentType(validatedPartUri);

The ContentTypeHelper looks up the content type here:

internal ContentType? GetContentType(PackUriHelper.ValidatedPartUri partUri)
{
//Step 1: Check if there is an override entry present corresponding to the
//partUri provided. Override takes precedence over the default entries
if (_overrideDictionary != null)
{
if (_overrideDictionary.TryGetValue(partUri, out ContentType? val))
return val;
}
//Step 2: Check if there is a default entry corresponding to the
//extension of the partUri provided.
string extension = partUri.PartUriExtension;
if (_defaultDictionary.TryGetValue(extension, out ContentType? value))
return value;
//Step 3: If we did not find an entry in the override and the default
//dictionaries, this is an error condition
return null;
}

The lookup does not find a match because the part name "/part" and the content type override for "/PART" do not match.

However, the spec states that "The comparison shall be ASCII case-insensitive matching" (ECMA-376, 5th Edition 7.2.3.5).

Reproduction Steps

  1. Create a new console project:

    dotnet new console -n demo
    
  2. Overwrite Program.cs with the C# program above.

  3. Create a zip file called minimal.zip with an empty file called part and a file [Content_Types].xml with the xml content above.

  4. Run the program: dotnet run

Expected behavior

The program should finish without errors.

Actual behavior

$ dotnet run
Unhandled exception. System.InvalidOperationException: Specified part does not exist in the package.
   at System.IO.Packaging.Package.GetPart(Uri partUri)
   at Program.<Main>$(String[] args) in /Program.cs:line 8

Regression?

No response

Known Workarounds

No response

Configuration

.NET version: 9.0.103
OS: Linux 6.13.3
Architecture: x64

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions