Teckenuppsättningar och Servlets/JSP

När tecken som inte ingår i 7-bits ASCII (tex å, ä, ö, Å, Ä eller Ö) ska hanteras riskerar vi problem med teckenuppsättningarna. Det viktiga är att alla browsrar använder samma teckenuppsättning som servern. Den här sidan avhandlar bara kodning av tecken som sänds från browsern till servern, tex genom att användaren fyller i ett HTML-formulär.

På servern

Det är förmodligen ingen bra ide att anpassa servern eftersom vi inte kan lita på att alla browsrar beter sig lika. Väljer vi ändå att göra det finns det två olika sätt:
  1. Klassen javax.servlet.ServletRequest (som är superklass till javax.servlet.http.HttpServletRequest) innehåller metoden setCharacterEncoding(java.lang.String env) som kan användas för att ange vilket teckenset som ska användas när requestparametrar läses. Den metoden måste anropas innan något läses. Om setCharacterEncoding(java.lang.String env) inte anropas och HTTP-requestet inte innehåller någon uppgift om teckenset i headern Content-type ska servern, enligt Servlet-specifikationen 2.3 (051122:gäller även 2.4), anvvända ISO-8859-1 och getCharacterEncoding(java.lang.String env) ska returnera null.
  2. Förmodligen finns det något serverspecifikt sätt att ange att en annan teckenuppsättning än ISO-8859-1 (se ovan) ska vara default.

I browsern

Enligt HTML 4.0 kan attributet accept-charset användas för att tala om för browsern vilket teckenset som ska användas för att skicka tecken från ett visst formulär, se specifikationen. Om detta attribut saknas rekommenderar specifikationen att browsern använder samma teckenuppsättning som servern använde när den skickade HTML-sidan med formuläret, men det är inget krav.

Några mycket korta ord om teckenuppsättningar

ISO/IEC har tagit fram standarden 10646 som brukar kallas UCS (Universal Character Set) och ska innehålla alla världens tecken. UCS-2 har 16-bitars tecken och UCS-4 har 32-bitars. Unicode är en teckenuppsättning framtagen av en sammanslutning av olika företag. Från version 1.1 är Unicode kompatibel med ISO/IEC 10646. Exakt vad kompatibel betyder i det här fallet är inte solklart, men vad gäller svenska bokstäver (inklusive åäöÅÄÖ) är det ingen skillnad på Unicode och UCS-2. Unicode-tecken är 16 bitar långa.

US-ASCII eller (7-bits ASCII) är en "mycket gammal" teckenuppsättning som (hör och häpna) har 7-bitars tecken. Den innehåller bla alla svenska bokstäver utom åäöÅÄÖ. ISO 8859-1 (eller ISO Latin-1) är en teckenuppsättning som har 8-bitars tecken. Den innehåller även å, ä, ö, Å, Ä och Ö Alla teckenkoder upp till 127 är identiska med US-ASCII. De "första" 256 tecknen i Unicode/UCS-2 består av åtta nollor följt av teckenkoden i ISO 8859-1.

UTF-8 (UCS Transformation Format) är ingen teckenuppsättning utan en transformation av Unicode/UCS-2. Poängen med den är att kunna spara tecken från Unicode/UCS-2 utan att det ska finnas några byte som är otillåtna enligt reglerna för vedertagna filsystem. Alla tecken i US-ASCII har exakt samma kod i UTF-8, vilket däremot inte gäller för övriga tecken i ISO 8859-1. Om tex 'å' sparas med UTF-8 och läses med ISO 8859-1 blir resultatet 'Ã¥'. Om 'å' sparas med ISO 8859-1 och läses med UTF-8 blir resultatet en otillåten kod (vilket visas lite hur som helst). UTF-16 är en transformation från UCS-4 till UCS-2 som saknar betydelse för svenska tecken.

HTTP tillåter endast ett subsett av tecknen i US-ASCII att skickas i klartext. Övriga tecken ska skickas på formatet %HH där HH är tecknets kod i hexadecimal form. Tyvärr anger inte http vilken standard som ska användas för tecknets kod. Många browsrar använder för närvarnade (031027) ISO 8859-1 för de svenska bokstäverna.

Några ord om Tomcat 5.5

Om Tomcat används gäller inte det som står i stycket nedan. Tomcat följer servlet-specen (förstås, den är ju specen) och tolkar alltså post-parametrar enligt ISO-8859-1 default.

Några ord om Orion 2.0.2

Jag råkade använda Orion 2.0.2 när jag gjorde ovanstående utforskning, så jag skriver ned några speciella iaktagelser just för den servern. Om inte attributet default-charset används i taggen orion-web-app i orion-web.xml kommer orion att använda UTF-8 för att läsa request-parametrar oavsett om setCharacterEncoding("ISO-8859-1") anropats eller ej. Om däremot default-charset angetts till iso-8859-1 kommer orion att använda ISO 8859-1 om setCharacterEncoding inte anropats. Anropas setCharacterEncoding("ISO-8859-1") går orion över till UTF-8.

Orion förljer alltså inte servlet-specen.