CGI: Tutorial 01: Supplying Dynamic Data to a Web Client
In the early '90s the NCSA released HTTPd 1.0 (a web server), a new concept was
included; CGI. This feature allowed web content to be dynamically generated on
the server. Up-to-date reports of stocks, scores, and weather were possible
with CGI. Other uses include message boards, guest books, or e-stores.
Typically a CGI application will interface with a Mosaic type web browser;
supplying HTML with the data. When the server recieves a request targeting a
CGI program, it will lauch the application. Any data from the client will be
piped to StdIn. The app's StdOut will then be sent back to the client.
Tools Needed
This tutorial is written for FAsm ({http://omega.im.uj.edu.pl/~grysztar/}). If
you wish to assemble the program, you will need FAsm 1.13.4 (or later) or you
can translate it to an assembler supporting 80x86 PE console.
For any CGI testing access to a web server is a must. I recommend Apache 1.3.20
({http://httpd.apache.org/}). For starting out, you can place your assembled
executable into the \Apache\cgi-bin\ directory. For the server name use
"localhost" (excluding the quotes).
Knowledge of HTML (HyperText Markup Language) is usefull. The basics of HTML
are easy to learn. CSS (Cascading Style Sheets) will prove invaluable if you
use a lot of HTML. A list of books is provided at the end of this article.
A Win32 platform. My system consist of Win 98 SE on a Celeron 433 w/ 128MB RAM.
Win 95 - NT should work without issues. A Linux box running WINE shoud also
work for those with a strong stomach.
Win32 API
Since everything a CGI application does is non GUI, the kernal32.dll will
suffice for most projects. Database intensive app's will link to other dll's
to better implement designs.
To access the Standard I/O, will need to use GetStdHandle. Under Win32, StdIO
is not availiable under predefined handles. ReadFile and WriteFile is used to
move data. ReadConsole and WriteConsole will not work; file redirection in not
availiable.
CGI Environment
A CGI program is not required to read data, but it is required to send it.
Client data is availiable on the StdIn. The length is in the CONTENT_LENGTH
environment variable. Also, 255 bytes of the data is in the QUERY_STRING
EnvVar. All out put must start with "Content-Type:" a space, the type, and two
newlines (CrLf). Common types include: "text/plain", "text/html", or
"image/gif". Example output:
Content-Type: text/plain
Hello World. Example of HTTP 1.1 header and body.
If you don't write any data, the web server will report with the error:
"Premature end of script headers". If you really don't want to supply data,
you could just write: "Content-Type: text/plain" and two newlines.
The Example Program
The program I've supplied writes HTML containing the current date and time. It
demonstrates use of API's, HTML, data manipulation.
~~~~~~~~~~~~~~~~~~~|||-------------------[code]-------------------|||
format PE console
entry Start
include '\Asm_Win32\Include\Kernel.inc'
include '\AsmWin32\Include\macro\stdcall.inc'
include '\Asm_Win32\Include\macro\import.inc'
Cr = 0x0D
Lf = 0x0A
;***---------------------------------------------------------------***
section '.code' code readable executable
Start:
pusha ;Save all of the Registers
stdcall [GetStdHandle], STD_OUTPUT_HANDLE ;Retrive the actual handle
mov [StdOut], eax
cmp eax, INVALID_HANDLE_VALUE ;Error with handle
jz Exit
- Get Time
- stdcall [GetSystemTime], Time ;Load SYSTEMTIME with UTC
call Format_Time ;Convert Hex(bin) to ascii
; and Place into HTML
- Write
- stdcall [WriteFile], [StdOut], HTML, HTML._size, HTML.Len, 0
;Write the HTML to StdOut
- Exit
- popa ;Restore all of the Registers
stdcall [ExitProcess], 0
;***-------------------------[Subroutine]--------------------------***
Format_Time:
mov ax, [Time.wYear] ;16b Data
mov edi, HTML.Date_S + 9 ;Ptr to LAST byte of dest
call .ascii ;Convert and place into HTML
mov ax, [Time.wDay]
mov edi, HTML.Date_S + 4
call .ascii
mov ax, [Time.wMonth]
mov edi, HTML.Date_S + 1
call .ascii
mov edi, HTML.Day_S ;Destination Ptr
mov esi, Day.Wk ;Source Ptr (Array of Days)
xor eax, eax
mov ax, [Time.wDayOfWeek] ;0 <= eax < 7
add esi, eax ;esi =+ eax * 3
add esi, eax ; Indexes the Array
add esi, eax
mov ecx, 3 ;3B per Day String
cld ;Copy Left to Right
rep ; (esi++, edi++)
movsb
mov ax, [Time.wHour]
cmp al, 13 ;Check for PM
jl .wHour
sub al, 12 ;Correct Hour
mov [HTML.Time_S + 9], 'P' ; AM -> PM
.wHour:
mov edi, HTML.Time_S + 1
call .ascii
mov ax, [Time.wMinute]
mov edi, HTML.Time_S + 4
call .ascii
mov ax, [Time.wSecond]
mov edi, HTML.Time_S + 7
call .ascii
ret
;***----------------------[Import Table / IAT]---------------------***
.ascii:
std ;String OPs Right to Left
cmp ax, 10 ;Single Digit?
jl .onex10
and ah, ah ;Only Two Digits
jz .twox16
mov bh, 10 ;Reduce 3x16 to 2x16
div bh ; so that AAM can be used
or ah, 0x30 ;BCD -> ASCII
mov [edi], ah
dec edi
.twox16:
aam ; AH / 10 = AH r AL
or al, 0x30 ;BCD -> ASCII
stosb
mov al, ah
cmp ah, 9
jg .twox16
.onex10:
or al, 0x30
stosb ;Copy Last/Only Digit to Mem
ret
;***--------------------[Data used by this App]--------------------***
section '.data' data readable writeable
StdIn dd 0 ;Standard I/O Handles
StdOut dd 0
- HTML
- db 'Content-type: text/html', Cr, Lf, Cr, Lf
db '<html><head><title>Hello World</title></head>', Cr, Lf
db '<body bgcolor=Black text=Cyan><h1>Hello World</h1>', Cr, Lf
db '<h2><font color=Lime>', Cr, Lf
db 'This HTML is dynamicly generated by a PE console Application writen in'
db '80x86 Assembler</font></h2>', Cr, Lf
db '<h2><font color=Red>It is: </font><font color=Blue>'
.Day_S db 'WkD '
.Date_S db ' 0/00/0000</font> <font color=Magenta>'
.Time_S db ' 0:00:00 AM</font> <font color=Lime>UTC</font></h2>', Cr, Lf
db '</body></html>', Cr, Lf
HTML._size = $ - HTML - 1
HTML.Len dd 0 ;Number of bytes actually wrote
Time SYSTEMTIME
Day.Wk db 'SunMonTueWedThuFriSat'
;***----------------------[Import Table / IAT]---------------------***
section '.idata' import data readable writeable
library kernel, 'KERNEL32.DLL'
- kernel
- import GetModuleHandle, 'GetModuleHandleA',\
GetCommandLine, 'GetCommandLineA',\
GetSystemTime, 'GetSystemTime',\
GetEnvVar, 'GetEnvironmentVariableA',\
GetStdHandle, 'GetStdHandle',\
CreateFile, 'CreateFileA',\
ReadFile, 'ReadFile',\
WriteFile, 'WriteFile',\
CloseHandle, 'CloseHandle',\
ExitProcess, 'ExitProcess'
__________________|||-------------------[/code]-------------------|||
How to Run
You can run this example from the command line since it requires no client
data. You can also pipe the data into an html doc and open with IE:
Main > Text.html
For the real CGI, place Main.exe into the cgi-bin directory, launch Apache, and
type "localhost/cgi-bin/Main.exe" in the address box of IE.
References
SAMS Teach Yourself CGI in 24 Hours
SAMS 2000 $24.99US
Rafe Colburn ISBN: 0-672-31880-6
CGI by Example
QUE 1996 $34.99US
Robert Niles & Jeffry Dwight ISBN: 0-7897-0877-9
HTML in Plain English - 2nd Edition
MIS Press 1998 $19.95US
Sandra E. Eddy ISBN: 1-55828-587-3
Cascading Sytle Sheets - The Definitive Guide
O'Reilly 2000 $34.95US
Eric A. Meyer ISBN: 1-56592-622-6
Win32 Programming Reference (Win32 API Help file)
Microsoft 1990-1995 Free
{http://win32asm.rxsp.com/files/win32api.zip}
Contact
{
This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
}
|