Open the document by what it is called when its bytes only say text - #611
Merged
Conversation
Merged
odrcore builds its open candidates from the content alone - `list_file_types` is `magic::file_type`, and the name is never consulted. A document whose signature does not sit at the front of the file therefore never opens as itself. The case that turned this up is a pdf saved straight out of a browser, with the http response that delivered it still attached, so `%PDF-1.4` starts at byte 178. What the user got depended on the file. `odr-public`-shaped ones read as text with a charset the core could name, and the reader was shown pages of pdf source with a bar offering to open it elsewhere. The file in #552 has binary enough content that no charset could be named, so the guard in `host` refused it and the app reported an unsupported format - for a pdf the core parses perfectly well once told what it is. Neither knob in `DecodePreference` fixes this on its own. `fileTypePriority` only stable-sorts the candidates detection already found, so it is inert when detection found the wrong one or none. `asFileType` replaces detection outright and has no fallback, which would hand a file misnamed by its extension to a parser that cannot read it. So it is a second attempt rather than the first: `CoreLoader.openFile` opens as detection reads the bytes, and only where that reading is the residual answer does it open again as the type the name states. Two things keep it narrow. The name has to be one the core files as a `DOCUMENT` - csv and plain text are both `text` by category, so whether comma separated values are a table or prose stays the core's question, which #576 and 6.8.0 tuned deliberately. And the name is taken from `IdentifiedFile.filename`, not from its `mimeType`: `FileIdentifier` takes that from `Odr.mimetype` wherever it answered, so feeding it back would only repeat the reading this is here to back up. `CoreTest` pins both halves against a fixture it builds at run time from `dummy.pdf`, so no binary asset joins the repo: without a declared type the served html carries the http preamble as text, with one it does not, and an odt declared a pdf still opens as an odt. Checked on API 31 (full suite, 84 tests) and API 36, plus a sweep of the corpus' txt and csv files, which are what this could have disturbed and did not - the 5000 row csv still comes out a table. The private pdf #552 names renders as the document it is. Closes #552
andiwand
force-pushed
the
open-what-the-file-is-called
branch
from
August 21, 2026 09:00
4ddcb84 to
8524ed3
Compare
andiwand
enabled auto-merge (squash)
August 21, 2026 09:10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
odrcore builds its open candidates from the content alone -
list_file_typesismagic::file_type, and the name is never consulted. A document whose signaturedoes not sit at the front of the file therefore never opens as itself. The case
that turned this up is a pdf saved straight out of a browser, with the http
response that delivered it still attached, so
%PDF-1.4starts at byte 178.What the user got depended on the file.
odr-public-shaped ones read as textwith a charset the core could name, and the reader was shown pages of pdf source
with a bar offering to open it elsewhere. The file in #552 has binary enough
content that no charset could be named, so the guard in
hostrefused it and theapp reported an unsupported format - for a pdf the core parses perfectly well
once told what it is.
Neither knob in
DecodePreferencefixes this on its own.fileTypePriorityonlystable-sorts the candidates detection already found, so it is inert when
detection found the wrong one or none.
asFileTypereplaces detection outrightand has no fallback, which would hand a file misnamed by its extension to a
parser that cannot read it. So it is a second attempt rather than the first:
CoreLoader.openFileopens as detection reads the bytes, and only where thatreading is the residual answer does it open again as the type the name states.
Two things keep it narrow. The name has to be one the core files as a
DOCUMENTtextby category, so whether comma separatedvalues are a table or prose stays the core's question, which Take odrcore 6.4.0, and let it render csv #576 and 6.8.0 tuned
deliberately. And the name is taken from
IdentifiedFile.filename, not from itsmimeType:FileIdentifiertakes that fromOdr.mimetypewherever it answered,so feeding it back would only repeat the reading this is here to back up.
CoreTestpins both halves against a fixture it builds at run time fromdummy.pdf, so no binary asset joins the repo: without a declared type theserved html carries the http preamble as text, with one it does not, and an odt
declared a pdf still opens as an odt.
Checked on API 31 (full suite, 84 tests) and API 36, plus a sweep of the corpus'
txt and csv files, which are what this could have disturbed and did not - the
5000 row csv still comes out a table. The private pdf #552 names renders as the
document it is.
Closes #552
🤖 Generated with Claude Code