; ; HTTPC.ASM ; ; Compile with FASM for Menuet ( v1.40 for DOS ) ; ; This program implements a very simple web browser ; ; Version 0.4 2nd December 2003 Mike Hibbett ; Enabled lowercase/uppcase characters in URL ; Version 0.3 30th November 2003 Mike Hibbett ; Fixed bug with tcp socket opne - uses unique port ; Version 0.2 27th November 2003 Mike Hibbett ; Added user entry of url, and implements url -> IP address ; resolution through DNS ; ; Version 0.1 Ville Mikael Turjanmaa ; Original version ; Enabling debugging puts stuff to the debug board DEBUGGING_ENABLED equ 1 DEBUGGING_DISABLED equ 0 DEBUGGING_STATE equ DEBUGGING_DISABLED use32 org 0x0 db 'MENUET01' ; header dd 0x01 ; header version dd START ; entry point dd I_END ; image size dd 0x100000 ; required memory dd 0x100000 ; esp dd 0x0 , 0x0 ; I_Param , I_Path include 'lang.inc' include 'macros.inc' ;include "DEBUG.INC" URLMAXLEN equ 50 ; maximum length of url string ; Memory usage ; webpage source file at 0x10000 ; decoded text page at 0x20000 ; text attribute 0x30000 (1 = normal, 2 = bold, 128+ = link) START: ; start of execution ;dps <"Program started",13,10> mov eax,40 ; Report events mov ebx,10000111b ; Stack 8 + defaults mcall red: ; redraw call draw_window still: mov eax,23 ; wait here for event mov ebx,1 mcall cmp eax,1 ; redraw request ? je red cmp eax,2 ; key in buffer ? je key cmp eax,3 ; button in buffer ? je button ; Get the web page data from the remote server call read_incoming_data mov eax,[status] mov [prev_status],eax mov eax,53 mov ebx,6 mov ecx,[socket] mcall mov [status],eax cmp [prev_status],4 jge no_send cmp [status],4 jne no_send mov [onoff],1 call send_request no_send: call print_status cmp [prev_status],4 jne no_close cmp [status],4 ; connection closed by server jbe no_close ; respond to connection close command ; draw page call read_incoming_data mov eax,53 mov ebx,8 mov ecx,[socket] mcall call draw_page mov [onoff],0 no_close: jmp still key: ; key mov eax,2 ; just read it and ignore mcall shr eax,8 cmp eax,184 jne no_down cmp [display_from],25 jb no_down sub [display_from],25 call display_page no_down: cmp eax,183 jne no_up add [display_from],25 call display_page no_up: jmp still button: ; button ;dps <"Button pressed",13,10> mov eax,17 ; get id mcall cmp ah,1 ; button id=1 ? jne noclose ;dps "Closing socket before exit... " mov eax, 53 mov ebx, 8 mov ecx, [socket] mcall ;dpd eax ;dps <13,10> exit: or eax,-1 ; close this program mcall noclose: cmp ah,31 jne noup sub [display_from],20 call display_page jmp still noup: cmp ah,32 jne nodown add [display_from],20 call display_page jmp still nodown: cmp ah, 10 ; Enter url jne nourl mov [addr],dword document_user mov [ya],dword 38 mov [len],dword URLMAXLEN mov ecx,[len] mov edi,[addr] mov al,' ' rep stosb call print_text mov edi,[addr] f11: mov eax,10 mcall cmp eax,2 ; key? jz fbu jmp still fbu: mov eax,2 mcall ; get key shr eax,8 cmp eax,8 jnz nobs cmp edi,[addr] jz f11 sub edi,1 mov [edi],byte ' ' call print_text jmp f11 nobs: cmp eax, dword 10 je retkey cmp eax, dword 13 je retkey cmp eax,dword 31 jbe f11 ; Removed in v0.4 ; cmp eax,dword 95 ; jb keyok ; sub eax,32 keyok: mov [edi],al call print_text add edi,1 mov esi,[addr] add esi,URLMAXLEN cmp esi,edi jnz f11 jmp still retkey: mov ah, 22 ; start load nourl: call socket_commands ; opens or closes the connection jmp still ;**************************************************************************** ; Function ; send_request ; ; Description ; Transmits the GET request to the server. ; This is done as GET then URL then HTTP/1.0',13,10,13,10 in 3 packets ; ;**************************************************************************** send_request: pusha mov eax,53 ; 'GET ' mov ebx,7 mov ecx,[socket] mov edx,4 mov esi,string0 mcall mov edx,0 next_edx: ; Determine the length of the url to send in the GET request inc edx cmp [edx+document],byte ' ' jne next_edx mov eax,53 ; document_user mov ebx,7 mov ecx,[socket] mov esi,document mcall mov eax,53 ; ' HTTP/1.0 .. ' mov ebx,7 mov ecx,[socket] mov edx,stringh_end-stringh mov esi,stringh mcall popa ret ;**************************************************************************** ; Function ; print_status ; ; Description ; displays the socket/data received status information ; ;**************************************************************************** print_status: pusha mov eax,26 mov ebx,9 mcall cmp eax,[nextupdate] jb status_return add eax,25 mov [nextupdate],eax mov eax,13 mov ebx,5*65536+100 mov ecx,[winys] shl ecx,16 add ecx,-18*65536+10 mov edx,0xffffff mcall mov eax,47 mov ebx,3*65536 mov ecx,[status] mov edx,12*65536-18 add edx,[winys] mov esi,0x000000 mcall mov eax,47 mov ebx,6*65536 mov ecx,[pos] mov edx,40*65536-18 add edx,[winys] mov esi,0x000000 mcall status_return: popa ret ;**************************************************************************** ; Function ; read_incoming_data ; ; Description ; receive the web page from the server, storing it without processing ; ;**************************************************************************** read_incoming_data: cmp [onoff],1 je rid ret rid: mov ecx,-1 newbyteread: mov eax, 53 mov ebx, 2 mov ecx, [socket] mcall cmp eax,0 je no_more_data read_more: mov eax, 53 mov ebx, 3 mov ecx, [socket] mcall yesm: inc [pos] mov ecx,[pos] mov [0x10000+ecx],bl call print_status cmp eax,0 jne read_more mov eax,5 mov ebx,50 mcall jmp newbyteread no_more_data: ret ;**************************************************************************** ; Function ; draw_page ; ; Description ; parses the web page data, storing displayable data at 0x20000 ; and attributes at 0x30000. It then calls display_page to render ; the data ; ;**************************************************************************** draw_page: pusha mov esi,0 mov [command_on_off],0 newlettercheck: movzx eax,byte [esi+0x10000] cmp al,'<' jne no_c_on mov [command_on_off],1 no_c_on: cmp al,'>' jne no_c_off mov [command_on_off],0 no_c_off: cmp [command_on_off],0 je no_lower_case cmp eax,96 jg no_lower_case cmp eax,65 jb no_lower_case add eax,32 no_lower_case: mov [esi+0x10000],al inc esi cmp esi,[pos] jbe newlettercheck mov edi,0x30000 mov ecx,0x10000 mov al,0 cld rep stosb mov [text_type],1 mov [command_on_off],0 mov esi,0 mov ecx,[pos] ; search for double lf find_dlf: cmp [0x10000+esi-4],dword 0x0d0a0d0a je found_dlf cmp [0x10000+esi-4],dword 0x0a0d0a0d je found_dlf cmp [0x10000+esi-2],word 0x0d0d je found_dlf cmp [0x10000+esi-2],word 0x0a0a je found_dlf cmp esi,5500 je found_dlf inc esi jmp find_dlf found_dlf: newbyte: mov al,[esi+0x10000] cmp al,'<' jne no_command_on mov [command_on_off],1 no_command_on: cmp al,'>' jne no_command_off mov [command_on_off],0 jmp byte_done no_command_off: mov eax,[esi+0x10000] ; cmp ax,'->' jne no_com2_end mov [com2],0 inc esi jmp byte_done no_com2_end: mov eax,[esi+0x10000] ;