Direktørers mobiltelefoner. CGI script filtypenavn
Introduktion.
I denne artikel vil jeg tale om CGI-grænsefladen generelt, dens implementering til Windows og brugen af assemblersprog i særdeleshed ved skrivning af CGI-programmer. Det er uden for rammerne af denne artikel Fuld beskrivelse CGI, da der simpelthen er et hav af materiale om dette emne på internettet, og jeg kan simpelthen ikke se meningen med at genfortælle det hele her.
TeoriCGI.
CGI – (Common Gateway Interface) – Common Gateway Interface. Som du måske kan gætte, fungerer denne grænseflade som en gateway mellem serveren (her mener jeg serverprogrammet) og et eller andet eksternt program skrevet til det operativsystem, som netop denne server kører på. Således er CGI ansvarlig for præcis, hvordan data vil blive overført fra serverprogrammet til CGI-programmet og tilbage. Interfacet pålægger ingen begrænsninger for, hvad CGI-programmet skal skrives i; det kan enten være en almindelig eksekverbar fil eller en hvilken som helst anden fil - det vigtigste er, at serveren kan køre det (i Windows-miljøet kan det f.eks. kan være en fil med filtypenavnet knyttet til ethvert program).
Fra det øjeblik du ringede (for eksempel klikkede på en formularknap, som et CGI-programkald er knyttet til) CGI-programmet, indtil du modtager resultatet i dit browservindue, sker følgende:
En webklient (såsom en browser) opretter en forbindelse til den server, der er angivet i URL'en;
Webklienten sender en anmodning til serveren, denne anmodning foretages normalt ved hjælp af to metoder GET eller POST;
Data fra klientanmodningen (f.eks. formularfeltværdier) sendes af serveren ved hjælp af en CGI-grænseflade til det CGI-program, der er angivet i URL'en;
CGI-programmet behandler klientdataene modtaget fra serveren og genererer på baggrund af denne behandling et svar til klienten, som det transmitterer via det samme CGI-interface til serveren, og det transmitterer det igen direkte til klienten;
Serveren lukker forbindelsen med klienten.
Standard CGI-specifikationen forudsætter, at serveren kan kommunikere med programmet på følgende måder:
Miljøvariabler – de kan indstilles af serveren, når programmet starter;
Standard input stream (STDIN) - med sin hjælp kan serveren overføre data til programmet;
Standard output stream (STDOUT) – programmet kan skrive sit output ind i det, som sendes til serveren;
Kommandolinje – i den kan serveren videregive nogle parametre til programmet.
Standard input/output streams er meget praktiske og udbredt på UNIX-systemer, hvilket ikke kan siges om Windows, så der er en CGI-specifikation udviklet specifikt til Windows-systemer, kaldet "Windows CGI". Men selvfølgelig kan standard input/output streams også bruges i Windows CGI programmering. Her vil jeg ikke berøre "Windows CGI"-standarden, og der er mindst to grunde til dette - den første og vigtigste er, at i øjeblikket ikke alle http-servere til Windows understøtter denne specifikation (især min favorit Apache 1.3.19). Du kan se den anden grund ved at indtaste en hvilken som helst søgemaskine linje "Windows CGI". Jeg vil kun bemærke generelle detaljer vedrørende denne grænseflade - alle data fra serveren til klienten overføres ved hjælp af det sædvanlige Windows *. ini fil, hvis navn sendes til programmet på kommandolinjen. I dette tilfælde er alle data i filen allerede omhyggeligt opdelt i sektioner af serveren, og alt du skal gøre er at bruge "GetPrivateProfile*"-funktionerne til at udtrække dem derfra. Svaret sendes til serveren igen via en fil, hvis navn er angivet i den tilsvarende post i ini-filen.
Hvilke data kan overføres af klienten til CGI-programmet? - næsten alle. Generelt sendes programmet værdierne af formularfelterne, som klienten udfylder, men det kan også være en slags binær data, for eksempel en fil med et billede eller musik. Data kan overføres til serveren ved to forskellige metoder - GET-metoden og POST-metoden. Når vi opretter en formular, der skal udfyldes på vores side, angiver vi eksplicit, hvilken af de givne metoder, vi ønsker at sende de data, som brugeren har indtastet, dette gøres i formularens hovedtag noget som dette:
Når der sendes data ved hjælp af GET-metoden, læser browseren dataene fra formularen og placerer dem efter script-URL'en efterfulgt af et spørgsmålstegn; hvis der er flere væsentlige felter i formularen, sendes de alle gennem "&" tegnet, feltnavnet og dets værdi skrives i URL'en gennem "=" tegnet " For eksempel en anmodning genereret af en browser fra en formular, når du klikker på en knap, hvortil scriptet "/cgi-bin/test.exe" er knyttet, idet det tages i betragtning, at det første felt i formularen hedder "dit_navn" , den anden – “din_alder”, kan se sådan ud:
GET /cgi-bin/test.exe?dit_navn=Pupkin&your_age=90 HTTP/1.0
At bruge GET metoden har flere svagheder – den første og vigtigste er pga Dataene transmitteres i URL'en, så har den en grænse for mængden af disse transmitterede data. Den anden svaghed følger igen af URL'en - dette er fortrolighed, med en sådan overførsel forbliver dataene absolut åbne. Så det er godt, hvis vi har 2-3 små felter i formularen ... spørgsmålet opstår, hvad skal man gøre, hvis der er flere data? Svaret er at bruge POST-metoden!
Ved brug af metoden POST data overføres til serveren som en datablok og ikke i en URL, hvilket i nogen grad frigør vores hænder til at øge lydstyrken overførte oplysninger, for ovenstående POST-formeksempel vil blokeringen, der sendes til serveren, være sådan her:
POST /cgi-bin/test.exe HTTP/1.0
Accepter: tekst/almindelig
Accepter: tekst/html
Acceptere: */*
Indholdstype: application/x-www-form-urlencoded
Indholdslængde: 36
your_name=Pupkin&your_age=90
Som nævnt ovenfor, efter at have modtaget dataene, skal serveren transformere dem og transmittere dem CGI-program. I standard CGI-specifikationen placeres klientinput for en GET-anmodning af serveren i programmets miljøvariabel "QUERY_STRING". På POST anmodning Dataene placeres på applikationens standard inputstrøm, hvorfra de kan læses af den. Derudover sætter serveren med en sådan anmodning yderligere to miljøvariabler - CONTENT_LENGTH og CONTENT_TYPE, som man kan bedømme længden af anmodningen i bytes og dens indhold.
Ud over selve dataene sætter serveren også andre miljøvariabler for det kaldte program; her er nogle af dem:
REQUEST_METHOD
Beskriver præcis, hvordan dataene er opnået
Eksempel:REQUEST_METHOD=FÅ
QUERY_STRING
Forespørgselsstreng, hvis GET-metoden blev brugt
Eksempel:QUERY_STRING= dit_navn=Hvalpe&din_alder=90&hobby=asm
CONTENT_LENGTH
Længde i bytes af anmodningsteksten
Eksempel:CONTENT_LENGTH=31
INDHOLDSTYPE
Anmod om kropstype
GATEWAY_INTERFACE
CGI protokol version
Eksempel:GATEWAY_ GRÆNSEFLADE= CGI/1.1
REMOTE_ADDR
IP-adressen på den eksterne vært, det vil sige den klient, der klikkede på knappen i formularen
Eksempel: REMOTE_ADDR=10.21.23.10
REMOTE_HOST
Navnet på fjernværten, dette kan være dens domænenavn eller for eksempel computernavnet i Windows miljø, hvis de ikke kan modtages, så indeholder feltet sin IP
Eksempel:REMOTE_HOST=wasm.ru
SCRIPT_NAME
Navnet på det script, der blev brugt i anmodningen.
Eksempel:SCRIPT_NAME=/cgi-bin/gols.pl
SCRIPT_FILENAME
Navnet på scriptfilen på serveren.
Eksempel:SCRIPT_FILENAME=c:/page/cgi-bin/gols.pl
SERVER _ SOFTWARE
Server software
Eksempel: Apache/1.3.19 (VINDE32)
Generelt er dette alt i korte træk, for mere detaljeret information om Common Gateway Interface, se den specialiserede dokumentation, jeg lavede denne beskrivelse for at minde dig om, og hvis du ikke vidste det, så hold dig opdateret. Lad os prøve at gøre noget i praksis.
Praktisk del.
Til praksis har vi brug for mindst 3 ting - en slags http-server til Windows, jeg prøvede alle eksemplerne på Apache 1.3.19 til Windows, serveren er gratis, du kan downloade den fra http://httpd.apache. org/download.cgi . Ja, og vi skal bruge en server, ikke en hvilken som helst server, men en, der er konfigureret til at køre CGI-scripts! Se dokumentationen for, hvordan du gør dette for den server, du bruger. Den anden ting, vi har brug for, er selvfølgelig en assembler; det er også nødvendigt, at compileren understøtter oprettelsen af WIN32-konsolapplikationer, jeg bruger Tasm, men Fasm og Masm og mange andre *asms er perfekte. Og endelig er det vigtigste, at dette ønske er påkrævet.
Så jeg antager, at serveren blev installeret og konfigureret med succes af dig, så der i serverdokumenternes rodbibliotek er en index.html-fil, som vises perfekt i browseren, når du skriver adressen http://127.0 .0.1. Jeg vil også tage højde for, at der et sted i junglen af servermapper er en "cgi-bin"-mappe, hvori scripts må køre.
Lad os tjekke serverindstillingerne, og samtidig skrive et lille script. Vores script vil være en almindelig *.bat fil. Jeg forudser spørgsmål - hvordan? virkelig? Ja, det er normalt batch-fil, som nævnt ovenfor, skelner CGI-specifikationen ikke mellem filtyper, det vigtigste er, at serveren kan køre den, og den har til gengæld adgang til stdin/stdout og miljøvariabler, en bat-fil, omend ikke fuldt ud, men det vil for eksempel passe os ret godt. Lad os oprette en fil med omtrent følgende indhold:
@echo off rem Anmod om header echo Indholdstype: text/html echo. rem Request body echo "
Hej!ekko "Med FÅ anmodning modtagne data: %QUERY_STRING%
Lad os kalde filen test.bat og placere den i mappen til at køre scripts, højst sandsynligt vil det være mappen "cgi-bin". Den næste ting vi skal gøre er at kalde dette script på en eller anden måde, i princippet kan dette gøres direkte ved at skrive noget i stil med følgende "http://127.0.0.1/cgi-bin/test.bat" i browseradressen vindue, men lad os kalde det fra vores hovedside, og samtidig kontrollere GET-metodens funktion. Lad os oprette en fil index.html i serverroden med følgende indhold:
Nu, når du går ind på serveren (http://127.0.0.1 i browserens adresselinje), skal der vises en formular, skriv noget i den og klik på knappen "send", hvis alt blev gjort korrekt, vil du se svaret fra vores bat- i browservinduets script. Lad os nu se, hvad vi nåede frem til der.
Som du måske kan gætte, udsender "echo"-kommandoen til stdout; først og fremmest sender vi headeren af vores svar til serveren - "echo Content-type: text/html". Dette er en standard CGI-specifikationsheader, der indikerer, at vi ønsker at overføre tekst eller et html-dokument; der er andre overskrifter. Meget vigtigt punkt– titel skal adskilt fra svarorganet tom linje, hvilket vi gør med følgende kommando "echo.". Dernæst sendes selve svarets brødtekst - dette er et almindeligt html-dokument. I dokumentets brødtekst viser jeg for klarhedens skyld en af miljøvariablerne sendt til os af serveren - "QUERY_STRING", som allerede nævnt med GET-metoden (og det er præcis vores tilfælde), overføres alt i denne variable brugerindtastede data, som vi kan observere i script-svaret. Du har måske bemærket "anførselstegnene er malplacerede" i de sidste 2 linjer i filen, umiddelbart efter "ekko", de er der på grund af bat-filernes specificitet, da du kan se html-tags er omgivet af tegn "<» и «>", samtidig fungerer disse symboler som input/output omdirigering i bat-filer, og derfor kan vi ikke frit bruge dem her.
Jeg anbefaler at lege lidt med sådanne bat-scripts, det kan være meget nyttigt, prøv at se på andre miljøvariabler. Jeg vil sige lidt, afvigende fra emnet, på UNIX-systemer er kommandofortolkersprog meget højt udviklede, og grænsen mellem programmering i et kommandofortolkersprog og programmering i et "rigtigt" programmeringssprog er meget, meget sløret i nogle tilfælde, så simple scripts er ofte skrevet på UNIX-systemer specifikt i kommandofortolkersprog, men Windows-fortolkeren cmd.exe eller, tidligere, command.com er tydeligvis svage til disse formål.
Lad os nu gå videre til det faktiske hovedopgave i denne artikel, til faktisk at skrive et CGI-program i assembler. I princippet, hvis vi tager højde for alt ovenstående om CGI, kan vi drage en konklusion om, hvad CGI-grænsefladen kræver af vores program:
2. Programmet skal være i stand til at skrive til standardoutputstrømmen (stdout) for at kunne overføre resultatet af sit arbejde til serveren;
3. Af de to første punkter følger det, at for at serveren kan sende noget til vores program i stdin, og for at den kan reagere på det i stdout, skal CGI-programmet være en konsolapplikation;
Dette er ganske nok til at skabe en fuldgyldig CGI-applikation.
Lad os starte med det sidste punkt. For at få adgang til miljøvariablerne i en Windows-applikation, bruges API-funktionen "GetEnvironmentStrings", funktionen har ingen argumenter og returnerer en pointer til et array af miljøvariabler (NAME=VALUE) adskilt af nul, arrayet lukkes med et dobbelt nul, når programmet startes af serveren i programmiljøet udover standardvariabler, tilføjes de specifikke CGI-variabler beskrevet ovenfor, når programmet køres fra kommandolinje du vil naturligvis ikke se dem.
For at skrive noget til stdout eller læse fra stdin, skal vi først have håndtagene til disse streams, dette gøres ved hjælp af API-funktionen "GetStdHandle", en af følgende værdier sendes som en funktionsparameter:
STD_INPUT_HANDLE - for stdin (standard input);
STD_OUTPUT_HANDLE - for stdout (standard output);
STD_ERROR_HANDLE - for stderr.
Funktionen returnerer det håndtag, vi har brug for til læse-/skriveoperationer. Den næste ting vi skal gøre er at skrive/læse disse streams. Dette gøres ved normale fillæse/skriveoperationer, dvs. ReadFile og WriteFile. Der er en subtilitet her, du tror måske, at WriteConsole/ReadConsole kan bruges til disse formål, men dette er faktisk sandt for konsoller og det vil fungere fantastisk, resultaterne, ligesom med WriteFile, vil blive udsendt til konsollen, men dette vil fortsætte indtil vi kører vores program som et script på serveren. Dette sker, fordi når vores program startes af serveren, vil de håndtag, der returneres af "GetStdHandle"-funktionen, ikke længere være konsolhåndtag som sådan, de vil være rørhåndtag, hvilket er nødvendigt for at forbinde to applikationer.
Her er et lille eksempel på, hvordan et CGI-program skal se ud i assemblersprog; Jeg tror, det ikke vil være for svært at finde ud af det:>
386 .model flat,stdcall includelib import32.lib .const PAGE_READWRITE = 4h MEM_COMMIT = 1000h MEM_RESERVE = 2000h STD_INPUT_HANDLE = -10 STD_OUTPUT_HANDLE = -11 .data hStdout ? hStdin dd ? hMem dd ? header: db "Content-Type: text/html",13,10,13,10,0 start_html: db "
CGI-programmiljøet ser sådan ud:",13,10,0 for_stdin: db " Programmets STDIN indeholder:
",13,10,0 end_html: db "",13,10,0 nwritten dd ? toscr db 10 dup (32) db " - Filtype",0 .code _start: xor ebx,ebx call GetStdHandle,STD_OUTPUT_HANDLE mov hStdout,eax call GetStdHandle,StHAND_INPmov call h_DIN,INPmov write_stdout, offset header call write_stdout, offset start_html call VirtualAlloc,ebx,1000,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE mov hMem,eax mov edi,eax call GetEnvironmentStringsA mov esi,eax next_symbol, mov al_, mov al, mov al_ : cmpsb jmp kort næste_symbol end_string: mov ,">rb<" add edi,3 cmp byte ptr ,0 jnz next_string inc edi stosb call write_stdout, hMem call write_stdout, offset for_stdin call GetFileSize,,ebx mov edi,hMem call ReadFile,,edi, eax,offset nwritten, ebx add edi, mov byte ptr ,0 call write_stdout, hMem call write_stdout, offset end_html call VirtualFree,hMem call ExitProcess,-1 write_stdout proc bufOffs:dword call lstrlen,bufOffs call WriteFile,,bufOffs,eax,offset nwritten,0 ret write_stdout endp extrn GetEnvironmentStringsA:near extrn GetStdHandle:near extrn ReadFile:near extrn WriteFile:near extrn GetFileSize:near extrn VirtualAlloc:near extrn VirtualFree:near extrn ExitProcess:near extrn lstrlen:near ends end _start
Den eksekverbare fil er bygget med kommandoerne:
tasm32.exe /ml test.asm
tlink32.exe /Tpe /ap /o test.obj
Glem ikke, at programmet skal være et konsolprogram.
Arkiver med programmet.
Du kan kalde dette program ved hjælp af html-formularen beskrevet ovenfor, du skal bare ændre navnet test.bat i formularen til test.exe og kopiere det til /cgi-bin/ tilsvarende, du kan indstille det til POST i anmodningsmetoden , behandler programmet det.
Jeg vil også bemærke, at du kan kalde programmet på en anden måde, du kan oprette en fil i cgi-bin biblioteket, for eksempel test.cgi, med en enkelt linje "#!c:/_path_/test.exe" og kalder det ind forespørgsler, og serveren vil til gengæld læse sin første linje og starte exe-filen; for dette er det nødvendigt, at *.cgi-udvidelsen angives i http-serverindstillingerne som en udvidelse til scripts. Med denne tilgang vil serveren starte vores program med kommandolinjen "test.exe path_to_test.exe", dette har flere fordele - den første er, at den person, der kører vores script, ikke engang vil gætte, hvad scriptet er skrevet i, det andet er måden det sendes til os navnet på filen med vores linje, kan vi f.eks. tilføje alle indstillinger for vores script til denne fil, hvilket forenkler fejlfinding, i øvrigt er det sådan alle tolke fungerer - du kan have bemærket, at der i alle perl/php/etc-programmer er en lignende linje - hvilket indikerer selve kommandofortolkeren. Så når serveren starter et cgi-program, hvis programudvidelsen er registreret som et script i indstillingerne, læser den den første linje i filen, og hvis den viser sig at være i formatet beskrevet ovenfor, starter den programmet angivet i linjen med navnet på denne fil efterfulgt af et mellemrum, lad os sige, at i Perletolken er angivet i linjen; efter at have modtaget en sådan gave, begynder den udførelsen, fordi Kommentaren i Perl er "#" symbolet, så springer den første linje over, og scriptet fortsætter med at blive udført, generelt er det en praktisk ting.
Det er dybest set alt, jeg ville skrive om, jeg ved ikke, hvor nyttigt alt dette vil være for dig, men jeg vil sige, at jeg har en intranetserver, der kører ved hjælp af assembler-scripts. Jeg indrømmer, at der ikke var nogen god grund til at gøre dette, men ikke desto mindre gjorde jeg det i starten blot af æstetiske årsager og en vis modvilje mod at lære pearl/php eller noget andet. MEN jeg afskrækker dig på ingen måde fra at lære Pearl, men tværtimod vil jeg sige, at det er nødvendigt at gøre dette, og endda meget nødvendigt, det indså jeg senere, men jeg tror stadig, at på tungt belastede servere, hvor hastigheden af udførelse, indlæsning og mængden af hukommelse optaget af applikationen spiller en rolle cgi-scripts skrevet i assembler vil tage deres retmæssige plads.