– Hva er greia med alle de likhetstegnene, egentlig
Utvikler Lars Ingebrigtsen har forklaringen!
Av en eller annen grunn har folk postet massevis med utdrag av gamle eposter på Twitter de siste dagene. Spørsmålet alle har stilt seg er selvsagt: Hva er greia med alle de likhetstegnene!?
Og dette er noe jeg er en slags ekspert på. Altså, i min tid har jeg skrevet både epostlesere (Gnus, for de som husker gamle dager) og mye kode for å parse epost (f eks Gmane, for de som husker litt nyere dager).
(Det er kanskje viktig å presisere her at jeg er derimot ikke er ekspert på øyer i Karibia.)
Rikingkode
Jeg har sett folk som påstår (med stor sikkerhet) at dette er noen slags milliardærkode, eller at dette er noe som har oppstått mens man har gjort optisk scanning (OCR) av dokumentene. Men det er ingen av delene — problemet er at de som har gjort konveretingen av epostene er idioter.
Jeg mener: Hardt arbeidende, dyktige konsulenter som sikkert bare har hatt litt for lite tid.
Nå hører jeg koret sier: "Konvertering? Man konvererer da ikke epost! Epost er da bare tekst!" Vel, det var sant i veldig gamle dager, men man må nesten tilbake til 80-taller for at det skal være sant. På 90-tallet fant man opp ting som "lange linjer" og "röcktödlar" (eller norske tegn, for den saks skyld), så da måtte man begynne å "kode" epostene før man sender dem, for eposttjenere liker ikke slikt tull.
Det vi ser i disse utdragene er fra en kodemetode som heter "quoted printable", eller som vi brukte si da dette ble innført: "Quoted unreadable". Denne kodemetoden gjør to ting: 1) Den lar oss ha lange linjer i epost, og 2) den lar oss bruke ikke-ASCII-tegn i epost. De likhetstegnene vi ser i utdragragene kommer (mest sannsynlig) av samspill mellom feilbehandling av begge disse to tingene.
Eksemplene
Så la oss ta det den første eksempellinja som vi kan se der i starten av artikkelen: Den som skrev den, tastet inn noe slikt i sin epostleser:
we talked about designing a pig with different non- cloven hoofs in order to make kosher bacon
Vi kan se at dette er en ganske lang linje. Eposttjenere liker ikke slikt, så epostleseren vil brekke dette om til to linjer. Resultatet ser slik ut:
we talked about designing a pig with different non- = cloven hoofs in order to make kosher bacon
Ser dere? Der er det et likhetstegn! Ja, man bruker et liketstegn på slutten av linja for å si "dette skal egentlig være én linje, men jeg har brukket den om til to linjer sånn at eposttjeneren ikke skal bli sint på meg".
Men her må jeg bli litt teknisk, dessverre, siden den formelle definisjonen er viktig for å skjønne hva som har gått galt i detalj. Dersom du ikke er interessert i detaljene, så kan du bare bite deg fast i uttrykket "quoted printable". Neste gang du er i et selskap og noen begynner snakke om disse tingene, så kan du bare bruke uttrykket, hoverende, og så vinne diskusjonen.
Men når man sender epost, så bruker man ikke bare en normal "slutt-på-linje"-markør (eller "\n"), men CRLF, "carriage return and line feed".
Eller:
=CRLF
Dvs, tre tegn totalt, så det vil si at linja vi koder vil se slik ut:
... non- =CRLF cloven hoofs...
Når man viser dette fram i mottakerens epostleser, så vil den fjerne disse tre tegnene igjen, og vi sitter igjen med:
... non- cloven hoofs...
Så hva er det som har skjedd i den konverteringen vi ser utdrag av på Twitter? Vel, de som lagret disse epostene har lagret dem uten CRLF (som ofte kalles "Windows"-linje-ending, men er en del av SMTP-standarden), og har lagret dem på Unix-måten, med "newline" isteden. Dette er helt normalt, men du ender opp med ett tegn mindre:
... non- =NL cloven hoofs...
Dersom du har skrevet en dum algoritme som er "finn likhetstegn på slutten av linja, og slett de to neste tegnene (samt likhethetstegnet)", så ville du ende opp med:
... non- loven hoofs...
Dvs, du mister "c"-en. Dette er nesten hva som har hendt her, men hvorfor sitter du igjen med likhetstegnet?
Stackoverflow-forklaring
Denne StackOverflow-artikkelen fra 14 år siden forklarer fenomenet, på en måte:
Obviously the client notices that = is not followed by a proper CR LF sequence, so it assumes that it is not a soft line break, but a character encoded in two hex digits, therefore it reads the next two bytes. It should notice that the next two bytes are not valid hex digits, so its behavior is wrong too, but we have to admit that at that point it does not have a chance to display something useful. They opted for the garbage in, garbage out approach.
Det vil si, det at vi ikke har CRLF gjør at algoritmen ikke gjenkjenner dette som "lang linje"-koding i det hele tatt, men faller igjennom og tar fatt på neste steg i quoted-printable-dekoding (som vi ser et eksempel på senere i dette eksemplet):
=C2 please note
Dersom likhetstegnet ikke er på slutten av linja, så brukes det til noe annet: Nemlig å kode "rare tegn", som f eks i "röcktödlar". =C2 er 194, som er første byte i en UTF-8-sekvens. De påfølgende tegnene var sikkert =A0, for =C2=A0 er NON BREAKABLE SPACE, som folk ofte bruker for å rykke inn tekst. Og dette er tilfelle her: "please note" er indentert, og du kan finne =A0 i mange andre eposter.
Så min erfaring sier meg at algoritmen som skulle konvertere disse tingene var uforberedt på at "lang linje"-biten feiler, så den har tolket "=\nc" som koding av ikke-ASCII-tegn. Den fjernet disse to tegnene (dermed forsvant c-en i eksemplet). Men når den prøvde å tolke "\nc" som hex-tegn, så feiler dette selvsagt, og den hadde ikke noe å bytte ut likhetstegnet med — så den lot det bare stå i fred. Dermed ender vi opp med resultatet vi ser i epostene:
... non- =loven hoofs...
(Jeg har dog ingen god forklaring på hvorfor noen av disse =C2-ene har overlevd og andre ikke. Kanskje en off-by-one-feil som fører til at den hopper over annenhvert kodet tegn?)
Jeg tror dette er måten disse epostene har blitt feilkontervert på. Så 1) "det er teknisk", og 2) "det er en kombinasjon av to ting som har feilet samtidig: Feil behandling av linjeendinger, og samtidig feil behandling av ikke-ASCII-tegn", og 3) "de som prosesserte disse epostene var ikke så veldig flinke".
Det siste punktet vil kanskje ikke overraske så veldig mange folk etterhvert.