A magyar karakterek kezelése mindig is egy homályos területnek számított - köszönhetően a nagyon sokféle kódlapnak, a programozói figyelmetlenségekből vagy egyszerűen tudatlanságból származó tévedéseknek és keveredéseknek, és így tovább.

Némileg érhetőbbé szeretném tenni ezzel a kis fejtágítóval a magyar karakterek kezelését mindenki számára webes környezetben. A téma maga ugyan nem túlzottan bonyolult, azért feltételezek némi előismeretet az alapokról - nevezetesen a PHP-ről és a HTTP szabványról.

A probléma

Nyelvünkkel annyi a gond az informatika terén, hogy gyarló módon olyan karakterekre van mersze támaszkodni, amelyeket az angolszász területeken élők alapból misztikumnak tekintenek. Ezzel a gondunkkal nem vagyunk egyedül, Európa és a világ tele van speciális karaktereket is használó nyelvekkel. Az informatikában ugye sajátosan először minden érdekesebb dolog angol nyelven "történik", ezért a szoftverekre hagyományosan mindig utólag húzták rá - ha megtették - a "nem angol" karakterkészlet karaktereinek megjelenítését.

Kezdetben (Ádám és Éva után közvetlenül) volt az ASCII kódlap, amely 256 féle karaktert tartalmazott, ezek között egyébként egész sok mindenféle ékezetest is. A magyar ékezeteseket persze már nem - illetve részben igen, de azt is csak azért, mert történetesen pár más nyelvben is megvannak egyes általunk használt karakterek. Valahol itt kezdődött például a "kalapos ő" és a "kalapos ű" karrierje - ugyanis amikor nem volt kéznél rendes megfelelő karakter, akkor ezeket használta mindenki helyettesítésre.

A kódlapról magáról egy kis kitérő: azt ugye tudjuk, hogy a mindenféle háttértárakon leginkább byteokat szoktunk tárolni - vagyishát fileokat, de azok byteokból állnak össze. Egy byte - mint tudjuk - 0 és 255 között vehet fel értékeket, és a letárolt byteokat a számítógép valahogyan értelmezi.

Ha futtatni próbálunk mondjuk egy filet (legtöbbször mondjuk az EXE kiterjesztésűeket az MS alapú oprendszereken), akkor gépünk a tárolt byteokat programkódként próbálja értelmezni, ha viszont valamilyen módon megjelenítjük/kiíratjuk azt, akkor minden egyes byte-értékhez az ASCII kódtábla alapján kirak a képernyőre egy karaktert (más kérdés, hogy egy EXE file esetén ez túl sok értelmet így nem hordoz). Tehát egy file byteokból áll - mondjuk az, hogy "szövegfile" igaziból csak egy rövidítés, hiszen ha pontosabbak akarnánk lenni, akkor azt mondanánk rá, hogy "szövegesnek szánt tartalmú, amúgy simán csak byteokból összeálló file".

Amikor ez az egész informatika-dolog kezdett körvonalazódni - mondjuk úgy a nyolcvanas évek végén - már látszott, hogy minden nyelvhez kitalált az azt használó náció vagy egy-két velük foglalkozó cég egy-két kódlapot (lásd pl. a szépemlékű PC CWI, vagy az IBM PC 852 kis honunkban), amellyel kiváltani vélte a DOS-ban eredetileg használatost - így lehetővé tették a helyes ékezetek megjelenítését azokban a szoftverekben, amelyek azt a kódlapot használták.

A nagy megoldás ezekben mindössze annyi volt, hogy ahol az ASCII kódlapban egy haszontalannak ítélt karaktert találtak a készítők, annak helyén másféle karaktert jelenített meg a szoftver. A hátrány: egy CWI kódlapot használó szoftverben megírt szövegfile helyes ékezetekkel csak egy másik CWI kódlapot használó szoftverben olvasható. A kódlap használata nélkül (mondjuk simán DOS-ban kiírva a filet) jó esetben egy hasonló dolgot olvashatunk, mint amilyen az eredeti volt (rendes ő betű helyett kalaposat), rossz esetben (egy extrémebb kódlapnál) pedig vegyes grafikus karaktereket (a korábban használatos kódlapokról némi információ innen kihámozható: http://lex.jak.ppke.hu/~pasztor/ekezet.html ).

... és hát nem meglepetés: gyakorlatilag ugyanez a helyzet azóta is az összes szöveges tartalommal számítógépes környezetben - vagy van valaki, ami még nem látott négyzeteket vagy kérdőjeleket ékezetek helyett, "esetleg" kalapos ő betűket normális helyett - weben, szórólapon, újságban, bárhol?

Ehhez a néhány kezdeti kódlaphoz lassan hozzácsapódott a Microsoft által célszerűnek talált kódlapkezelés, amely értelemszerűen teljesen eltért az akkor már ismertektől (ennek köszönhetjük a Windows 1250 néven ismert kódlapot), illetve párhuzamosan azért fejlődgettek mindenféle "rendes" (nem cégtulajdonban lévő) szabványok is - így alakult ki például az ISO-8859-2, ami végre rendesen törődött a Közép-Európában használatos nyelvekkel. (Ha már szó esett róla, jó tudni: az ISO-8859 egy tíz kódlapot tartalmazó család: Észak-, Dél-, Kelet- és Nyugat-Európa, cirill, arab, görög, héber, török és Nordic - ezen családtagokat jelzik aztán a kötőjeles számozással, számunkra a -2 az érdekes, amely Latin2 néven is ismeretes).

A nagy kérdés persze, hogy miért ez az egész kavarás, mikor elég lenne egyetlen nagy kódlap, amiben minden nyelv minden karakterét el lehetne helyezni. Eddig szerencsére eljutottak Más Nagy Gondolkodók is, és megalkották az Unicode szabványt.

Amit érdemes róla tudni, hogy alapvetően eltér a DOS-os "egy-byte = egy-karakter" rendszertől: egy karakter ugyanis két byteon kerül ábrázolásra (aztán ezt a két byteot megint más kérdés, hogy pontosan hogyan tároljuk le). Ez a kétbyteos dolog azért olyan nagyon jó, mert két byteon már 65536 féle karakter fér el (2 tizenhatodik hatványa), így jöhet egész Japán és Kína az ott használatos néhány ezer/tízezer írásjellel is, bőven van helyük.

(Némi plusz információ ezzel kapcsolatosan: Unicode Consortium, uicode_utf)

Ennek a mindent megváltó Unicode-nak mindössze annyi a hátránya, hogy míg az ISO-8859 és hasonszőrű szabványok már egész jól beépültek a szoftverekbe, addig az Unicode-ot pont a nagysága miatt nem képes minden szoftver jól kezelni. Ami késik, nem múlik, olyan húsz-harminc éven belül - a nagyrészt élő szövet alapú processzorok és holografikus tárolóeszközök, implant technológiák és vízzel működő autók korában - várhatóan talán ide is eljut majd az informatika :)

Mi viszont foglalkozzunk már most is garantáltan mindenhol életképes megoldásokkal: lássuk, mit kezd egy magyar fejlesztő a neten az ékezetekkel.

Az oldalak megjelenítése

Alapszabály: az oldalakat a böngészők mindig megjelenítik valahogyan.

Ez eddig nem nagy meglepetés, nap mint nap szembesül vele az ember. A nagy kérdés inkább az, hogy hogyan is történik a megjelenítés.

Ennek megértéséhez jó, ha tudjuk: a webszerver és a böngészők kommunikációjakor először úgynevezett HTTP headerek közlekednek. Ezekben a headerekben írja meg a böngésző a szerver számára, hogy milyen cookie-kat tart nyilván az adott domain számára, hogy mely oldalt szeretné megnyitni, hogy milyen tartalmakat képes megjeleníteni. A szerverek viszontválaszukban elmondják, hogy milyen típusú tartalmat küldenek, az milyen hosszú - és sok minden más mellett valószínűleg még azt is, hogy milyen kódlap szerint kell az épp küldésre kerülő tartalmat értelmezni.

Két megjegyzés:
  1. ezektől persze jóval több header közlekedhet, de az itt említettek tipikusak
  2. valamint visszafelé nyilván csak akkor jön kódlapjelzés, ha szöveges jellegű, pl. HTML tartalom érkezik

Nos, amennyiben a böngésző egy oldal letöltésekor a szervertől valóban kap egy olyan header-t, amelyben jelzik számára a tartalom kódlapját, akkor ezt veszi alapul, a kapott tartalmat azon kódlap szerint mutatja meg. Ha ilyet nem kap, akkor figyelembe veheti még a HTML oldalban META tagként megadott hasonló célú jelzést is, majd ha minden kötél szakad, akkor beállítástól függően vagy automatikusan megpróbálhatja megállapítani, hogy milyen kódlapot kell használnia, vagy a beállított kötelezően használandó kódlappal dolgozik.

A legbiztosabb megoldás kétségkívül az, ha egy header elküldésével jól megmondjuk, milyen kódlappal készültek tartalmaink:

  header("Content-Type: text/html; charset=iso-8859-2");  

Végre eljutottunk hát első programsorunkhoz. A header() függvénnyel ugyebár minden más tartalom kiírása előtt kell dolgoznunk, hiszen a HTTP headereknek még a HTML forrás előtt ki kell menniük - ezért is hívják headernek, nem lehet belekeverni a "tartalomba". Emiatt célszerű vagy minden HTML-t eredményező PHP kódunk legelejére beszúrni ezt a sort, vagy inkább egy minden oldalról amúgyis behívott includeban elhelyezni - persze ekkor nem tehetjük meg, hogy az include-ot már HTML kiírás után hívjuk be (szépen felépített alkalmazásnál ilyet úgysem nagyon csinálunk).

Ismét egy megjegyzés: ha valaki jobban szeretné átlátni ezt a headeres témakört, a legjobban teszi, ha szétnéz, hogy mi is történik a böngészők és a szerverek között (ajánlott eszközök, oldalak a cikk végén).

A sorunkban jelzett kódlap a magyar nyelv számára (is) alakított ISO-8895-2 - azért ezt célszerű használni, mivel ezt nagyjából a legtöbb operációs rendszer alatt a legtöbb szoftverrel egész jól tudjuk kezelni.

A header() mellett lehetséges másik, már említett megoldás, hogy a HTML HEAD részében egy META tagben definiáljuk a kódlapot:

  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset='iso-8859-2'">  

Ezzel megvan az a probléma, hogy nem egyértelmű, hogy minden böngésző figyelembe veszi-e ezt, illetve nem tartja-e majd fontosabbnak saját beállításait, Auto-detectjét vagy esetleg a szerver által tudtunk nélkül kiküldött, talán másféle kódlapjelzést tartalmazó headert (igaziból általában sem egyértelmű a szerver felől érkező kódlapinformációk és a böngésző beállításainak "versenye", előfordulhat, hogy egyes böngészők fontosabbnak tartják saját beállításaikat, mint amit az oldal írója jelez - ez mondjuk legalábbis érdekes hozzáállás).

Ha már szóbakerült: mindig legyünk tisztában azzal, mi jön ki a szerverünkből. Az Apache-ban például beállítható a konfigurációban az

    AddDefaultCharset iso-8859-2  

sorral, hogy küldjön ki minden oldal előtt megfelelő kódlapheadert - azonban ha ezt valamilyen installer vagy bármi más beállította nekünk előzetesen mondjuk iso-8859-1-re, mi pedig nem foglalkoztunk a kérdéssel, akkor vidám délutánjaink fognak elmenni arra, hogy végigszenvedjük a kódlapozás témakörét.

Honnan tudjuk, hogy baj van?

Egész egyszerű kideríteni, ha nem figyeltünk eléggé eddig a kódlapokra: csak nézzük meg, valójában milyen értékek érkeznek egy form felől a PHP-be, próbáljuk ki a következő kódot:

  test.php     <HTML>     <HEAD>       <TITLE>Proba</TITLE>     </HEAD>     <BODY>     <PRE>     <?php       if (isset($_POST['szoveg']))         echo htmlspecialchars($_POST['szoveg']);     ?>     </PRE>     <FORM ACTION='test.php'>       <INPUT TYPE=TEXT NAME='szoveg' VALUE=''>       <INPUT TYPE=SUBMIT>     </FORM>     </BODY>     </HTML>  

Ha kipróbáljuk a példaprogramot, a böngészőben (jó) esély van arra, hogy kis/nagy hosszú ő és ű karaktereket beírva, majd a formot elküldve megkapjuk a

  &#337; &#369; &#336; &#368;  

HTML entitások egyikét. Ha nem így kapjuk, akkor próbáljuk ki mondjuk ISO-8859-1 kódlapra átállított böngészővel - ugyanis számítanunk kell arra, hogy bőségesen látogatják oldalainkat ilyen böngészőbeállítással is, köszönhetően a sok angol nyelvű operációs rendszernek és a külföldi látogatóknak. (Az oprendszerek alapbeállításait a böngészők is örökölhetik, ezért számít a rendszer nyelve).

Két jelentős kérdés merülhet fel ezekkel a megjelenő hieroglifákkal kapcsolatosan:

  1. mik ezek?
  2. és mégis hogy kerülnek ide?
Hm, lássuk:
  1. Az elsőre egész könnyű a válasz: ezek HTML entitásként kódolt Unicode karakterek. Az &aacute;, &oacute; entitások ismerősek lehetnek: őket általában egy-egy karakter (vagy akár jel) leírására használjuk.

    A &#xxx; formát használva viszont nem egyes előredefiniált, névvel ellátott karakterek/jelek jelennek meg, hanem az Unicode szerinti xxx kódnak megfelelő karakter - így például &#65; a nagy A betűt jelzi, &#66; a nagy B-t, és így tovább (lásd HTML Document Representation).

    Az ő, ű ékezetes karaktereink a fent látható kódokon kaptak helyet Unicode alatt (lásd az Unicode kódtábla ezen részét itt: http://www.unicode.org/charts/PDF/U0100.pdf), így jöttek ki ezek a karakterjelzetek.

  2. Nos, a "hogy kerül ide" már egy érdekesebb kérdés - a megértéshez a böngésző viselkedését kell megismernünk némileg alaposabban.

    1. A böngésző a megjelenített HTML oldalunkat látva, kódlap Auto detectre állítva jó eséllyel dönthet úgy önállóan, hogy ez egy ISO-8859-1 (nem 8859-2!) kódolású oldal: még akkor is mondhatja ezt, ha esetleg pár ékezet ugyan szerepel benne (mondjuk á, é), de ezek még esetleg beleférnek a 8859-1-es kódlapba. Ugyanígy ha ISO-8859-1 kódolás van a böngészőben beállítva, ha akarja, még META tagünket illetve a kiküldött header-t is figyelmen kívül hagyhatja (ez utóbbi már speciel ordító hiba, emlékeim szerint az Opera követett el ilyen alatomosságot).

      A folyamatban pedig valami ilyesmi zajlik...

    2. Ha beírjuk saját kedvenc ő, ű karaktereinket a formba, ezek már nem férnek bele a megjelenítésre használt ISO-8859-1-be, hiszen abban nincsenek ilyen karakterek definiálva.

    3. A böngésző szeretné megoldani ezt a helyzetet (nincs vele egyedül). Adott egy kódlap, ami "kijött" valahogy (előzetes jelzések vagy a tartalom elemzése alapján), és adott az egységsugarú felhasználó által megadott szöveg, ami nem fér bele a használt kódlapba.

    4. A böngésző a következőképp morfondíroz: "rendes 8859-1 kódlapbéli karakterként nem tudom átvinni a szervernek a megadott karaktert, mert a megadott karakter nem része annak a kódlapnak. El mégse dobhatom, mert akkor a fejlesztőim kapják a bugreportokat, az megint nem jó. Na nézzünk szét a spájzban... aszonnya van flash pluginünk, nyolcvankét elmentett jelszó, tizenhat doboz cookie, a cache majdnem tele (hm, kéne már itt takarítani...) jéééé! Milyen édes kis üveg, aszongya 'Unicode'..."

      Böngészőnk tehát leporolja Unicode kódolását, amiben minden karakter benne van (ez akár reklámszlogen is lehetne), és megkeresi az Unicode kódlapban azokat a problémákat okozó karaktereket. Ott meg is van a helyük, azonban mivel az Unicodeban két byteon van tárolva minden karakter, ezért egy bevett, ismert, és ISO-8859-1 kódolás alatt is használható módon próbálja ábrázolni ezt a két byteos karaktert - így jön a HTML entitásszerű forma, hiszen "igazi" két byteon nem teheti: azt nem teszi lehetővé a HTML szabvány ISO-8859-1 kódlap alatt.

Megjegyzés: érdekes dolgoknak lehetünk tanúi, ha az oldalt eleve Unicode alatt írjuk: normális (nem Unicode) szövegként megtekintve ugyanis úgy néz ki, mintha minden karakter után szóköz jönne (az egyébként egy nulla tartalmú byte), és az ábrázolásból sajátosságaiból adódó egyéb finomságok is láthatók. Egy Unicode-ban írott oldalra példa itt: Unicode Plane 1 Example Using UTF-16

Az oldal megtekintése során nagy meglepetés nem érhet, próbáljuk csak meg lementeni és úgy megnézni ezt a HTML-t :)

A folyamatban tehát ott a bökkenő, hogy ha nem adjuk meg az oldalunk kódolását, akkor a kapott eredmény olyasmi is lehet, amit mi nem akarunk.

Mit tegyünk, hogy elfelejthessük ezt az egészet?

Semmiképp se próbáljuk elfelejteni: ehelyett gondoljuk végig a dolgot, nézzünk utána, (ha mindezek alapján nem lenne világos), és törődjünk vele.

A legfontosabb kezdő lépés: nézzünk végre szét, hogy mivel és hogyan is dolgozunk. Magyarországon magyar nyelvű oldalakat használva akkor járunk el helyesen, ha webes alkalmazásunk és szerverünk minden összetevője összehangoltan egy kódlapot használ - célszerűen az ISO-8859-2-t.

Apache vagy más webszerver
Ha csak magyar nyelvű oldalakat szolgálunk ki, az ISO-8859-2 kódolást a korábban leírt Apache konfigurációs sorral minden oldal előtt kiküldött headerben jelezhetjük. Ha esetleg más kódlapot használó oldalak is előfordulnak szerverünkön, akkor is célszerű lehet ezt az "alapértelmezést" megtartani, majd azon oldalak számára esetleg külön Apache .htaccess file vagy PHP header() függvény segítségével megfelelő másik kódlapot is jelezni. Persze választhatjuk azt is, hogy minden oldal előtt mondjuk PHP jelezze a használt kódlapot, ezesetben nem kell foglalkoznunk Apache konfigurálással.
PHP
PHP-ből az említett header() sorral tudunk segíteni magunkon. Így ha korábban esetleg az Apache ki is küldött egy nem megfelelő header-t, ahelyett a miénk lép majd érvénybe (több ugyanolyan célú headerből az utolsó lesz az érvényes).
HTML
Ha statikus HTML oldalakról van szó (vagyis PHP-ből nem küldhetünk előttük headert), és ha nem férünk hozzá az Apache konfigurációjához, akkor marad a META tag megadása. Ezzel akkor járhatunk rosszul, ha az Apache nem megfelelő headert küldött ki, ekkor ne is számítsunk sok jóra: inkább beszéljük meg a dolgot a rendszergazdával.
Adatbáziskezelők: MySQL, PostgreSQL, Oracle vagy más
Ha használunk adatbázist, akkor jól tesszük, ha az adatbáziskezelőt is felvilágosítjuk arról, hogy épp milyen kódlap alól származnak az adatbázisba tömött adataink. Ezzel nemcsak azt segítjük elő, hogy az adatbázistartalomban bárhol navigálva helyesen láthatjuk a tartalmakat, hanem elejét vehetjük jónéhány konverziós problémának is.

MySQL

MySQL alatt célszerű a megfelelő magyar karakterkészletet a my.cnf állományban állíthatjuk át (Linux alatt általában /etc/mysql/my.cnf, Windows alatt pl. c:\windows\my.cnf):

  default-character-set=hungarian   character-sets-dir=/usr/share/mysql/charsets   character-sets-dir=c:/mysql/share/charsets/   default-character-set=hungarian  

Egyéb információk itt: http://www.mysql.com/doc/en/Character_sets.html

PostgreSQL

PostgreSQL-nél egy új adatbázis létrehozásánál tudjuk legegyszerűbben megadni kódlapunkat:

  initdb --locale=hu_HU.ISO8859-2  

(lásd http://www.postgresql.org/docs/view.php?version=7.3&idoc=1&file=char..)

Jelenlegi adatbázisaink kódlapbeállításait a psql -l paranccsal tekinthetjük meg.

Oracle

Az Oracle számára kommunikálhatjuk preferált kódlapunkat az NLS_LANG környezeti változó segítségével (is). Ha ezt webes környezetben használjuk, akkor a környezeti változót célszerűen vagy az Apache konfigjában állítjuk be (megfelelő konfigurációs sorokkal), vagy valahol máshol, konkrétan az Apache beindulása előtt (mondjuk az Apache indítgatására szolgáló wrapper scriptben)

Például:

  NLS_LANG=HUNGARIAN_HUNGARY.EE8ISO8859P2  

Ez aztán egyéni céljainknak megfelelően variálható (pl. a nyelv_ország lehet akár AMERICAN_AMERICA is (az ISO-8859-2-es kódlap mellett), mert ez már nincsenek hatással a karakterek kezelésére - a "nyelv" paraméter az üzenetek kiírását, az "ország" pedig a dátum-, szám- és fizetőeszköz formátumát és kezelését befolyásolja).

Lásd: http://otn.oracle.com/products/reports/htdocs/getstart/docs/A92102_0..

Mint látható, kissé minden adatbáziskezelő másképp képzeli ezt a kódlap-dolgot, itt pont sikerült három egész eltérő konfigurációs módot kifognunk.

Különösebb problémákba más RDBMS-ek esetén sem nagyon futhatunk - arra viszont NAGYON figyeljünk, hogy ha nemcsak webes alkalmazásunk használja az adatbázist, akkor arra is tekintettel kell lennünk! Egy nagyobb rendszer esetén ez szoros együttműködést jelent más alkalmazásfejlesztőkkel és az adatbázis adminisztrátorával.

Levelek küldése

A levelek kiküldését szép magyar karakterekkel a PHP alól a multi-byte sztringfüggvények segítségével tudjuk talán a legszebben kivitelezni, valahogy így:

  <?   mb_internal_encoding('iso-8859-2');   setlocale(LC_CTYPE, 'hu_HU');   $felado =     '"'.       mb_encode_mimeheader(         trim( $felado_teljes_neve ), 'iso-8859-2', 'Q', "\n\t").     '"'.     ' <' . $felado_emailcime . ">";   $level_temaja =       mb_encode_mimeheader(         trim( $level_temaja ), 'iso-8859-2', 'Q', "\n\t");   $HEADERS =     "From: $felado\n".     "Subject: ".trim($level_temaja)."\n".     "Content-type: text/plain; charset=\"iso-8859-2\"\n".     "Mime-Version: 1.0\n"     ;   $sendmail = popen('/usr/lib/sendmail -t -f '.$mail, 'w');   if ($sendmail) {     $num =  fputs($sendmail, $HEADERS);     $num += fputs($sendmail, 'To: '. $cimzett_cime ."\n");     $num += fputs($sendmail, "\n");     $num += fputs($sendmail, $level_szovege );     pclose($sendmail);   }   ?>  
Természetesen nem a multi-byte függvények használata az egyetlen üdvözítő megoldás, azonban kétségkívül "ő" van a legalaposabban felkészítve a kódlapok kezelésére.

Némi magyarázat azért mindenképp szükséges lehet...

  mb_internal_encoding('iso-8859-2');  

Az mb_internal_encoding a multibyte függvények számára definiálja előzetesen, hogy az általunk paraméterekben átadott szövegek milyen kódlap alatt "készültek". Értelemszerűen azt az oldalt, ahol a levél tartalmát összeállítjuk, a megfelelő kódlapheadert el kell helyeznünk.

  $felado =     '"'.       mb_encode_mimeheader(         trim( $felado_teljes_neve ), 'iso-8859-2', 'Q', "\n\t").     '"'.     ' <' . $felado_emailcime . ">";  

Itt egy egyszerű "Kovács József" <jozsef@kovacs.hu> formájú sztring összeállítása történik. A gyakorlottabbak persze már tudják, hogy a levélben kiküldünk egy Content-type headert is, ami a kódlapot írja le - azonban a levelezőprogramok azt nem veszik érvényesre a Subject és más, headerben közlekedő sorokra. Sőt, a headerben (nem a levél bodyjában) utazó szövegekkel kapcsolatosan egész pontosan akkor járunk el szerencsésen, ha csak az alapvető 128 karakterre hagyatkozunk (vagyis 7 biten ábrázolható karaketereket használunk) - mivel egyes levelezőszerverek/programok más esetekben meglepetéseket (számunkra hibákat) tudnak okozni.

Ahhoz tehát, hogy az idézőjelek közötti szöveg helyesen jelenjen meg, el kell azt tehát kódolnunk olyan formára, ami ékezetes, ISO-8859-2 formáju szövegünkből nem ékezetes, 7 biten ábrázolható szöveget állít elő. Az mb_encode_mimeheader() függvény pont egy olyan elkódolást végez, amely nekünk alkalmas a célra - ez a függvény szövegünket 7 biten ábrázolhatóra kódolja át úgy, hogy az ékezetes és egyéb speciális karaketereket egy sajátos (szabványos) jelölésrendszerrel cseréli fel. Ezt a levelezőprogramok is ismerik, így a levelezőkben helyesen fog megjelenni az adott sztring.

A 'Q' paraméter a két választható kódolási mechanizmusból (transfer-encoding) az egyiket jelöli ki, értéke lehet 'Q' (quoted-printable) vagy 'B' (base64), jelentős indokok (tudtommal) nem szólnak sem egyik vagy másik mellett vagy ellen.

A \n\t karakterekkel azt írjuk elő, hogy az idevágó 822-es RFC-ben előírtnál hosszabb sorokat egy soremeléssel és egy tab karakterrel törje meg (ezt foldingnak hívják az RFC-ben). Ennek segítségével elérjük azt, hogy szép, szabványosan formázott többsoros fejléc kerekedjen a levelünk előtt. A sortörés kérdése igencsak fontos, ugyanis a túl hosszúra hagyott sorokat egyes levelezőszerverek nem viszik át (vagy akár átalakítják saját szájízük szerint), egyes levelezőkliensek pedig hibásan jelenítik meg. Egy "szép" subjectsor ehhez hasonlóan néz ki:

  Subject: =?ISO-8859-2?Q?=E1rv=EDzt=FBr=F5_t=FCk=F6rf=FAr=F3g=E9p_=C1R?=           =?ISO-8859-2?Q?V=CDZT=DBR=D5_T=DCK=D6RF=DAR=D3G=C9P_=E1rv=EDzt=FBr=F5?=           =?ISO-8859-2?Q?_t=FCk=F6rf=FAr=F3g=E9p_=C1RV=CDZT=DBR=D5_T=DCK=D6R?=           =?ISO-8859-2?Q?F=DAR=D3G=C9P_?=  
(ez a szöveg mellesleg a szokásos "árvíztűrő tükörfúrógép ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP" kétszer egymásután). Ilyen formában (a \n\t-nek köszönhetően) a levelünk ékezetesen is átverekszi magát a levelezőszerverek és kliensek forgatagán.

Ugyanezt a függvényt használjuk a Subject sorban is, így különösebb meglepetést ez sem okozhat - ami még érdekes kicsiny példánkból, az az, hogy miért is érdemes kínlódni a sendmail program meghívásával ahelyett, hogy a PHP mail() függvényét használnánk...

Ez a PHP-ben rejlő érdekes bugra vezethető vissza, amely a 4.2.3 verzióig létezett (elméletileg az utána következő verziók már túlvannak ezen). A tárgysort a PHP ugyanis egy kis átalakításnak veti alá (vagy vetette, ki hol tart épp a verziókban :) - konkrétan kiszed belőle minden vezérlőkaraktert, így a mi \n\t sorozatunkat is. Azaz, ha mi szépen megformáztuk a subjectünket, akkor igen jó esély van arra, hogy néhány mailer hibásan jelenítse meg, mivel eltűntek belőle a szabvány szerint szükséges folding-karakterek... Ez a hiba persze csak akkor jön elő, amikor az ékezetek vagy a Subject hossza miatt túl hosszú sorokat kellene elküldeni (tehát előfordulhat, hogy már működő levélküldőinknél is beugorhat a probléma, csak még a felhasználók nem adtak meg olyan hosszú mailcímet).

Egyébként ha levélküldést tesztelünk, igyekezzünk minél több mailerrel megtekinteni az eredményt - még az Outlook Express és az Outlook között is igen sok különbség kiugorhat (főleg ezek különböző verziói alatt), de sokan használnak még Netscape 4.7x-et levelezésre, és persze még a Netscape 7-es széria mailere, az Opera M2-je, Linux és Unix alatt a pine, és így tovább...
    ////     setlocale(LC_CTYPE, 'hu_HU');

Linkek

A HTTP headerek közelebbről
Web-alapú HTTP header vizsgálat, mindössze meg kell adni a vizsgálni kívánt URL-t:
Mozilla(/Netscape) kiegészítés, a megnyitott oldalakkal kapcsolatos headereket lehet vele áttekinteni
  • http://livehttpheaders.mozdev.org/installation.html
Néhány fizetős segédprogram, érdemes kipróbálgatni őket, igen hasznosak lehetnek.
A cikkben előforduló linkek