Bramka MF / Kryptografia
Windows-1250, ISO-8859-2 i niedozwolone znaki w XML JPK
Objaw / komunikat błędu
Błąd parsowania XML: niezgodna deklaracja encoding (windows-1250, ISO-8859-2) albo niedozwolony znak sterujący (U+0000–U+0008, U+000B, U+000C, U+000E–U+001F).
Bramka czyta XML jako UTF-8. Deklaracja windows-1250 albo iso-8859-2 przy bajtach CP1250 psuje polskie znaki albo przerywa parser. Znaki sterujące wklejone z ERP są w XML 1.0 nielegalne nawet w UTF-8.
Przyczyna techniczna
- Prolog <?xml version="1.0" encoding="windows-1250"?> opisuje bajty, nie „polski język”. Jeśli plik jest już UTF-8, a prolog kłamie, parser MF interpretuje wielobajtowe ą, ę, ś jako pojedyncze bajty CP1250 i albo podstawia złe znaki, albo przerywa dokument.
- Odwrotnie: bajty CP1250 opisane jako UTF-8 urywają się na pierwszym znaku spoza ASCII, bo bajt 0xB9 („ą” w CP1250) nie jest poprawnym UTF-8.
- XML 1.0 zabrania większości znaków C0: U+0000–U+0008, U+000B, U+000C i U+000E–U+001F. Tabulator, LF i CR są dozwolone. Eksport z pól memo, ze starych bibliotek COM albo ze zrzutu bazy wstawia tam NULL i inne sterujące.
- Usunięcie znaku zmienia długość pliku, a więc Document/ContentLength i SHA-256 oryginału. Poprawka kodowania po policzeniu skrótu do InitUpload daje odrzucenie sesji, nie tylko błąd parsera.
Jak naprawić błąd krok po kroku
- 1
Wykryj deklarację w pierwszych bajtach
Prolog jest na początku pliku. Odczytaj okno, nie cały dokument, i sprawdź, czy encoding to UTF-8, czy windows-1250 / iso-8859-2.
- 2
Dekoduj źródło właściwą stroną kodową i zapisz UTF-8
CP1250 i ISO-8859-2 dekoduj do znaków, a wynik zapisz jako UTF-8. Prolog ma wtedy mówić UTF-8 albo zostać pominięty zgodnie z zasadą domyślnego UTF-8.
- 3
Wytnij niedozwolone znaki sterujące przy zapisie
Usuń U+0000–U+0008, U+000B, U+000C i U+000E–U+001F. Zostaw tabulator, LF i CR. Nie zamieniaj ich na spację, jeśli zmiana treści księgowej nie jest potrzebna — po prostu nie mogą wejść do XML 1.0.
- 4
Po konwersji policz rozmiar i skrót od nowa
ContentLength i HashValue w InitUpload dotyczą bajtów, które naprawdę szyfrujesz. Skrót ze starego CP1250 nie pasuje do nowego UTF-8.
Jak rozwiązuje to architektura SecureJPK
Przygotowanie pliku dekoduje deklarację windows-1250 albo iso-8859-2 przy odczycie strumienia i zapisuje wynik jako UTF-8 w OPFS. W trakcie zapisu wycinane są znaki sterujące zabronione w XML 1.0, bez ładowania całego drzewa DOM. Dalsze szyfrowanie liczy SHA-256 już na tych bajtach, więc InitUpload opisuje plik, który bramka dostanie po rozszyfrowaniu, a nie kopię sprzed konwersji.
Najczęstsze pytania (FAQ)
- Czy samą zmianę prologu na UTF-8 wystarczy?
- Tylko gdy bajty już są UTF-8, a prolog kłamie. Gdy bajty są CP1250, trzeba je przekonwertować. Sam napis encoding="UTF-8" nie zmienia bajtów ą i ź.
- Czy znak nowej linii trzeba usuwać?
- Nie. LF (U+000A), CR (U+000D) i tabulator (U+0009) są w XML 1.0 dozwolone. Problemem są pozostałe znaki sterujące, zwłaszcza U+0000.
- Czy konwersja psuje podpis kwalifikowany na XML?
- Tak, jeśli podpisany był już sam JPK. W tym modelu podpisuje się InitUpload, który wskazuje skrót oryginału. Dlatego konwersja musi zakończyć się przed liczeniem SHA-256 i przed podpisem InitUpload.