Bölüm 4: Form İşleme

POST metodunda bilgiler URL ile birlikte gönderilmediği GET metodundan daha güvenlidir. POST metodunun GET metoduna bir diğer üstünlüğü de daha fazla bilgi gönderebilmesidir. Ayrıca, GET metodu ile gönderilen bilgiler web browser, web server ya da proxy server'ın kaşe belleğinde (cache) saklanabilir fakat POST metodu ile bilgiler her defasında yeniden gönderilir. Dezavantajı ise POST ile gönderilen bilgiler daha karmaşık olacağından dolayı bu bilgileri çözmek için daha biraz daha karmaşık bir kod yazmamız gerekir.

Web server, form bilgilerini CGI programına kodlayarak gönderir. Alfanumerik karakterler olduğu gibi gönderilir; boşluklar artı (+) işaretine çevrilir; tab, çift tırnak (") gibi özel işaretler de "%HH" şeklinde kodlanır. Burada "HH" karakterin ASCII karşılığının hexadesimal (16'lık sistemdeki) değeridir. Bu kodlama işlemine "URL kodlama" denir. Aşağıdaki tabloda sık kullanılan bazı karakterlerin kodlanmış karşılıklarını görebilirsiniz.

Normal
Karakter
Kodlanmış
Hali
 \n (enter)  %0A
 \t (tab)  %09
 /  %2F
 ~  %7E
 :  %3A
 ;  %3B
 @  %40
 &  %26

Gönderilen bilgiyle işe yarar şeyler yapabilmek için CGI bu kodlanmış bilgiyi çözmelidir. Neyse ki Perl'de substitute ve translate komutlarıyla bunu yapmak oldukça kolaydır. Perl, karakter içerisinde arama yapma ve değiştirme konusunda oldukça yeteneklidir. substitute komutunun temel yazılış biçimi aşağıdaki gibidir.

    $yazi =~ s/aranan/yerinekonan/;

Bu örnek $yazi scalar değişkeninde aranan kelimesinin yerine yerinekonan kelimesini koyar. Araya konan operatör =~ (eşittir ve yanında tilde) işaretidir.

Daha iyi anlaşılacağını düşündüğüm başka bir örnek:

    $selamlama = "Merhaba. Benim adım xisimx.\n";
    $selamlama =~ s/xnamex/Sinan/;
    print $selamlama;

Yukarıdaki örnek "Merhaba. Benim adım Sinan." yazdıracaktır. $selamlama değişkeninde "xisimx"in yerini "Sinan"ın aldığına dikkat edin.

Buna yakın fakat bir parça farklı bir komut da translate komutudur.

    $yazi =~ tr/arananlistesi/yerinekonanlistesi/;

Bu komut "arananlistesi"ndeki bütün karakterleri "yerinekonan" listesindekilerle değiştirir. İşte bir örnek:

    $kucukh =~ tr/[A-Z]/[a-z]/;

Bu örnek bütün yazıyı küçük harfe çevirir. [A-Z]'deki parantezler karşılaştırılacak karakter sınıfını belirtir.

Şimdi tekrar formlara dönelim. Formla gönderilen bilginin kodunu çözmeniz için bilgide iki değişiklik yapmalısınız:

    $value =~ tr/+/ /;
    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

İlk satırda + işaretleri boşluğa çevrilir. İkinci satırda ise pack() fonksiyonu kullanılarak %HH hex çiftleri ASCII karşılıklarına çevrilir.

Şimdi "post.cgi" adında yeni bir CGI hazırlayalım.

    #!/usr/bin/perl

    print "Content-type:text/html\n\n";

    read(STDIN, $tampon, $ENV{'CONTENT_LENGTH'});
    @ciftler = split(/&/, $tampon);
    foreach $cift (@ciftler) {
       ($isim, $deger) = split(/=/, $cift);
       $deger =~ tr/+/ /;
       $deger =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
       $FORM{$isim} = $deger;
    }

    print "<html><head><title>Form Bilgileri</title></head><body>";
    print "<h2>Formla gönderilen bilgiler:</h2>\n";

    foreach $anahtar (keys(%FORM)) {
       print "$anahtar = $FORM{$anahtar}<br>";
    }

    print "</body></html>";

Şimdi yukarıdaki kodları açıklayalım. Form ile gönderilen bilgi önce $tampon scalar değişkenine okunuyor. Sonra & işaretlerinden ayrılarak elde edilen "formdegiskeni=deger" şeklindeki form alanı bilgileri @ciftler dizisine yerleştiriliyor. Sonra foreach döngüsünde herbir form alanı bilgisi = işaretinden ayrılıyor ve URL kodu çözülerek %FORM Hash değişkenine atanıyor. %FORM değişkenindeki anahtar adları form alanının adıdır. Mesela <input type="text" name="ad" size=30> HTML kodunda koyu yazılan "ad" değeri form alanının adıdır. Formunuzda "ad" ve "soyad" isimli iki form alanı varsa scriptinizde bu değerleri $FORM{'ad'} ve $FORM{'soyad'} şeklinde kullanabilirsiniz.

Aşağıdaki örneği inceleyerek split fonksiyonunun nasıl çalıştığını hatırlayalım.

    $yazi = "sari&kirmizi&yesil";
    @renkler = split(/&/,$yazi);

@renkler değişkeninin yeni değeri ("sari","kirmizi","yesil") olur.

Şimdi de scriptimizi denemeye geldi sıra. Form için aşağıdaki kodları kullanarak bir HTML dosyası oluşturun ve "post.html" adıyla kaydedin.

    <form action="http://www.sinanilyas.com/cgi-bin/ornek/post.cgi" method="POST">
    <pre>
       Adınız: <input type="text" name="ad" size=30><br>
    Soyadınız: <input type="text" name="soyad" size=30><br>
    </pre>
    <input type="submit" value="Gönder">
    <input type="reset" value="Tümünü Sil">
    </form>

Denemek için tıklayın

İsterseniz scriptimizi biraz daha geliştirelim. Scriptimiz form bilgilerini mail adresimize göndersin. İlk önce sistemimizde sendmail programının nerede olduğunu bulalım. Bunu öğrenmek için which sendmail ya da whereis sendmail komutunu kullanabilirsiniz. (sinanilyas.com için bu programın yeri /usr/sbin/sendmail olduğundan örneklerimizde bu şekilde kullanacağız. Eğer sizin server'ınızda farklı bir yerde ise kendi server'ınızdaki yerini yazmanız gerekir.)

Not: @ işaretini çift tırnak arasında ya da print <<HTMLSonu bloğunda kullanırken önüne "sinan\@sinanilyas.com" örneğindeki gibi \ işareti koymalısınız. Tek tırnak arasında 'sinan@sinanilyas.com' örneğinde olduğu gibi \ işareti koymadan güvenle kullanabilirsiniz.

    #!/usr/bin/perl

    print "Content-type:text/html\n\n";

    read(STDIN, $tampon, $ENV{'CONTENT_LENGTH'});
    @ciftler = split(/&/, $tampon);
    foreach $cift (@ciftler) {
        ($isim, $deger) = split(/=/, $cift);
        $deger =~ tr/+/ /;
        $deger =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
        $FORM{$isim} = $deger;
    }

    $mailprog = '/usr/sbin/sendmail';

    # bunu kendi mail adresinizle değiştirin

    $gonderilen = 'sinan@sinanilyas.com';

    # burada maili göndermek üzere sendmail programı açılıyor
    # eğer sendmail programı bulunamazsa hata alt programı (en altta)
    # işletilerek programın bulunamadığı yazıyor

    open (MAIL, "|$mailprog -t") or &hata("$mailprog bulunamadı!\n");

    # sendmail programına mailin kime gönderileceği bildiriliyor

    print MAIL "To: $gonderilen\n";

    # sendmail programına ziyaretçinin email adresi bildiriliyor.
    # bu "Yanıtla" tuşuna bastığınızda işe yarar
    # kullanmak zorunda değilsiniz
    # formunuzda 'email' ve 'isim' kutularının bulunduğu varsayılmıştır.

    print MAIL "Reply-to: $FORM{'email'}\n";

    # sendmail programına mailin konusu gönderiliyor
    # konudan sonra iki tane \n olduğuna dikkat edin

    print MAIL "Subject: Form Bilgileri\n\n";

    # sendmail programına form bilgileri gönderiliyor

    foreach $anahtar (keys(%FORM)) {
       print MAIL "$anahtar = $FORM{$anahtar}\n";
    }

    # bilgiler gönderildikten sonra sendmail programını kapatmayı unutmayın

    close(MAIL);

    # teşekkür sayfası oluşturuluyor

    print <<HTMLSonu;
    <html><head><title>Teşekkürler</title></head><body>
    <h2>Teşekkürler</h2>
    Mailiniz gönderildi. Formu gönderdiğiniz için teşekkürler<p>
    </body></html>
    HTMLSonu
    ;

    # hata alt programı

    sub hata {
        ($hatamesaji) = @_;
        print "<html><head><title>Hata!</title></head><body>";
        print "<h2>Hata</h2>\n";
        print "$hatamesaji<p>\n";
        print "</body></html>\n";
        exit;
    }

Yukarıdaki scriptte yeni bir yapı kullandık: hata isimli bir "alt program". Alt programlar programların sadece çağırıldıkları zaman işletilen komutlarıdır diyebiliriz. Örneğimizde hata alt programı sadece sendmail programı bulunamazsa çalıştırılır. Programınızın bu durumda size bir server hatası vermesi yerine neyin yanlış gittiğine dair bilgi vermesini istersiniz. hata alt programıyla bu yapılıyor. sendmail programının bulunmadığını bildiren bir web sayfası gösteriyor ve Perl'den çıkıyor. Perl'de alt programlar &altprogramadi ya da &atlprogramadi (argümanlar) şeklinde çağrılır. Argümanlar alt programa gönderilen değerlerdir.

Şimdi aşağıdaki kodlarla bir form oluşturun ve scripti deneyin.

    <form action="http://www.sinanilyas.com/cgi-bin/ornek/mail.cgi" method="POST">
    <pre>
              Adınız: <input type="text" name="isim" size=30>
    E-mail adresiniz: <input type="text" name="email" size=30>
        Web sayfanız: <input type="text" name="web_sayfasi" size=30>
             Yaşınız: <input type="text" name="yas" size=3>
    </pre>
    <input type="submit" value="Gönder">
    <input type="reset" value="Tümünü Sil">
    </form>

Denemek için tıklayın

Eğer herşey yolunda giderse birkaç dakika sonra form bilgileri e-mail adresine gelecektir.

Eğer form bilgilerini birkaç adrese birden göndermek istiyorsanız adresleri aşağıdaki gibi aralarına virgül koyarak yazabilirsiniz.

    $gonderilen = 'sinan@sinanilyas.com, silyas@sakarya.edu.tr, sinanilyas@gmx.net';

Önceki Konular Sonraki

     

©1997-2005, Sinan İLYAS