[16.0][FIX] account_statement_import_ofx: handle mislabeled OFX charsets - #968
Open
renatonlima wants to merge 3 commits into
Open
[16.0][FIX] account_statement_import_ofx: handle mislabeled OFX charsets#968renatonlima wants to merge 3 commits into
renatonlima wants to merge 3 commits into
Conversation
Contributor
|
Hi @alexis-via, |
renatonlima
force-pushed
the
16.0-account_statement_import_ofx-decode
branch
from
June 19, 2026 01:24
acbaa6b to
c7b5262
Compare
renatonlima
marked this pull request as draft
June 19, 2026 01:28
Member
Author
|
There's an error in another module; I believe the cause is the version of the Python library ofxtools. It's likely the newest version of this library isn't compatible. I've changed the status of this PR to draft while I investigate the error in CI. |
ofxparse trusts the charset declared in the OFX SGML header (e.g. CHARSET:1252) and decodes the body with a strict cp1252 codec. Some banks emit files whose header declares one charset while the body is actually encoded differently (UTF-8 is common). Decoding then raises UnicodeDecodeError on bytes undefined in cp1252 (e.g. 0x81), and since _check_ofx swallows the exception the import fails with the misleading "This bank statement file format is not supported" message. Decode the raw bytes ourselves instead: UTF-8 first (it is self-validating, so it rarely matches non-UTF-8 data by accident), then the charset declared in the header, and finally latin-1, which maps every byte value and never raises. The decoded text is re-encoded to UTF-8 and the SGML ENCODING header is normalized to UTF-8, so ofxparse decodes the body consistently regardless of the original (possibly wrong) declaration. Passing bytes (not a text stream) also avoids ofxparse re-running its own cp1252 detection on the data. This fixes imports for files produced by Brazilian banks and works across locales (Western Europe, Latin America, Asia) without corrupting characters outside latin-1 (e.g. the Euro sign or CJK text). Add tests covering UTF-8 mislabeled as cp1252, genuine cp1252, UTF-8 with characters outside latin-1 (Euro sign, em dash) and CJK content.
…e version of the python ofxtools library.
…sts/test_import_bank_statement.py:40:58: E231 missing whitespace after ':'
renatonlima
force-pushed
the
16.0-account_statement_import_ofx-decode
branch
from
June 19, 2026 18:34
52631d5 to
6a90f7b
Compare
renatonlima
marked this pull request as ready for review
June 19, 2026 21:35
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.
Summary
Fix OFX imports failing with a misleading "file format is not supported" error when the file's declared charset does not match its real encoding.
Problem
ofxparsereads the charset declared in the OFX SGML header and decodes the body with a strict cp1252 codec. Several banks emit OFX files whose header declaresCHARSET:1252while the body is actually UTF-8. Decoding then fails on bytes that are undefined in cp1252 (e.g.0x81):output
_check_ofxcatches this exception and returnsFalse, so the user only sees the generic dialog:In the affected file the accented name
ROMÁRIOis stored in UTF-8 (Á=0xC3 0x81), so the lone0x81byte breaks the cp1252 decoder even though the header claimsCHARSET:1252.Solution
Decode the raw OFX bytes ourselves before handing them to
ofxparse:UTF-8 first — it is self-validating, so it rarely matches non-UTF-8 data by accident.
Then the charset declared in the header (cp1252 / iso-8859-1).
Finally latin-1, which maps every byte value and never raises. The decoded text is re-encoded to UTF-8 and the SGML
ENCODINGheader is normalized toUTF-8, soofxparsedecodes the body consistently regardless of the original (possibly wrong) declaration. Passing bytes rather than a text stream also preventsofxparsefrom re-running its own cp1252 detection on the content.This works across locales — Western Europe, Latin America and Asia — without corrupting characters outside latin-1 (the previous behaviour silently turned a UTF-8
€or CJK text into mojibake).Tests
Added regression tests covering four encoding scenarios, each asserting that the special characters survive the round-trip:
test_ofx_encoding_latinCHARSET:1252(the reported bug; contains byte0x81)test_ofx_encoding_cp1252test_ofx_encoding_utf8_eurotest_ofx_encoding_asian