Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions