Home Map Index Search News Archives Links About LF
[Top Bar]
[Bottom Bar]
[Photo of the Author]
Luis Colorado
Yazar Hakkında:

Luis Colorado UNIX sistemleri ve Telefónica Sistemas S.A. için Internet erişim yönetmeni olarak İspanya'da calışmaktadır. Universidad Complutense of Madrid'in Fizik bölümünü bitirmiş olup çeşitli açık kaynak UNIX kullandırımları (utility) olusturmuştur.

Yazara yazın

İçindekiler:
Giriş
Motivasyon
M4
Nasıl çalışır
Kullanıcıdan CGI'a veri aktarımı
Yöreyeçekim

Görsel Sanalortamdan Veritabanına PG2CGI Girişi

Çeviri: Görkem Şevik

[Ilustration]

Özet:

HTML sayfalarından veritabanı girişini sağlayan yeni bir program betimliyoruz. Programın tasarım amaçları veri girişini denetleme, düzenlemedeki esneklik ve biçimden bağımsızlıktı. Bu program son 12 ay boyunca Linux Journal ve LinuxFocus(www.linuxfocus.org) dergilerinde okuduğum M4 ile ilgili pekçok yazı sonucu kafamda oluşan fikirlerle sonuçlanmıştır.


Giriş

Bu yazı görselerişim'den veritabanı girişini sağlayacak paketi oluşturmama neden olan düşünce ve akıl yürütmeleri anlatmaktadır. PG2CGI paketi hakkında bir elyordamı yazmak eğiliminde değildim (bir yolgösteren kaynağı zaten yazılımın dağıtımında içerilmektedir, bu paket için URL daha sonra verilecektir), aslında amacım kısa bir tanıtım yapmak ve okuyucuları bunu kullanmak ve geribeslemelerini göndermek için iteklemektir.

Motivasyon

Bu programı Linux Journal ve LinuxFocus'da yayınlanan M4'ün HTML kaynaklarını yönetme ile ilgili yazılara yanıt olarak yazdım. Bu yazılar M4'ün görsel sanalyöre sayfalarının bakımını ve dinamik içerik üretimini sağlayan bir araç olarak avantajlarını ve potansıyellerini kanıtlamaktadır.

Diğer taraftan sayısız görsel sanalyöre sunucusu ve veritabanlarının elde edilebilirliği ile iki çevrenin arasındaki arayüzlerin eksikliği çelişmektedir (bu arayüz uygulamalarının çoğu tecimseldir (ticari) ya da kotarılabilecek (handled) biçimlerle ilgili eksiklikleri bulunmaktadİr).

Aşağıdaki yazılım paketi verıtabanı ve görselerişim çevrelerini birleştirmektedir. Şu gereksinimleri karşılamak için düzenlenmiştir:

Burada sunulan kullandırım bu gerektirimleri (requirement) verimdeki küçük bir azalma karşılığında sağlamaktadır (çalıştırım sürecinde M4'ü birkaç kez çağırmalıdır) fakat çoğu zaman sonuçlar doyurucu olmaktadır (çoğu durumda veritabanı sorgulamasının HTML metinlerinin dinamik oluşturumundan daha uzun zaman aldığını hesaba katmak gereklidir).

M4

M4 çok daha önceden oluşturulmuş bulunan bir makro üretici aygıttır. Bizim yazılımımız bu makro içlemcinin yoğun kullanımını gündeme getirir:

Makro işlemcinin yinelemeli kullanımı, GNU M4 özellikleri ile yaptığımız sınamaların doyurucu olmasına karşın, verimin azalması anlamına gelebilir.

Düzgün Anlatımlar:

Yazılımımız biçimlendirme kurallarının uygulanmasını doğrulamak için düzgün anlatımların (regular expressions) yoğun kullanımını gündeme getirmektedir. Düzgün anlatımlar basit karşılaştırmalara göre daha çok yeğlenmektedirler, çünkü bize daha fazla işlevsellik sağlamkatadırlar. Düzgün anlatımlar şu üstünlüklere de sahiptir:

PG2CGI, kullanılacak biçimlendirme kuralını doğrularken, düzgün anlatımları kullanır.

Anlatımların sözdizimi ve düzgün anlatımlarda geçen sürücüler için veri incelenmesi tek bir düzgün anlatımda yan zincirlerin toplanması sayesinde kolayca yapılabilir.

Bir örnek: diyelim ki müşteri query_string'e bazı bılgıler girmek zorunda ve bu bılgıler şu söz dizimine uyacak:

    FIELD=value
    

Bunun da ötesinde, query_string bu biçime uymalı ve katarda hiçbir ek bilgi olmamalı.

Bu sözdizimine uymayı zorlamak seçim kuralında aşağıdaki terimi yazarak kolayca başarılabilir:

    QUERY_STRING: "^FIELD=[^&]*$";
            

Önceki satırlar sadece QUERY_STRING sözdizimine uyduğunda kuralın çağrılmasına izin verir. Sadece bu da değil, eğer tümcedeki değeri parantezler arasına alırsak, program karşı gelen değerin alınmasına izin verir:

    QUERY_STRING: "^FIELD=([^&]*)$";
    
İşlem sırasında program kaçış ardıllarını %xx formunda gezginde tanıtarak da gönderebilir.

Nasıl Çalışır?

Programın nasıl çalıştığını anlatma zamanı geldi. İlk başlatıldığında görselerişim sunucusu cevresinden değişkenleri alır ve bu değişkenlere göre kendisini biçimlendirir. Çevre değişkenleri programın bulmak zorunda olduğu şeylerdir: Peki ya istemciler? İstemlerin kökenleri nerede? İstemciler tarafından hangi tür bilgiler (MIME türü) destekleniyor? vs. PG2CGI sol tarafa dayalı olan kuralı kullanacak olan kuralı seçer. Aynı zamanda üç çeşit kural vardır:

Bütün bunlarla kuralları oluşturmaya başlayabiliriz. Daha sonra kural için geçerli bir değer bulacak olan bazı durumlar gruplayacağız. Bu durumlar küme parantezleri "{}" içinde yer alacak.

Bir kuralın sol ve sağ tarafları küme parantezleri "{}" ile sınırlandırılacak ve `->' ile ayrılacak.

Sağ taraf aynı sözdizimli durumları icermektedir: bir değişken adı, ':' karakteri, karakterler zinciri ve ';' sonuçlandırıcısı. Sağ taraftaki tüm durumlar değişkenlere atanacak M4 tarafından yerine getirilecek degerlerdir:

Diğer değişkenler ya şablon dosyası ile ya da karşı gelen sürücü ile kullanılabilir.

Kullanıcıdaki Bilgi CGI'a Nasıl Ulaşır?

Çok kolay. Her kuralın sol tarafındaki terimlerin içindeki düzgün anlatımlardan oluşan gruplar değişkenlere çevrilir (bu yeni değişkenler için kullanılan adlar şu şekli alır: `term_<i>_match_<j>', burada <i> terimin kuraldaki sırasının sayısını göstermektedir (böylece ilk terim 1, ikinci bölüm 2, ... şeklinde olacaktır) ve <j> açıklayıcı tümcenin solundan itibaren sayarak grubun derecesini gösterir. Sonra query_string istemci tarafından geçilirse:

`NAME=JOSE&FAMNAME1=DE+LA+FUENTE&FAMNAME2=LOPEZ'

ve görsel sanalyörede belirtimi yapılan kural:

     QUERY_STRING: "NAME=([^&]*)";
     QUERY_STRING: "FAMNAME1=([^&]*)";
     QUERY_STRING: "FAMNAME2=([^&]*)";
sonuç:
     term_0_match_0  <- "NAME=JOSE";
     term_0_match_1  <- "JOSE";
     term_1_match_0  <- "FAMNAME1=DE LA FUENTE";
           (noticed the replacement of the + characters by ` ')
     term_1_match_1  <- "DE LA FUENTE";
     term_2_match_0  <- "FAMNAME2=LOPEZ";
     term_2_match_1  <- "LOPEZ";
Sürücüler:

Bu makalede sürücülerin kullanımını anlatmayacağız, bütün bunlar PG2CGI 'ın dağıtımında içerilen kaynakyazılarda anlatılmıştır. İlgilenen okuyucular içerilen kaynak elyordamına bakabilirler.

Şu an sadece bir sürücü bulunmaktadır, o da POSTGRESQL veritabanının bağlantısı içindir. Yazar LDAP türünde veritabanları için yeni bir sürücü yazma planlamasında bulunmaktadır.

Bir Örnek:

Haydi, şimdi tam bir örnek vermek amacıyla kaynakları inceleyelim.

Duyurular tablosunu slug.ctv.es deki duyuruların veritabanından duyurular çizelgesini gözönüne alalım. ( AVISO A LOS NAVEGANTES bağlantısını izleyelim) Bu bir tablodan bireysel kayıtları incelemek veya tam bir liste yapmak için iki şablon kullanan çok basit bir örnektir.

/etc/html2sql.cfg
{
  PATH_INFO: "^/avisos/?$"; # PATH_INFO tarafından seçiliyor
  [SERVER_ADMIN: ".*"];     # SERVER_ADMIN'den bilgi alıyor. Seçmeli
} -> {
  DRIVER:       "POSTGRESQL";
  PGTTY:        "/dev/console"; # Konsola kayıtlar gönderir
  PGDATABASE:   "postgres";
# Bir sorgu yaratıyoruz (OID'yi her zaman öylesine yazın ki 
# o şablon dosyasında bireysel kayıtlara bağlantı kurmak için 
# içeriden çalışsın)
  PGQUERY:  "select oid,ct,titulo,texto,mt"
      " from avisos"
      " where (dt is NULL or dt > 'now')"
      " order by mt desc";
# Şablonu içeren dosya
  M4FILE:    "/usr/local/etc/httpd/plantillas_m4/avisos.m4";
  WEBMASTER: "term_1_match_0";
  #TESTMODE: "TRUE";
}

# Sonraki seçim kuralı, bilinen bir OID (birincil açkı) ile
# duyuruyu (aviso)seçmeyi sağlamaktadır. Bilgi CGI'daki PATH_INFO 
# değişkeninde içerilir.

{
  PATH_INFO: "^/avisos/([0-9]+)/?$";
  SERVER_ADMIN: ".*";
} -> {
  DRIVER:    "POSTGRESQL";
  PGTTY:     "/dev/console"; # önceden olduğu gibi kayıtları konsola yazar
  PGDATABASE:  "postgres";
  OID:      "term_0_match_1"; # bir OID atar

# Bir kez daha seçim önem kazanmaktadır. Bu kayıdı silmek için bir hiperlink
# yazamak istediğimizde alanın başlangıcında OID içeririz.

  PGQUERY:   "select oid,ct,titulo,texto,mt,dt,autor"
             " from avisos"
             " where (dt is NULL or dt > 'now') and oid=OID";
# Şimdi şablon değişmiş olmaktadır.
  M4FILE:    "/usr/local/etc/httpd/plantillas_m4/avisos_oid.m4";
  WEBMASTER: "term_1_match_0";
  #TESTMODE: "TRUE";
}

/usr/local/etc/httpd/plantillas_m4/avisos.m4
define(<<<for>>>, <<<dnl
ifelse(eval((<<<$2>>>) <= (<<<$3>>>)), 1,
<<<define(<<<$1>>>,<<<$2>>>)$4<<<>>>dnl
for(<<<$1>>>,eval(<<<$2>>>+1),<<<$3>>>, <<<$4>>>)dnl
>>>)dnl
>>>)dnl
divert(0)dnl
Mime-Version: 1.0
Content-type: text/html

<HTML>
  <BODY BGCOLOR="#ffffff">
    <CENTER>
      <H1>AVISOS A LOS NAVEGANTES QUE PASAN POR SLUG</h1>
    </center>
    <B>Nota:</b> Esta secci&oacute;n ha sido creada para dar a conocer
    cualquier noticia de inter&eacute;s relacionada con
    <A HREF="http://slug.ctv.es/">SLUG</a>,
    <A HREF="http://LuCAS.ctv.es/">LuCAS</a>,
    <A HREF="http://www.HispaLinux.ctv.es/">HispaLinux</a>
    y en general, cualquier servicio prestado por <B>slug.ctv.es</b>.<p>
    <CENTER><HR WIDTH=100></center>
ifelse(PGRES_RESULTSTATUS, <<<PGRES_TUPLES_OK>>>,<<<dnl
ifelse(PGRES_NTUPLES, 0,<<<dnl

      <!-- la tabla est\xe1 vac\xeda -->
      No hay avisos.<p>

>>>,<<<dnl /* PGRES_NTUPLES != 0 )( */
      <CENTER>
        <!-- contenido de la tabla -->
        <TABLE>
          <TR>
            <TH></th>
            <TH ALIGN="LEFT">Fecha-Hora&nbsp;</th>
            <TH ALIGN="LEFT">Asunto&nbsp;</th>
          </tr>

for(<<<i>>>,0,eval(PGRES_NTUPLES-1),<<<dnl
          <TR>
            <TD>
              <A HREF="/cgi-bin/pg2cgi/avisos/cell(i,0)">
                <IMG SRC="/icons/burst.gif">
              </a>
            </td>
            <TD><B>cell(i,1)&nbsp;</b></td>
            <TD>cell(i,2)&nbsp;</td>
          </tr>
>>>)dnl /* for */

        </table>
      </center>

>>>)dnl /* PGRES_NTUPLES */

>>>,<<<dnl /* ifelse PGRES_RESULTSTATUS )(*/

      Error en el resultado: <B>PGRES_RESULTSTATUS</b><BR>
      Mensaje del servidor: PGRES_ERRORMSG<P>

>>>)dnl

      <CENTER><HR WIDTH=100></center>
      <FONT SIZE=-2>
        <A HREF="mailto:WEBMASTER?subject=TABLON DE ANUNCIOS"><CODE>WEBMASTER</code></a>
      </font>
  </body>
</html>


/usr/local/etc/httpd/plantillas_m4/avisos_oid.m4
divert(-1)
$Id: generic_list.m4,v 1.1 1998/07/06 17:13:33 luis Exp $
define(<<<cell>>>, <<<PGRES_CELL_$1_$2>>>)
define(<<<field>>>, <<<PGRES_FNAME_$1>>>)
define(<<<for>>>, <<<dnl
ifelse(eval((<<<$2>>>) <= (<<<$3>>>)), 1,
<<<define(<<<$1>>>,<<<$2>>>)$4<<<>>>dnl
for(<<<$1>>>,eval(<<<$2>>>+1),<<<$3>>>, <<<$4>>>)dnl
>>>)dnl
>>>)dnl
divert(0)dnl
Mime-Version: 1.0
Content-type: text/html

<HTML>
  <BODY BGCOLOR="#ffffff">
    <CENTER>
      <H1>AVISO OID</h1>
    </center>
    <CENTER><HR WIDTH=100></center>

ifelse(PGRES_RESULTSTATUS, <<<PGRES_TUPLES_OK>>>,<<<dnl
ifelse(PGRES_NTUPLES, 0,<<<dnl

      <!-- la tabla est\xe1 vac\xeda -->
      No existe el aviso OID, o ha caducado.<p>

>>>,<<<dnl /* PGRES_NTUPLES != 0 )( */
      <CENTER>
        <!-- contenido de la tabla -->
        <TABLE>
          <TR VALIGN="BASELINE">
            <TD ALIGN="RIGHT" NOWRAP><font color="#808000"><B>Fecha de entrada:</b></font> </td>
            <TD width="80%">cell(0,1)</td>
          </tr><TR VALIGN="BASELINE">
            <TD ALIGN="RIGHT" NOWRAP><font color="#808000"><B>Fecha &uacute;ltima modif:</b></font> </td>
            <TD>cell(0,4)</td>
          </tr><TR VALIGN="BASELINE">
            <TD ALIGN="RIGHT" NOWRAP><font color="#808000"><B>Fecha eliminaci&oacute;n:</b></font> </td>
            <TD WIDTH=*>cell(0,5)</td>
          </tr><TR VALIGN="BASELINE">
            <TD ALIGN="RIGHT" NOWRAP><font color="#808000"><B>Autor:</b></font> </td>
            <TD><font size=+1><a href="mailto:cell(0,6)?subject=[TABLON-SLUG] cell(0,2)">cell(0,6)</a></font></td>
          </tr><TR VALIGN="BASELINE">
            <TD ALIGN="RIGHT" NOWRAP><font color="#808000"><B>Asunto:</b></font> </td>
            <TD><font size=+1><B>cell(0,2)<B></font></td>
          </tr><TR>
            <TD COLSPAN=2 BGCOLOR="#c0ffff"><font color="#404040">cell(0,3)</font></td>
          </tr>
        </table>
      </center>

>>>)dnl /* PGRES_NTUPLES */

>>>,<<<dnl /* ifelse PGRES_RESULTSTATUS )(*/

      Error en el resultado: <B>PGRES_RESULTSTATUS</b><BR>
      Mensaje del servidor: PGRES_ERRORMSG<P>

>>>)dnl

      <CENTER><HR WIDTH=100></center>
      <FONT SIZE=-2>
        <A HREF="mailto:WEBMASTER?subject=TABLON DE ANUNCIOS"><CODE>WEBMASTER</code></a>
      </font>
  </body>
</html>

Sonuçlar bu URL'lardan görülebilir:
http://slug.ctv.es/cgi-bin/pg2cgi/avisos/
or
http://slug.ctv.es/cgi-bin/pg2cgi/avisos/20384

Yöreyeçekim

PG2CGI programı izleyen URL'lerden yöreyeçekilebilir :

http://slug.ctv.es/~luis/utils/pg2cgi.tar.gz
http://slug.ctv.es/~luis/utils/pg2cgi.README
ftp://slug.ctv.es/pub/slug/luis/pg2cgi.tar.gz
ftp://slug.ctv.es/pub/slug/luis/pg2cgi.README

Miguel A Sepulveda tarafından İngilizce'ye çevrilmiştir


Bu görsel sanalyörenin bakımını Miguel Ángel Sepúlveda yapmaktadır
© Luis Colorado 1998
LinuxFocus 1999