Pagina precedentãPagina principalãPagina urmãtoareIndex


Publicarea unui site pe un server UNIX


Server de WEB

       O aplicatie de tip server Web este un program reactiv. El ruleazã în continuu pe un calculator conectat la INTERNET (server) asteptând sã-i parvinã o cerere din partea unei aplcatii client care ruleazã pe un alt calculator din retea (Netscape, Internet Explorer, etc.). Serverul de Web controleazã o colectie de documente (fisiere) dispuse pe discul calculatorului pe care acesta este instalat. Documentele sunt dispuse într-o structurã arborescentã. Dacã aplicatia client solicitã un document existent, aplicatia server le va furniza respectând regulile unui protocol precizat în cererea clientului (http). Pe un server de INTERNET ruleazã pe lângã serverul de Web si alte aplicatii server (pentru transmisii utilizând alte protocoale de transfer, de exemplu ftp). Transferul fisierelor se va realiza folosind protocolul de transmisie prin retea TCP/IP.

      Stabilirea unei conexiuni între calculatorul client si server :

      Documentele Web sunt de regulã documente multimedia continând text, imagini, sunet, animatii. Ele sunt stocate pe disc în mai multe fisiere, fiecare fisier continând informatii de un anumit tip. La solicitarea din partea operatorului a unui document aplicatia client începe prin a cere serverului documentul principal (document hipertext) si apoi diferitele fragmente referite prin marcajele din componenta acestuia (<IMG>de exemplu). Serverul va primi deci o suitã de cereri de transfer de fisiere începând cu fisierul principal. Asamblarea documentului din fragmentele primite cade în sarcina aplicatiei client.

      Pe serverele de INTERNET functionând sub Linux programul server de Web cel mai popular este Apache, distribuit împreunã cu Linux-ul. Pentru regãsirea fisierelor solicitate de cãtre aplicatiile client pe un server functionând sub Linux acestea sunt dispuse în directoare prestabilite, astfel :

      Fisierele care sunt transferate folosind protocolul ftp sunt dispuse în directorul /home/ftp.

      Pentru a putea separa fisierele diferitelor site-uri înregistrate pe discul serverului se vor crea directoare derivate, în care fisierele vor fi plasate dupã aceleasi reguli (documentele hipertext în directoare derivate din /home/httpd/htp, etc.).

      Dacã o cerere care parvine serverului nu specificã numele fisierului care trebuie transmis, serverul va trimite din directorul precizat fisierul index.html.

      Dacã o cerere de document hipertext contine numai numele serverului pe care sunt plasate fisierele unui site, serverul va furniza de exemplu documentul /home/httpd/htp/index.html.
http://postuniv.east.utcluj.ro/                          /home/httpd/htp/index.html
http://postuniv.east.utcluj.ro/sitecj/mon/          /home/httpd/htp/sitecj/mon/index.html

Publicarea site-ului creat

      Pentru publicarea (transferul) unui site pe un server de INTERNET sunt necesari pasii urmãtori :

  1. Crearea de cãtre administratorul serverului (conectat ca root) a structurii de directoare necesare :
  2. Modificarea de cãtre administrator (root) a proprietarului acestor directoare folosind comanda UNIX chown :
    # chown proprietar fisiere
  3. Transferul de cãtre proprietar a fisierelor site-ului. Transferul se poate face cu utilitarul FTP Explorer. Dupã conectarea la server se vor selecta pe rând directoarele create si se vor transfera fisierele corespunzãtoare. Transferul se va realiza selectând pe calculator, în Windows Explorer fisierele si directoarele de transferat si deplasându-le cu mouse-ul în fereastra programului FTP Explorer.
  4. Dacã site-ul contine scripturi sau alte aplicatii care se vor executa pe server se va lansa programul Telnet si se vor crea executabilele. Drepturile de acces la directorul în care aplicatiile vor fi plasate (derivat din /home/httpd/cgi-bin) vor fi modificate folosind comanda UNIX chmod :
    $ chmod 777 director

    Scrierea scripturilor pentru prelucrarea datelor din formulare având METHOD="POST"

          Marcajul <FORM> din paginile Web care contin formulare specificã numele aplicatiei existente pe server (script) care realizeazã prelucrarea informatiilor trimise în momentul apãsãrii butonului Submit &ICIRC;ntrucât informatia parvine serverului ca un sir de caractere, prelucrarea constã de regulã în extragerea (separarea) informatiilor si apoi înregistrarea lor în fisiere existente pe server. &ICIRC;nregistrarea poate fi realizatã direct de cãtre aplicatie sau ca urmare a unor comenzi pe care aplicatia le trimite unei aplicatii dedicate (de regulã un server SQL).

          De obicei aplicatiile de acest tip sunt scrise în C, JAVA, sau PEARL (limbaj dedicat) dar pot fi scrise în orice limbaj pentru care pe server existã instrumente de dezvoltare.

          Principial o aplicatie de tip script CGI (Common Gateway Interface)

    1. citeste un sir de caractere din fisierul standard de intrare (stdin în C) în care aplicatia client a plasat informatiile din câmpurile formularului;
    2. le prelucreazã;
    3. trimite un rãspuns aplicatiei client. Rãspunsul este scris în fisierul standard de iesire (stdout în C).

      Exemplu:

      Exemplul 1:
      Se considerã fisierul magazin.htmlde intrare într-un magazin virtual :
      <HTML>
      <HEAD>
      <TITLE>Formular</TITLE>
      </HEAD>
      <BODY link="#0000FF" vlink="#800080" background="Image4.gif">
      <H1 ALIGN=center>Intrarea în magazinul virtual</H1>
      <CENTER>
      <FORM action="http://tcm.east.utcluj.ro/cgi-bin/mb/iasp/Form1" METHOD="POST">
      <TABLE>
      <TR><TH>Numele :</TH><TD><INPUT type=text size=25 name="nume"></TD>
      </TR><TR><TH>Prenumele :
      </TH><TD><INPUT type=text size=25 name="prenume"></TD>
      </TR><TR><TH>Codul de acces :
      </TH><TD><INPUT type=password size=10 name="cod_acces"></TD>
      </TR>
      </TABLE>
      <BR><BR>
      <INPUT TYPE=checkbox NAME="clinou">Intru prima datã în magazin
      <BR><BR> Plãtesc cu : <INPUT TYPE=radio NAME="plata" VALUE="0"><B>Card VISA</B>    
      <INPUT TYPE=radio NAME="plata" VALUE="1"><B>Cec</B>    
      <INPUT TYPE=radio NAME="plata" VALUE="2"><B>Mandat postal</B>
      <BR><BR>
      <TABLE>
      <TR> <TH ALIGN=left>Impresia dv. :</TH>
      </TR><TR>
      <TD><TEXTAREA NAME=rezumat ROWS=5 COLS=45></TEXTAREA>
      </TD></TR>
      </TABLE><BR> Mergem în raionul cu produse   
      <SELECT NAME=raion>
      <OPTION SELECTED VALUE=niciunde>(alegeti raionul)
      <OPTION VALUE=alimente>Produse alimentare
      <OPTION VALUE=bautura>Bãuturi
      <OPTION VALUE=cosmetice>Cosmetice
      <OPTION VALUE=menaj>Articole de menaj
      <OPTION VALUE=imbrac>Îmbrãcãminte
      <OPTION VALUE=electro>Articole electrocasnice
      <OPTION VALUE=gradina>Articole pentru grãdinãrit
      </SELECT>
      <BR><BR>
      <INPUT TYPE=submit value ="Intrãm în magazin!">
      </CENTER>
      </FORM>
      </BODY>
      </HTML>

            Pentru a vedea ce primeste aplicatia de pe server (Form1) s-a scris o versiune a acesteia care retrimite aplicatiei client sirul de caractere primit :

      #include <stdio.h>
      void main(int argc, char *argv[])
      {

      char S[200];
      scanf("%s",S);
      printf("Content-type: text/html%c%c",10,10);
      printf("<HTML><HEAD><TITLE>Sirul primit</TITLE></HEAD>");
      printf("<BODY>");
      printf("<H1>Am primit sirul</H1><HR><HR>");
      printf("Sir: %s", S);
      printf("</BODY></HTML>");

      }

            Citirea s-a realizat cu ajutorul functiei scanf() de citire din fisierul standard de intrare iar trimiterea rãspunsului spre client s-a realizat printr-o succesiune de functii printf(), de scriere în fisierul standard de iesire.

            Scrierea începe prin instructiunea

      printf("Content-type: text/html%c%c",10,10);

            Aceasta comunicã aplicatiei client ce va primi în continuare, aceastã informatie fiind obligatorie. Urmãtoarele instructiuni printf() comunicã aplicatiei client folosind codul HTML ce trebuie sã afiseze ecranul acesteia. Dacã pentru scrierea paginilor Web se pot folosi editoare specializate nefiind teoretic necesarã cunoasterea codificãrii HTML, pentru scrierea scripturilor cunoasterea acesteia este strict obligatorie !

            Dupã completarea informatiilor din câmpurile formularului si apãsarea butonului Submit pe ecranul acesteia se va afisa rãspunsul serverului :

            Se observã cã în sirul primit de aplicatia de pe server apar denumirile câmpurilor formularului (nume, prenume, cod_acces, …) urmate fiecare de caracterul '=' si de valoarea introdusã. Spatiile sunt înlocuite de caractere '+' iar separarea informatiilor corespunzãtoare diferitelor câmpuri se realizeazã prin caractere '&'.

            Erorile din script vor provoca afisarea pe ecranul aplicatiei client (Netscape) a unui mesaj de eroare. Dacã de exemplu se omite instructiunea printf() prin care se comunicã aplicatiei client tipul datelor pe care le va receptiona, aceasta va afisa mesajul de eroare :

      Exemplu:

      Exemplul 2 :

            Se considerã o paginã continând datele necesare înregistrãrii unui cursant în cadrul Scolii Academice Postuniversitare Informaticã Aplicatã si Programare :

            &ICIRC;n continuare se prezintã codul HTML asociat si scriptul care realizeazã prelucrarea datelor din formular :


      <HTML>
      <HEAD>
      <TITLE>Fisa de inscriere</TITLE>
      </HEAD>
      <BODY link="#0000FF" vlink="#800080" background="Image4.gif">
      <center><img SRC="Image6.gif" height=4 width=500></center>
      <H2 ALIGN=center>Fisa de inscriere</H2>
      <center><img SRC="Image6.gif" height=4 width=500></center>
      <FORM action="http://tcm.east.utcluj.ro/cgi-bin/mb/iasp/Formul" method="POST">
      <B>Numele<SUP>(*)</SUP> :  </B>
      <INPUT type="text" size="25" name="nume">
           <B>Initiala tatalui :  </B>
      <INPUT type="text" size="4" name="initiala">
      <BR>
      <B>Prenumele : </B><INPUT type="text" size="25" name="prenume">
      <BR> Daca in urma casatoriei numele dv. s-a schimbat, completati mai jos numele conform certificatului de nastere
      <BR>
            Numele : <INPUT type="text" size="25" name="nume1">
      <HR>
      <B>Data nasterii : </B>     anul :
      <INPUT type="text" size="4" name="an">
          luna : <INPUT type="text" size="9" name="luna">
          ziua : <INPUT type="text" size="2" name="zi">
      <HR>
      <B>Locul nasterii :    </B> <BR>        Localitatea :
      <INPUT type="text" size="25" name="local">
      <BR>        Judetul :       
      <INPUT type="text" size="25" name="judet">
      <HR>
      <B>Adresa : </B>    <INPUT type="text" size="70" name="adresa"><BR>
             Cod postal :   
      <INPUT type="text" size="4" name="cod">
           Localitatea :    
      <INPUT type="text" size="25" name="localitatea"> <BR>
             Judetul :   
      <INPUT type="text" size="16" name="jud">
      <BR> <BR>
      <center><img SRC="Image6.gif" height=4 width=500></center>
      <BR>
      <B>Denumirea cursului : </B> <BR>
      <INPUT type=radio name="curs" checked value="0"> Bazele utilizarii calculatorului IBM-PC<BR>
      <INPUT type=radio name="curs" value="1"> Bazele programarii calculatoarelor. Notiuni de programare în limbajul C
      <BR>
      <INPUT type=radio name="curs" value="2"> Programarea în C a aplicatiilor WINDOWS<BR>
      <INPUT type=radio name="curs" value="2"> Programarea aplicatiilor WINDOWS în VISUAL C++<BR>
      <INPUT type=radio name="curs" value="2"> Utilizarea calculatorului în proiectarea constructiva si tehnologica<BR>
      <INPUT type=radio name="curs" value="2"> Crearea si exploatarea bazelor de date relationale<BR>
      <INPUT type=radio name="curs" value="2"> Realizarea aplicatiilor multimedia si a documentelor hypertext<BR>
      <INPUT type=radio name="curs" value="2"> Utilizarea calculatorului în modelare cu elemente finite, calcul numeric si simbolic<BR>
      <INPUT type=radio name="curs" value="2"> Notiuni de sisteme de operare si retele de calculatoare<BR>
      <BR>
      <B> Voi participa la curs in semestrul :
          </B>
      <INPUT type=radio name="semestrul" checked value="0"> I (octombrie-februarie)
      <INPUT type=radio name="semestrul" value="1"> II (martie-iunie) <BR> <BR>
      <center><img SRC="Image6.gif" height=4 width=500></center>
      <BR>
      <P> <CENTER>
      <INPUT type = "submit" value = "Expediere formular">     
      <INPUT type = "reset" value = " Anulare ">
      </CENTER>
      <BR>
      <center>
      <table>
      <th> <a href="index.html"><img SRC="but_rev.jpg" BORDER=0 height=30 width=55 ALIGN=middle></a> </th>
      <th> <FONT size=4 COLOR="#0000FF" ALIGN=middle>
      <I><B>Pagina principala... </B> </I>
      </FONT> </th> </table> </center>
      <P><I> <font COLOR=blue> Va multumim pentru atentia cu care ati completat formularul. Mult succes! </I> </font>
      </FORM>
      </body>
      </html>





      #include <stdio.h>
      #include <string.h>
      #include <stdlib.h>

      struct entry {
      char *name;
      char *val;
      };

      char *camp(char *line, char stop);
      char *cuvant(FILE *f, char stop, int *len);
      void plustospace(char *);

      void main(int argc, char *argv[])
      {
      struct entry intrari[25]; /* Pentru campuri */
      char s[250];
      int cl, i ; /* cl = nr. de caractere, i = pozitia in sirul receptionat */
      int numeid=0, initialaid=0, prenumeid=0, nume1id=0, anid=0, lunaid=0, ziid=0, localid=0, judetid=0, adresaid=0, codid=0, localitateaid=0, judid=0, cursid=0, semestrulid=0;
      /* Variabile care retin pozitiile in sirul intrari */ int nrlegitim;
      FILE *fp;
      FILE *inscrisi;
      cl = atoi(getenv("CONTENT_LENGTH")); /* Nr. de caractere primite */
      intrari[0].val = "";
      for (i=1;cl && (!feof(stdin)); i++) {
      /* Recuperez campul curent (sir de forma nume=valoare) */
      intrari[i].val = cuvant(stdin,'&',&cl);
      /* Inlocuiesc plusurile cu spatii */
      plustospace(intrari[i].val);
      /* Recuperez numele campului (caracterele pana la '=') */
      intrari[i].name = camp(intrari[i].val,'=');
      if ((!strcmp(intrari[i].name, "nume")) &&
      (strcmp(intrari[i].val, ""))) {
      /* strcmp(s1, s2) return. valoarea 0 daca s1=s2 si 1 daca s1 > s2 */
      numeid = i;
      /* daca intrari[i].name="nume" se memoreaza i in numeid,
      daca nu, se continua testele */
      } else if ((!strcmp(intrari[i].name, "initiala")) && (strcmp(intrari[i].val, ""))) { initialaid = i;
      } else if ((!strcmp(intrari[i].name, "prenume")) && (strcmp(intrari[i].val, ""))) { prenumeid = i;
      } else if (!strcmp(intrari[i].name, "nume1")) { nume1id = i;
      } else if ((!strcmp(intrari[i].name, "an")) && (strcmp(intrari[i].val, ""))) { anid = i;
      } else if ((!strcmp(intrari[i].name, "luna")) && (strcmp(intrari[i].val, ""))) { lunaid = i;
      } else if ((!strcmp(intrari[i].name, "zi")) && (strcmp(intrari[i].val, ""))) { ziid = i;
      } else if ((!strcmp(intrari[i].name, "local")) && (strcmp(intrari[i].val, ""))) { localid = i;
      } else if (!strcmp(intrari[i].name, "judet")) { judetid = i;
      } else if ((!strcmp(intrari[i].name, "adresa")) && (strcmp(intrari[i].val, ""))) { adresaid = i;
      } else if ((!strcmp(intrari[i].name, "cod")) && (strcmp(intrari[i].val, ""))) { codid = i;
      } else if ((!strcmp(intrari[i].name, "localitatea")) && (strcmp(intrari[i].val, ""))) { localitateaid = i;
      } else if (!strcmp(intrari[i].name, "jud")) { judid = i;
      } else if ((!strcmp(intrari[i].name, "curs")) && (strcmp(intrari[i].val, ""))) { cursid = i;
      } else if ((!strcmp(intrari[i].name, "semestrul")) && (strcmp(intrari[i].val, ""))) { semestrulid = i;
      }
      }
      /* Trimit programului de navigatie (Netscape . . .) tipul docum. Pe care il va primi (in cazul dat, o pagina Web) care se codifica sub forma text/html apoi trimit doua caractere LF (cod ASCII 10) */
      printf("Content-type: text/html%c%c", 10, 10);
      /* Verific daca toate campurile au fost completate */
      if (numeid*initialaid*prenumeid*anid*lunaid*ziid* localid*judetid*adresaid*codid*localitateaid* judid*cursid*semestrulid == 0) {
      /* Trimit un document .html de raspuns */
      printf("<HTML><HEAD><TITLE>Inscriere REFUZATA</TITLE></HEAD>");
      printf("<BODY><H1>Inscriere refuzata. Completati toate campurile!</H1></BODY></HTML>");
      }
      else {
      printf("<HTML><HEAD><TITLE>Inscriere acceptata</TITLE> </HEAD>");
      printf("<BODY><H1>Inscriere acceptata!</H1><HR>");
      /* Emit numarul de legitimatie */
      fp = fopen("/home/httpd/cgi-bin/mb/iasp/numar.dat", "r");
      fscanf(fp, "%d", &nrlegitim);
      fclose(fp);
      nrlegitim++;
      fp = fopen("/home/httpd/cgi-bin/mb/iasp/numar.dat", "w");
      fprintf(fp, "%d", nrlegitim);
      fclose(fp);
      printf("<H3>Cererea dv. a fost inregistrata cu numarul %d.</H3>", nrlegitim);
      printf("<HR><I>Pentru orice corespondenta ulterioara folositi acest numar.</I>");
      printf("</BODY></HTML>"); inscrisi = fopen("/home/httpd/cgi-bin/mb/iasp/inscrisi.dat", "a");
      fprintf(inscrisi, "%d \t ", nrlegitim);
      fprintf(inscrisi, "%s \t ", intrari[numeid].val);
      fprintf(inscrisi, "%s \t ", intrari[initialaid].val);
      fprintf(inscrisi, "%s \t ", intrari[prenumeid].val);
      fprintf(inscrisi, "%s \t ", intrari[anid].val);
      fprintf(inscrisi, "%s \t ", intrari[lunaid].val);
      fprintf(inscrisi, "%s \t ", intrari[ziid].val);
      fprintf(inscrisi, "%s \t ", intrari[localid].val);
      fprintf(inscrisi, "%s \t ", intrari[judetid].val);
      fprintf(inscrisi, "%s \t ", intrari[adresaid].val);
      fprintf(inscrisi, "%s \t ", intrari[codid].val);
      fprintf(inscrisi, "%s \t ", intrari[localitateaid].val);
      fprintf(inscrisi, "%s \t ", intrari[judid].val);
      fprintf(inscrisi, "%s \t ", intrari[cursid].val);
      fprintf(inscrisi, "%s \n ", intrari[semestrulid].val);
      fclose(inscrisi);
      }
      }

      char *camp(char *line, char stop)
      {
      int i=0, y;
      char *word = (char *) malloc(sizeof(char) * (strlen(line) +1));
      for(i=0;((line[i]) && (line[i] != stop)); i++) word[i] = line[i];
      word[i] = '\0'; /* Inchid sirul word la dreapta */
      if (line[i]) ++i; /* Depasesc separatorul */
      y=0; /* Translatez restul sirului peste zona deja preluata in word */
      while(line[y++] = line[i++]);
      return word;
      }

      /* Recuperez caracterele pana la caracterul 'stop' */
      char *cuvant(FILE *f, char stop, int *cl)
      {
      int wsize=1000; /* Functia preia siruri avand max. wsize = 1000 carac. */
      char *word;
      int i=0; /* numara caracterele citite */ word = (char *)malloc(sizeof(char) * (wsize + 1));
      while(1) {
      word[i] = (char)fgetc(f);
      --(*cl);
      if((i == wsize) || (word[i] == stop) || (feof(f)) || (!(*cl))) {
      if ((word[i] != stop) || (i == wsize)) i++; word[i] = '\0';
      return word;
      }
      ++i;
      }
      }

      void plustospace(char *str)
      {
      int i;
      for(i=0; str[i]; i++)
      if(str[i] == '+') str[i] = ' '; /* Inloc. car. '+' cu spatiu */
      }

            Structura aplicatiei precum si functiile de recuperare a informatiilor utile din câmpurile formularului pot fi pãstrate pentru orice alt formular.

            Fatã de cele incluse în acest script, o astfel de aplicatie mai poate realiza si trimiterea unui mesaj prin e-mail clientului (cursantului în cazul de mai sus). Dacã adresa e-mail a destinatarului este continutã în intrari[emailid].val atunci în zona de prelucrare a informatiilor primite si decodificate se vor include liniile :


      FILE *out;
      char buf(81);
      . . .
      sprintf(buf, "%s %s", EMAIL_BINARY,
      intrari[emailid].val);
      out=popen(buf, "w");
      fprintf(out, "From : %s\n", damian@yahoo.com);
      fprintf(out, "Subject: Acceptare inscriere\n");
      fprintf(out, "Va multumim ca v-ati exprimat dorinta de …");
      . . .
      pclose(out);
      . . .


      Pagina precedentãPagina principalãPagina urmãtoareIndex