SecureJPK
Zaloguj się

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. 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. 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. 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. 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.