Lomakkeiden käsittely esteettömästi, tekniikkana CGI
Tässä artikkelissa kerrotaan, miten verkkosivustoon toteutetaan lomaketta käyttävä toiminto CGI-tekniikalla siten, että se toimii kaikenlaisissa käyttötilanteissa. Erityisesti kiinnitetään huomiota siihen, että käyttäjän saama palaute on selkeää ja myös ääneen luettuna helposti ymmärrettävä.
Tarkemmin sanoen tekniikkana käytetään Perl-kielellä kirjoitettuja ohjelmia, jotka on asennettu toimimaan CGI-skripteinä. Jos palvelimessa käytettävä tekniikka on jokin muu, esimerkiksi ASP tai PHP, tässä kuvattavat menettelyt eivät sovellu sellaisinaan, mutta esitetyistä yleisistä periaatteista on silti hyötyä.
Lukijan oletetaan tuntevan HTML-lomakkeiden, Perl-kielen ja CGI:n käytön perusteet taikka opiskelevan niitä rinnan tämän aineiston kanssa. Näistä aiheista löytyy tietoja esimerkiksi seuraavien sivujen kautta: WWW-lomakkeet, Suomenkielistä aineistoa Perl-kielestä Webissä ja Web-julkaisemisen oppaan kohta Palvelinskriptit (server-side scripting).
Ensimmäinen tavoite: lomake, jonka voi täyttää vaikka silmät kiinni
Yksi tavoite on, että lomakkeen voi täyttää sananmukaisesti silmät kiinni. Tämä on vain osa yleistä tavoitetta: lomake tulisi voida täyttää erilaisissa käyttötilanteissa ja -muodoissa. Tähän sisältyy myös esimerkiksi se, että lomakkeen voi täyttää myös kokonaan ilman hiirtä tai vaikkapa puhumalla, sikäli kuin käyttäjän laite ja ohjelmisto tätä tukevat.
Alla on esimerkki lomakkeen osasta, joka ei kovin hyvin täytä tätä vaatimusta:
Tämän voisi selain esittää ääneen esimerkiksi näin: "Lomake alkaa. Sukunimi etunimi synt asiakasnumero. Kirjoita teksti." Käyttäjän kirjoitettua ensimmäisen syöttötiedon kuuluisi seuraavaksi uusi kehote: "Kirjoita teksti". Kirjoittaminen käy hankalaksi, jos kenttiä on paljon, koska käyttäjän pitää muistaa tietojen järjestys.
Harjoitustehtävä: Millainen olisi vaihtoehto, joka toimisi paremmin ääniesityksessä? Mitä etuja tai haittoja siitä olisi näkyvässä esityksessä?
Harjoitustehtävä: Mene Googlen sivulle, jolla monipuolinen hakutoiminto
("advanced search", suomenkielisessä versiossa "lisähaku"); osoite on
<http://www.google.com/advanced_search>.
Siirrä hiiri syrjään niin, ettet pääse siihen käsiksi. Tee haku, joka etsii
ruotsinkielisiä sivuja .fi-domainista hakusanana kiva. Millaisia vaikeuksia
hiirettömyys aiheutti?
Aihetta käsitellään jäljempänä kohdassa Esteettömän lomakkeen tekeminen. Lomakkeen täyttämisen ja lähettämisen sujuvuuden lisäksi on tärkeää, millaisen vastauksen käyttäjä saa, kun hän on lähettänyt lomakkeen. Tätä aihetta on yleensä käsitelty melko vähän, yllättävän vähän.
Toinen tavoite: vastaus, joka menee suoraan asiaan
Jos kyse on esimerkiksi hakutoiminnosta, jossa käyttäjä on antanut hakusanan ja napsauttanut Hae-painiketta, hänen saamansa vastauksen tulisi alkaa olennaisilla tiedoilla. Hyvin olennaista on, montako osumaa kaikkiaan löytyi, koska varsin usein osumien määrästä voidaan heti päätellä, onko hakua syytä tarkentaa tai muuten muuttaa, suunnilleen seuraavaan tapaan:
Haku sanalla "kissa" tuotti 47 900 osumaa: - -
Tällaisen tiedon olisi hyvä olla heti alussa ja mielellään myös korostettuna - ei siis siihen tapaan, kuin eräs monella muulla tavalla hyvä hakutoiminto aloittaa vastauksensa:
![]()
![]()
![]()
Lisähaku Asetukset Kielivalinnat Hakuvihjeitä
Webbi
Kuvat
Keskusteluryhmät
Hakemisto
Jos edellä oleva luettaisiin puhesyntetisaattorin avulla, esitys alkaisi tähän tapaan: "siirry googlen kotisivulle lisähaku asetukset kielivalinnat hakuvihjeitä kissa syöttökenttä google-haku valintanappi etsi vee vee veestä valintanappi etsi kielellä suomi vebbi kuvat keskusteluryhmät hakemisto". Vasta tämän jälkeen käyttäjä kuulisi, mikä oli haun tulos. Lisäksi sivulla näkyvästä esityksestä monen on hankala löytää olennaisin tieto, ellei se ole alussa.
Kolmas tavoite: palautetta käyttäjälle
Käyttäjälle tulee antaa riittävästi, mutta ei liikaa palautetta siitä, mitä tapahtui. Palautteen tulee olla helposti ymmärrettävässä muodossa, ei koodattuna eikä ammattikielellä.
Edellä sanottu koskee ensiksikin virhetilanteita. Jos käyttäjä on kirjoittanut vuosiluvun tilalle "tänä vuonna", hänen tulisi saada sentapainen virheilmoitus kuin "ilmoita vuosi nelinumeroisella vuosiluvulla", eikä siis esimerkiksi "digit expected", kuten helposti käy, jos lomakkeen käsittelyn koodaaja käyttää valmiita rutiineita ilman, että hän ottaa huomioon niiden vaikutuksen käyttöliittymään.
Myös normaalitilanteissa käyttäjän tulisi saada tietoa siitä, että kaikki menee hyvin, ja myös riittävästi tietoa esimerkiksi tallennettavaksi myöhempää käyttöä varten. Jos kyse on palautelomakkeesta, lomakkeen käsittelyn tulisi antaa vastaukseksi vaikkapa sivu, joka kertoo, milloin palaute on lähtenyt ja joka sisältää kopion käyttäjän kirjoittamasta tekstistä. On sitten käyttäjän ratkaistavissa, haluaako hän tulostaa sivun itselleen, tallentaa sen levylle, lähettää tiedoksi jonnekin tai muuta sellaista.
Jos kyse on esimerkiksi ilmoittautumis- tai tilauslomakkeesta, saatavan palautteen tulisi selvästi kertoa tapahtumista luomatta vääriä mielikuvia. Usein lomakkeen käsittelevä koodi vain tallentaa tiedot, jotka ihminen sitten myöhemmin käsittelee. Ilmoittautumista ei ole ehkä hyväksytty tai tilatun tavaran saatavuutta ei kenties ole mitenkään varmistettu. Saattaa olla tarpeen sanoa tämä erikseen, selvyyden vuoksi sekä myönteisesti että kielteisesti esimerkiksi seuraavaan tapaan: "Tämä on automaattinen vastaus tilaukseenne. Tilauksenne on tallentunut järjestelmäämme; se tullaan käsittelemään ja teille tullaan ilmoittamaan, voidaanko tuote tai tuotteet toimittaa ja milloin. Tämä ei ole tilausvahvistus, vaan vain ilmoitus siitä, että tilauksenne on nyt odottamassa käsittelyä."
Lomakkeen luonnin perusteet
On mahdollista kirjoittaa lomake (form-elementti) suoraan HTML-dokumenttiin jollakin
editorilla tai sivunteko-ohjelmalla. Yleensä on kuitenkin parempi tuottaa lomake (ja koko sivu, jolla se
on) samalla ohjelmalla, joka käsittelee lomakedatan. Tästä on muun muassa se etu, että
tällöin voidaan toteuttaa helposti se, että käyttäjän saama vastaus
sisältää uuden kopion lomakkeesta esimerkiksi uutta, tarkennettua hakua varten. Näin toimivat
muun muassa useimmat yleiset hakupalvelut. Kätevimmin tämä käy Perlin CGI.pm-modulilla, jota
jatkossa käytämme.
Seuraava alkeisesimerkki on Perl-ohjelma, joka CGI-skriptinä kutsuttuna tulostaa syötteenä annettujen lukujen tulon, jos syötteitä on. Joka tapauksessa ohjelma tulostaa HTML-lomakkeen, jolla voi antaa syötteenä kaksi lukua ja lähettää ne saman ohjelman käsiteltäviksi. Tämä voi olla aluksi käsitteellisesti hämäävää, mutta kyse on sekä näppärästä että hyödyllisestä menettelystä.
#!/usr/local/gnu/bin/perl
use CGI qw(:standard);
print header, start_html(-title=>'Kertolasku',-lang=>'fi'),
h1('Kertolasku');
$eka = param('eka');
$toka = param('toka');
if($eka && $toka) {
$tulo = $eka * $toka;
print p("Lukujen $eka ja $toka tulo on $tulo.");
print hr, start_form(-method=>'get'),
p('Voit tehdä uuden kertolaskun:'),
div(defaults('Tyhjennä lomakkeen kentät')); }
else {
print start_form(-method=>'get'); }
print
div('Tällä lomakkeella voit laskea kahden luvun tulon.'),
div('<label for="k1">1. luku:</label>',
textfield(-name=>'eka',-id=>'k1')),
div('<label for="k2">2. luku:</label>',
textfield(-name=>'toka',-id=>'k2')),
div(submit(-value => 'Laske tulo')),
end_form,
end_html;
- Ensimmäinen rivi
#!/usr/local/gnu/bin/perlkertoo Perl-tulkin sijainnin palvelimen tiedostojärjestelmässä. Sijainti ilmaistaan tiedostopolkuna, joka kirjoitetaan suoraan merkkien#!perään. Korjaa rivi sen mukaiseksi, mikä on sijainti käyttämässi palvelimessa. Se on luultavimmin jotain muuta kuin tässä esimerkissä. - Rivi
use CGI qw(:standard);ottaa käyttöön CGI.pm-kirjaston. - Eri
print-lauseet rakentavat sen HTML-dokumentin, jonka palvelin lähettää selaimelle vastaukseksi, kun selain on lähettänyt pyynnön, joka viittaa tähän skriptiin. - Funktio
headertuottaa merkkijonon, joka palvelimen vastauksen alkuun liitettynä sisältää tarpeelliset tiedot siitä, että vastaus koostuu HTML-dokumentista. - Funktio
start_htmltuottaa merkkijonon, joka aloittaa HTML-dokumentin (ja sisältää muun muassa<html>-tägin). Rakenteella-nimi=arvo annetaan lisätietoja niille CGI.pm:n funktioille, joilla rakennetaan HTML-elementtejä. - Mainitulla tavalla annettavasta lisätiedosta voi tulla erillinen elementti, esimerkiksi
-title=>'...'tässä yhteydessä tekee dokumenttiin<title>-elementin, jossa on haluttu sisältö eli niin sanottu ulkoinen nimi dokumentille. - Tavallisesti lisätiedosta tulee elementin määrite eli attribuutti. Esimerkiksi
-lang='fi'tuottaa<html>-tägin sisään määritteenlang="fi", joka ilmoittaa dokumentin kieleksi suomen. Tämä on periaatteessa hyvin olennaista, koska oletustoimintona CGI.pm:ssä on, että se tuottaa määritteenlang="en-US"(amerikanenglanti)! Kielen ilmoittamisen merkitystä käsittelee dokumentti Kielimerkkaus: tekstin kielen ilmoittaminen merkkausjärjestelmissä. - Funktionkutsu
h1('Kertolasku')tuottaah1-elementin (ylimmän tason otsikon), jonka sisältönä on annettu merkkijono. Tässä otsikko on yksinkertaisuuden vuoksi sama eri tilanteissa: sekä alkutilanteessa, jossa tulostuu vain lomake että muissa tilanteissa, joissa tulostuu myös tuloksia. Käytännössä on usein parempi, että tämä otsikko (ja mahdollisesti myös edellä mainittutitle-elementti) riippuu tilanteesta ja on esimerkiksi virhetilanteissa aivan erilainen kuin normaalitilanteissa. Tällöin on ohjelman rakennetta vastaavasti muutettava. Olennaista on, että niintitle-elementti kuin pääotsikkokin on informatiivinen; käytännössä niiden on hyvä olla merkittävästi pidempiä kuin tässä, esimerkiksi tyyliin "Haku XYZ-tietokannasta" tai "XYZ-tietokannasta tehdyn haun tuloksia". - Kutsulla
param('nimi')saadaan lomakkeen tietynnimisen kentän (parametrin) arvo sellaisena, kuin se on tullut, kun käyttäjä on lähettänyt lomakkeen. Alkutilanteessa, kun mitään lomaketta ei ole lähetetty, tämä arvo on määrittelemätön. - Käytännössä koodin ehto
if($eka && $toka)testaa, että lomakedata ylipäänsä sisältää tietyt kaksi kenttää ja että kumpikaan niistä ei ole tyhjä. (Perlissähän muuttujannimi kuten$ekaantaa arvon epätosi ehtolausekkeena käytettynä, jos muuttujan arvo on määrittelemätön tai tyhjä merkkijono.) - Funktiot
p,hrjadivtuottavat vastaavannimiset elementit siten, että elementin sisällöksi tulee se, mitä funktioille annetaan argumentteina. - Funktio
start_formaloittaa lomake-elementin rakentamisen, eli käytännössä se tuottaa<form>-aloitustägin. Koska CGI.pm:ssä on tällöin oletusarvonamethod="post", olemme muuttaneet tämän argumentilla-method=>'get', sillä esimerkiksi yksinkertaiselle laskentaohjelmalle ei ole mitään syytä käyttääpost-metodia. - Lomakkeessa on kolme perusosaa: kaksi tekstinsyöttökenttää ja yksi lähetyspainike.
Näitä ennen on vielä alustuskenttä, joka luodaan
defaults-funktiolla siinä tapauksessa, että ohjelma myös tulostaa vastauksia. (Tällainen alustuskenttä palauttaa syöttökentät alkutilaan, jonka itse skripti alun perin luo, siis tässä tapauksessa sellaiseen tilaan, että tekstinsyöttökentät ovat tyhjiä.) - Tekstisyöttökenttä luodaan
textfield-elementillä, jolle annetaan tässä määritteiksi nimi (-name=...) ja tunniste (-id=...). Jälkimmäistä määritettä tarvitaan, jotta elementti voidaan yhdistää selitteeseen eli kehotteeseen, joka kertoo, mitä kenttään pitäisi syöttää. - Valitettavasti selitekenttää eli
label-kenttää ei voida suoraan tuottaa CGI.pm:n nykyversiolla, vaan se joudutaan tekemään tuottamalla "raakaa HTML:ää". Toisaalta tämä havainnollistaa, miten tuotettaessa HTML-dokumentti CGI.pm:llä voidaan tarvittaessa käyttää CGI.pm:n valmiita, usein näppäriä funktiota sekaisin HTML:n suoran tuottamisen lisäksi. - Syöttökentän ja
label-kentän yhteys toisiinsa kuvataan siten, että syöttökentässä onid-määrite, jolla on jokin arvo, jota ei ole dokumentin millään muullaid-määritteellä, jalabel-kentässä on sitä vastaavafor-määrite. Tämä on usealla tavalla kömpelö järjestely, mutta siitä on apua monille käyttäjille, joiden käyttämät ohjelmat osaavat tällaisen merkkauksen perusteella auttaa käyttäjää tietämään, mitä mihinkin kenttään kuuluu kirjoittaa. - Huomaa, että koodi tuottaa
label-elementin ja vastaavan syöttökentän peräkkäin samalle riville, jolla ei ole mitään muuta. Tämä on yleensä selkein ja esteettömin ratkaisu. Tässä se on tehty teknisesti niin, että ne ovatdiv-elementin jälkeen. (Toinen tapa olisi kirjoittaa ne peräkkäin ja niiden jälkeenbr-elementti.)
Harjoitustehtävä: Selvitä, miten voit asentaa käyttämääsi
palvelimeen Perl-ohjelman CGI-skriptiksi, ja tarkista, että CGI.pm on tällöin
käytettävissä. Asenna sitten yllä oleva ohjelma ja kokeile sitä. Huomaa, että kyseinen
selvittely ei aina ole ihan helppoa. Jos tämä ei onnistu, kokeile kyseistä skriptiä valmiiksi
asennettuna osoitteessa <http://www.cs.tut.fi/cgi-bin/run/~jkorpela/kerro.cgi>.
Joka tapauksessa kokeile lomakkeen käyttöä myös ilman hiirtä.
Virheiden käsittely
Ihmiset tekevät virheitä, joskus hyvinkin paljon. Esimerkiksi lukihäiriöinen kirjoittaa hakusanoja väärin, kättään vaikeasti liikuttava saattaa napsauttaa väärää painiketta ja hätäisesti päätöksiä tekevä lähettää tiedot, vaikka kaikkia välttämättömiä kenttiä ei ole täytetty.
Hyvässä lomakkeenkäsittelyssä on sekä selaimessa tapahtuvia tarkistuksia että palvelimessa tapahtuvia tarkistuksia, yleensä niin, että sama asia tarkistetaan kahteen kertaan. Selaimessa tapahtuva tarkistus on hyödyksi, koska se antaa käyttäjälle nopean palautteen, jopa niin, että heti kirjoitettuaan vaikkapa sanan johonkin kenttään hän saa tiedon, että pitää kirjoittaa luku. Käytännössä kyse on JavaScript-koodista, joka liitetään sopivalla tavalla HTML-dokumenttiin. Palvelimessa tapahtuva tarkistus taas on varmistus, koska on monia syitä, joiden takia selaimessa tapahtuva tarkistus voi jäädä suorittamatta. Palvelimessa tapahtuva tarkistus on tärkeämpi yleisen toimivuuden ja turvallisuuden takia. Lisäksi siihen voi sisältyä sellaisia asioita, joita olisi mahdoton tehdä selaimessa, kuten tietokantoihin liittyvät tarkistukset.
Jos esimerkiksi testaamme edellä esitettyä lomaketta tekemällä kertolaskua tarpeeksi monta kertaa, huomaamme, että voimme kirjoittaa kenttiin vaikkapa kirjaimet a ja b ja saada mielettömän tuloksen "Lukujen a ja b tulo on 0".
Harjoitustehtävä: Miten kertolaskuohjelmaa pitäisi kehittää, jotta se
asianmukaisesti havaitsisi ja käsittelisi virhetilanteet kuten sen, että syöttötiedot eivät
ole lukuja lainkaan? Perlissä on useita erilaisia tapoja
tarkistaa, onko muuttujan arvo luku. Tällöin joudutaan määrittelemään tarkemmin,
mitä luku tässä tarkoittaa. Yksi tapa on seuraavanlainen testi:
if($foo == 0 && $foo ne "0") ...
(Tämä perustuu siihen, että operaattori == tekee numeerisen vertailun: jos
$foo:n arvo on ei-numeerinen, tulos on nolla. Testin toinen osa huolehtii siitä, että
tämä erotetaan tapauksesta, jossa arvo on nimenomaan 0.) Halutessasi voit tarkastella asiaa myös
vain periaatteellisesti: oletetaan, että sopivat testit ovat käytettävissä. Miten ohjelman tulisi
ilmoittaa virheistä, jotta on käyttäjäkin ymmärtää, että tällä kertaa ei tullutkaan tulosta vaan
virheilmoitus? Miten muotoilisit ilmoitukset ja miten auttaisit käyttäjää jatkamaan virhetilanteen
jälkeen?
Todelliset lomakkeet ovat usein melko laajoja, eli niissä on paljon kenttiä. Tällöin ei riitä, että kullekin kentälle on tarkistukset, vaan lisäksi kokonaisuuden tulee olla helposti hahmotettavissa. Lomaketta lähetettäessä (selaimessa) tai lomakkeen lähettämisen jälkeen (palvelimessa) tarkistuksen suorittava koodi saattaa esimerkiksi havaita, että kahden kentän arvot muodostavat loogisesti mahdottoman yhdistelmän. Tällöin on olennaista kertoa,
- että tiedoissa on virheitä ja että ne pitää korjata.
- mitkä kentät ovat virheellisiä.
- mikä niissä on vikana. Vika on ilmaistava niin selvästi, että käyttäjä ymmärtää, miten hänen on korjattava tietoja.
Esteettömän lomakkeen tekeminen
Edellä on käsitelty sitä, miten lomakkeilla lähetettyjen tietojen käsittely saadaan esteettömäksi, ja ennen muuta sitä, miten käyttäjän saamat vastaukset ovat käyttökelpoisia kaikille. Myös itse lomakkeen täyttäminen voi olla ongelmallista. Asiaintilan parantamiseksi lomakkeisiin tarvitaan erityisiä esteettömyyspiirteitä hyvän ja loogisen yleisen rakenteen lisäksi.
Edellä esitetyssä esimerkissä oli jo yksi keskeinen esteettömyyspiirre: kukin
syöttökenttä on omalla rivillään, jolla on myös sen selite, ja nämä on
liitetty toisiinsa label-merkkauksella. Selitteen on syytä olla ennen
tekstinsyöttökenttää. Jos taas kyseessä on valintanappi (radio
buttons, input type="radio") tai asetusnappi (input type="checkbox") eli
valintaruutu, on syytä noudattaa yleistä tapaa kirjoittaa selite sen jälkeen. Näiden kenttien
yhteydessä on label-merkkauksesta erityinen etu, koska sen ansiosta käyttäjä voi napsauttaa myös
selitetekstiä tehdäkseen valinnan. Tämä on olennaista, koska napit ovat yleensä aika pieniä ja siksi niihin
osuminen vaatii tarkkaa motoriikkaa. Seuraavassa on asetusnapista ja selitteestä esimerkki, jonka avulla
voit testata, tukeeko oma selaimesi tässä kuvattua piirrettä eli voiko asetuksen muuttaa myös tekstiä
klikkaamalla:
Käytetty merkkaus on:
<div><input type="checkbox" name="lounas" id="chk"><label for="chk">Haluan ilmaisen
lounaan</label></div>
- Pyri tekemään lomake omaksi sivukseen, ellei kyseessä ole hyvin yksinkertainen lomake kuten "hae tästä sivustosta" -lomake. Oma sivu auttaa keskittymään lomakkeen täyttämiseen.
- Kirjoita tarvittavat ohjeet ennen syöttökenttiä. Tämä on olennaista puhesynteesiä käyttäville mutta myös muille. Moni ihminen lukee tekstiä lopusta alkuun, vaikka loppupuolella olisi korostettujakin huomautuksia.
- Jos kuitenkin ohjeita olisi paljon (useita virkkeitä), yleensä on parempi sijoittaa ne linkin taakse. Tällöin lomakkeen alussa siis on vain viittaus varsinaisiin ohjeisiin, ja itse lomakkeessa on vain lyhyet kenttien selitykset. Tämä koskee varsinkin sellaisia lomakkeita, joita käytetään toistuvasti, sillä ei ole hauskaa aina kuulla samoja ohjeita aluksi. Jos kuitenkin on jotain erityisen tärkeää varoitettavaa, se täytyy sanoa itse lomakesivulla, koska ihmiset eivät useinkaan katso erillisiä ohjeita.
- Sijoita lähetyspainike (submit button) viimeiseksi ja anna sille lomakkeen
lähettämisen merkitystä kuvaava nimi. CGI.pm:llä tämä voidaan tehdä seuraavaan tapaan:
submit(-value=>'Hae')taisubmit(-value=>'Ilmoittaudu'). - Älä laita lomakkeeseen tyhjennyspainiketta (reset button). Siitä on lähes
aina pelkkää harmia, kun käyttäjä lomakkeen huolella täytettyään vahingossa painaa väärää nappia. Sen sijaan
joissakin tapauksissa voi olla aiheellista sijoittaa lomakkeen alkuun, kauas lähetyspainikkeesta,
edellä kuvattu alustuskenttä
defaults-funktiolla.
Harjoitustehtävä: Hahmottele, miten aiemmin tarkasteltua Googlen monipuolista hakutoimintoa voisi kehittää edellä esitettyjen periaatteiden mukaisesti. Voit myös tehdä vastaavan hahmottelun ja ehkä toteutusluonnoksenkin jollekin muulle suhteellisen isolle lomakkeelle.
Lisätietoja
Lisätietoja lomakkeiden käytön tekemisestä esteettömäksi on Tieken Esteettömyysoppaassa kohdassa Lomakkeet, jossa on myös linkkejä englanninkieliseen lisäaineistoon.
CGI.pm:ää käsittelee johdattelevasti The Fool's Guide to CGI.pm, the Perl module for CGI scripting ja yksityiskohtaisesti alkuperäisdokumentaatio CGI.pm - a Perl5 CGI Library.
Virheilmoitusten tekemistä ymmärrettäviksi käsittelee Error Message Guidelines .



