; version: 0.5 ; last update: 07/10/2010 ; written by: Marat Zakiyanov aka Mario79, aka Mario ; changes: reducing the size of the binary code, ; program uses far less memory while running ; (>0x7000, the old version used >0x100000), ; process only net event at start with parameter ;----------------------------------------------------------- ; version 0.3 -0.4 ; written by: CleverMouse ; ;----------------------------------------------------------- ; wget 0.2 by barsuk ; based on Menuet Httpc ; Enabling debugging puts stuff to the debug board DEBUGGING_ENABLED equ 1 DEBUGGING_DISABLED equ 0 DEBUGGING_STATE equ DEBUGGING_ENABLED use32 org 0x0 db 'MENUET01' ; header dd 0x01 ; header version dd START ; entry point dd IM_END ; image size dd I_END ;0x100000 ; required memory dd stacktop ; esp dd params ; I_PARAM dd 0x0 ; I_Path include 'lang.inc' include '../../../macros.inc' include "../../../proc32.inc" include "dll.inc" include "debug.inc" URLMAXLEN equ 256 ; maximum length of url string primary_buffer_size equ 4096 ; Memory usage ; webpage headers at buf_headers START: ; start of execution ;dps <"Program started",13,10> ; prepare webAddr area mov al,' ' mov edi,webAddr mov ecx,URLMAXLEN cld rep stosb xor eax,eax stosb ; prepare document area mov al,'/' mov edi,document cld stosb mov al,' ' mov ecx,URLMAXLEN-1 rep stosb ; create local heap mcall 68,11 call load_settings cmp [params],byte 0 jz prepare_event ;red mcall 40,10000000b ; only net event!!! ; we have an url mov edi,document_user mov al,' ' mov ecx,URLMAXLEN rep stosb mov esi,params mov edi,document_user .copy_param: mov al,[esi] cmp al,0 jz .done cmp al,' ' jz .done_inc mov [edi],al inc esi inc edi jmp .copy_param .done_inc: ; url is followed by shared memory name. inc esi .done: mov [shared_name],esi mov ah,22 ; strange way to tell that socket should be opened... call socket_commands jmp still prepare_event: ; Report events ; Stack 8 + defaults mcall 40,10000111b red: ; redraw call draw_window still: mcall 23,1 ; wait here for event 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 mcall 53,6,[socket] 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 mcall 53,8,[socket] call draw_page mov [onoff],0 no_close: jmp still key: ; key mcall 2 ; just read it and ignore 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> mcall 17 ; get id cmp ah,26 je save cmp ah,1 ; button id=1 ? jne noclose ; dps "Closing socket before exit... " close_end_exit: ;dpd eax ;dps <13,10> exit: or eax,-1 ; close this program mcall save: dps "saving" newline mcall 70,fileinfo ;pregs jmp still 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,URLMAXLEN mov edi,[addr] mov al,' ' rep stosb call print_text mov edi,[addr] f11: mcall 10 cmp eax,2 ; key? jz fbu jmp still fbu: mcall 2 ; 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,10 je retkey cmp eax,13 je retkey cmp eax,31 jbe f11 ; Removed in v0.4 ; cmp eax,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.1',13,10,13,10 in 3 packets ; ;**************************************************************************** send_request: pusha mov esi,string0 mov edi,request movsd ; If proxy is used, make absolute URI - prepend http:// cmp [proxyAddr],byte 0 jz .noproxy mov dword [edi],'http' mov [edi+4],byte ':' mov [edi+5],word '//' add edi,7 mov esi,webAddr .copy_host_loop: lodsb cmp al,' ' jz .noproxy stosb jmp .copy_host_loop .noproxy: xor edx,edx ; 0 .next_edx: ; Determine the length of the url to send in the GET request mov al,[edx+document] cmp al,' ' je .document_done mov [edi],al inc edi inc edx jmp .next_edx .document_done: mov esi,stringh mov ecx,stringh_end-stringh rep movsb xor edx,edx ; 0 .webaddr_next: mov al,[webAddr + edx] cmp al,' ' je .webaddr_done mov [edi],al inc edi inc edx jmp .webaddr_next .webaddr_done: cmp [proxyUser],byte 0 jz @f call append_proxy_auth_header @@: mov esi,connclose mov ecx,connclose_end-connclose rep movsb pusha mov eax,63 mov ebx,1 mov edx,request @@: mov cl,[edx] cmp edx,edi jz @f mcall inc edx jmp @b @@: popa mov edx,edi sub edx,request ;;;;now write \r\nConnection: Close \r\n\r\n mcall 53,7,[socket],,request ;' HTTP/1.1 .. ' popa ret ;**************************************************************************** ; Function ; print_status ; ; Description ; displays the socket/data received status information ; ;**************************************************************************** print_status: pusha mcall 26,9 cmp eax,[nextupdate] jb status_return add eax,25 mov [nextupdate],eax mov ecx,[winys] shl ecx,16 add ecx,-18*65536+10 mcall 13,<5,100>,,0xffffff mov edx,12*65536-18 add edx,[winys] xor esi,esi mcall 47,<3,0>,[status],, mov edx,40*65536-18 add edx,[winys] mcall ,<6,0>,[pos] 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: push esi push edi dps "rid" newline newbyteread: ;call print_status mcall 53,2,[socket] cmp eax,0 je no_more_data mcall 53,11,[socket],primary_buf,primary_buffer_size ;dps "part " ;dph eax ;newline mov edi,[pos] add [pos],eax push eax mcall 68,20,[pos],[buf_ptr] mov [buf_ptr],eax add edi,eax mov esi,primary_buf pop ecx ; number of recently read bytes lea edx,[ecx - 3] rep movsb no_more_data: mcall 53,6,[socket] cmp eax,4 jne no_more_data.finish jmp newbyteread .finish: ;dps "finish " ;pregs call parse_result mov ecx,[shared_name] cmp [ecx],byte 0 jnz save_in_shared mcall 70,fileinfo ;dps "saving " ;pregs ; jmp close_end_exit pop edi pop esi ; if called from command line, then exit cmp [params],byte 0 jnz exit ret save_in_shared: mov esi,1 ; SHM_OPEN+SHM_WRITE mcall 68,22 test eax,eax jz save_in_shared_done sub edx,4 jbe save_in_shared_done mov ecx,[final_size] cmp ecx,edx jb @f mov ecx,edx @@: mov [eax],ecx lea edi,[eax+4] mov esi,[final_buffer] mov edx,ecx shr ecx,2 rep movsd mov ecx,edx and ecx,3 rep movsb save_in_shared_done: pop edi pop esi jmp exit ; this function cuts header, and removes chunk sizes if doc is chunked ; in: buf_ptr, pos; out: buf_ptr, pos. parse_result: ; close socket mcall 53,8,[socket] dps "close socket: " dph eax newline mov edi,[buf_ptr] mov edx,[pos] mov [buf_size],edx ; mcall 70,fileinfo_tmp dps "pos = " dph edx newline ; first, find end of headers .next_byte: cmp [edi],dword 0x0d0a0d0a ; мне лень читать стандарт, пусть будут оба варианта je .end_of_headers cmp [edi],dword 0x0a0d0a0d je .end_of_headers inc edi dec edx jne .next_byte ; no end of headers. it's an error. let client see all those headers. ret .end_of_headers: ; here we look at headers and search content-length or transfer-encoding headers ;dps "eoh " ;newline sub edi,[buf_ptr] add edi,3 mov [body_pos],edi ; store position where document body starts mov [is_chunked],0 ; find content-length in headers ; not good method, but should work for 'Content-Length:' mov esi,[buf_ptr] mov edi,s_contentlength mov ebx,[body_pos] xor edx,edx ; 0 .cl_next: mov al,[esi] cmp al,[edi + edx] jne .cl_fail inc edx cmp edx,len_contentlength je .cl_found jmp .cl_incr .cl_fail: xor edx,edx ; 0 .cl_incr: inc esi dec ebx je .cl_error jmp .cl_next .cl_error: ;pregs ;newline ;dph esi ;dps " content-length not found " ; find 'chunked' ; да, я копирую код, это ужасно, но мне хочется, чтобы поскорее заработало ; а там уж отрефакторю mov esi,[buf_ptr] mov edi,s_chunked mov ebx,[body_pos] xor edx,edx ; 0 .ch_next: mov al,[esi] cmp al,[edi + edx] jne .ch_fail inc edx cmp edx,len_chunked je .ch_found jmp .ch_incr .ch_fail: xor edx,edx ; 0 .ch_incr: inc esi dec ebx je .ch_error jmp .ch_next .ch_error: ; if neither of the 2 headers is found, it's an error ;dps "transfer-encoding: chunked not found " mov eax,[pos] sub eax,[body_pos] jmp .write_final_size .ch_found: mov [is_chunked],1 mov eax,[body_pos] add eax,[buf_ptr] sub eax,2 mov [prev_chunk_end],eax jmp parse_chunks .cl_found: call read_number ; eax = number from *esi inc eax ; bugfix :) .write_final_size: mov [final_size],eax ; if this works, i will b very happy... mov ebx,[pos] ; we well check if it is right sub ebx,[body_pos] ;dps "check cl eax==ebx " ;pregs ; everything is ok, so we return mov eax,[body_pos] mov ebx,[buf_ptr] add ebx,eax mov [final_buffer],ebx ; mov ebx,[pos] ; sub ebx,eax ; mov [final_size],ebx ret parse_chunks: ;dps "parse chunks" ;newline ; we have to look through the data and remove sizes of chunks we see ; 1. read size of next chunk ; 2. if 0, it's end. if not, continue. ; 3. make a good buffer and copy a chunk there xor eax,eax mov [final_buffer],eax ; 0 mov [final_size],eax ; 0 .read_size: mov eax,[prev_chunk_end] mov ebx,eax sub ebx,[buf_ptr] mov edx,eax ;dps "rs " ;pregs cmp ebx,[pos] jae chunks_end ; not good call read_hex ; in: eax=pointer to text. out:eax=hex number,ebx=end of text. cmp eax,0 jz chunks_end add ebx,1 mov edx,ebx ; edx = size of size of chunk add ebx,eax mov [prev_chunk_end],ebx ;dps "sz " ;pregs ; do copying: from buf_ptr+edx to final_buffer+prev_final_size count eax ; realloc final buffer push eax push edx push dword [final_size] add [final_size],eax mcall 68,20,[final_size],[final_buffer] mov [final_buffer],eax ;dps "re " ;pregs pop edi pop esi pop ecx ; add [pos],ecx add edi,[final_buffer] ;dps "cp " ;pregs rep movsb jmp .read_size chunks_end: ; free old buffer dps "chunks end" newline mcall 68,13,[buf_ptr] ; done! ret ; reads content-length from [edi+ecx], result in eax read_number: push ebx xor eax,eax xor ebx,ebx .next: mov bl,[esi] ;dph ebx cmp bl,'0' jb .not_number cmp bl,'9' ja .not_number sub bl,'0' shl eax,1 lea eax,[eax + eax * 4] ; eax *= 10 add eax,ebx .not_number: cmp bl,13 jz .done inc esi jmp .next .done: pop ebx ;newline ;dps "strtoint eax " ;pregs ret ; reads hex from eax,result in eax,end of text in ebx read_hex: add eax,2 mov ebx,eax mov eax,[ebx] mov [deba],eax ; pushf ; pushad ; mov edx,deba ; call debug_outstr ; popad ; popf xor eax,eax xor ecx,ecx .next: mov cl,[ebx] inc ebx cmp cl,0x0d jz .done ;dph ebx or cl,0x20 sub cl,'0' jb .bad cmp cl,0x9 jbe .adding sub cl,'a'-'0'-10 cmp cl,0x0a jb .bad cmp cl,0x0f ja .bad .adding: shl eax,4 or eax,ecx ; jmp .not_number ;.bad: .bad: jmp .next .done: ;newline ;dps "hextoint eax " ;pregs 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: ret ;**************************************************************************** ; Function ; linefeed ; ; Description ; ; ;**************************************************************************** linefeed: ret ;**************************************************************************** ; Function ; display_page ; ; Description ; Renders the text decoded by draw_page ; ;**************************************************************************** display_page: ret ;**************************************************************************** ; Function ; socket_commands ; ; Description ; opens or closes the socket ; ;**************************************************************************** socket_commands: cmp ah,22 ; open socket jnz tst3 dps "opening socket" newline ; Clear all page memory xor eax,eax mov [prev_chunk_end],eax ; 0 cmp [buf_ptr],eax ; 0 jz no_free mcall 68,13,[buf_ptr] ; free buffer no_free: xor eax,eax mov [buf_size],eax ; 0 ; Parse the entered url call parse_url ; Get a free port number mov ecx,1000 ; local port starting at 1000 getlp1: inc ecx push ecx mcall 53,9 pop ecx cmp eax,0 ; is this local port in use? jz getlp1 ; yes - so try next mov edx,80 cmp [proxyAddr],byte 0 jz sc000 mov edx,[proxyPort] sc000: mcall 53,5,,,[server_ip],1 mov [socket],eax mov [pagexs],80 push eax xor eax,eax ; 0 mov [pos],eax mov [pagex],eax mov [pagey],eax mov [command_on_off],eax mov [is_body],eax pop eax ret tst3: cmp ah,24 ; close socket jnz no_24 mcall 53,8,[socket] call draw_page no_24: ret ;**************************************************************************** ; Function ; parse_url ; ; Description ; parses the full url typed in by the user into a web address ( that ; can be turned into an IP address by DNS ) and the page to display ; DNS will be used to translate the web address into an IP address, if ; needed. ; url is at document_user and will be space terminated. ; web address goes to webAddr and is space terminated. ; ip address goes to server_ip ; page goes to document and is space terminated. ; ; Supported formats: ; address ; is optional, removed and ignored - only http supported ;
is required. It can be an ip address or web address ; is optional and must start with a leading / character ; ;**************************************************************************** parse_url: ; First, reset destination variables cld mov al,' ' mov edi,document mov ecx,URLMAXLEN rep stosb mov edi,webAddr mov ecx,URLMAXLEN rep stosb mov al,'/' mov [document],al mov esi,document_user ; remove any leading protocol text mov ecx,URLMAXLEN mov ax,'//' pu_000: cmp [esi],byte ' ' ; end of text? je pu_002 ; yep, so not found cmp [esi],ax je pu_001 ; Found it, so esi+2 is start inc esi loop pu_000 pu_002: ; not found, so reset esi to start mov esi,document_user-2 pu_001: add esi,2 mov ebx,esi ; save address of start of web address mov edi,document_user + URLMAXLEN ; end of string ; look for page delimiter - it's a '/' character pu_003: cmp [esi],byte ' ' ; end of text? je pu_004 ; yep, so none found cmp esi,edi ; end of string? je pu_004 ; yep, so none found cmp [esi],byte '/' ; delimiter? je pu_005 ; yep - process it inc esi jmp pu_003 pu_005: ; copy page to document address ; esi = delimiter push esi mov ecx,edi ; end of document_user mov edi,document cld pu_006: movsb cmp esi,ecx je pu_007 ; end of string? cmp [esi],byte ' ' ; end of text ; je pu_007 ; дзен-ассемблер ; jmp pu_006 ; не надо плодить сущности по напрасну jne pu_006 pu_007: pop esi ; point esi to '/' delimiter pu_004: ; copy web address to webAddr ; start in ebx,end in esi-1 mov ecx,esi mov esi,ebx mov edi,webAddr cld pu_008: movsb cmp esi,ecx ; je pu_009 ; дзен-ассемблер ; jmp pu_008 ; не надо плодить сущности по напрасну jne pu_008 pu_009: ; For debugging, display resulting strings if DEBUGGING_STATE = DEBUGGING_ENABLED mov esi,document_user call debug_print_string mov esi,webAddr call debug_print_string mov esi,document call debug_print_string end if ; Look up the ip address, or was it specified? mov al,[proxyAddr] cmp al,0 jnz pu_015 mov al,[webAddr] pu_015: cmp al,'0' jb pu_010 ; Resolve address cmp al,'9' ja pu_010 ; Resolve address if DEBUGGING_STATE = DEBUGGING_ENABLED mov esi,str2 ; print gotip call debug_print_string end if ; Convert address ; If proxy is given, get proxy address instead of server mov esi,proxyAddr-1 cmp byte [esi+1],0 jnz pu_020 mov esi,webAddr-1 pu_020: mov edi,server_ip xor eax,eax ip1: inc esi cmp [esi],byte '0' jb ip2 cmp [esi],byte '9' jg ip2 imul eax,10 movzx ebx,byte [esi] sub ebx,48 add eax,ebx jmp ip1 ip2: mov [edi],al xor eax,eax inc edi cmp edi,server_ip+3 jbe ip1 jmp pu_011 pu_010: if DEBUGGING_STATE = DEBUGGING_ENABLED mov esi,str1 ; print resolving call debug_print_string end if ; Resolve Address call translateData ; Convert domain & DNS IP address call resolveDomain ; get ip address if DEBUGGING_STATE = DEBUGGING_ENABLED mov esi,str3 call debug_print_string end if pu_011: ; Done ret ;*************************************************************************** ; Function ; translateData ; ; Description ; Coverts the domain name and DNS IP address typed in by the user into ; a format suitable for the IP layer. ; ; The ename, in query, is converted and stored in dnsMsg ; ;*************************************************************************** translateData: ; first, get the IP address of the DNS server ; Then, build up the request string. ; Build the request string mov eax,0x00010100 mov [dnsMsg],eax mov eax,0x00000100 mov [dnsMsg+4],eax mov eax,0x00000000 mov [dnsMsg+8],eax ; domain name goes in at dnsMsg+12 mov esi,dnsMsg +12 ;location of label length mov edi,dnsMsg + 13 ;label start mov edx,proxyAddr cmp byte [edx],0 jnz td000 mov edx,webAddr td000: mov ecx,12 ; total string length so far td002: mov [esi],byte 0 inc ecx td0021: mov al,[edx] cmp al,' ' je td001 ; we have finished the string translation cmp al,0 je td001 cmp al,'.' ; we have finished the label je td004 inc byte [esi] inc ecx mov [edi],al inc edi inc edx jmp td0021 td004: mov esi,edi inc edi inc edx jmp td002 ; write label len + label text td001: mov [edi],byte 0 inc ecx inc edi mov [edi],dword 0x01000100 add ecx,4 mov [dnsMsgLen],ecx ret ;*************************************************************************** ; Function ; resolveDomain ; ; Description ; Sends a question to the dns server ; works out the IP address from the response from the DNS server ; ;*************************************************************************** resolveDomain: ; Get a free port number mov ecx,1000 ; local port starting at 1000 getlp: inc ecx push ecx mcall 53,9 pop ecx cmp eax,0 ; is this local port in use? jz getlp ; yes - so try next ; Get DNS IP mcall 52,13 mov esi,eax ; First, open socket mov edx,53 ; remote port - dns ; mov esi,dword [dns_ip] xor ebx,ebx ; 0 mcall 53 mov [socketNum],eax ; write to socket ( request DNS lookup ) mcall 53,4,[socketNum],[dnsMsgLen],dnsMsg ; Setup the DNS response buffer mov eax,dnsMsg mov [dnsMsgLen],eax ; now, we wait for ; UI redraw ; UI close ; or data from remote ctr001: mcall 10 ; wait here for event cmp eax,1 ; redraw request ? je ctr003 cmp eax,2 ; key in buffer ? je ctr004 cmp eax,3 ; button in buffer ? je ctr005 ; Any data in the UDP receive buffer? mcall 53,2,[socketNum] cmp eax,0 je ctr001 ; we have data - this will be the response ctr002: mcall 53,3,[socketNum] ; read byte - block (high byte) ; Store the data in the response buffer mov eax,[dnsMsgLen] mov [eax],bl inc dword [dnsMsgLen] mcall 53,2,[socketNum] ; any more data? cmp eax,0 jne ctr002 ; yes, so get it ; close socket mcall 53,1,[socketNum] mov [socketNum],dword 0xFFFF ; Now parse the message to get the host IP ; Man, this is complicated. It's described in ; RFC 1035 if DEBUGGING_STATE = DEBUGGING_ENABLED mov esi,str4 call debug_print_string end if ; 1) Validate that we have an answer with > 0 responses ; 2) Find the answer record with TYPE 0001 ( host IP ) ; 3) Finally, copy the IP address to the display ; Note: The response is in dnsMsg ; The end of the buffer is pointed to by [dnsMsgLen] ; Clear the IP address text mov [server_ip],dword 0 mov esi,dnsMsg ; Is this a response to my question? mov al,[esi+2] and al,0x80 cmp al,0x80 jne ctr002a ; Were there any errors? mov al,[esi+3] and al,0x0F cmp al,0x00 jne ctr002a ; Is there ( at least 1 ) answer? mov ax,[esi+6] cmp ax,0x00 je ctr002a ; Header valdated. Scan through and get my answer if DEBUGGING_STATE = DEBUGGING_ENABLED pusha mov esi,str4 call debug_print_string popa end if add esi,12 ; Skip to the question field ; Skip through the question field call skipName add esi,4 ; skip past the questions qtype, qclass ctr002z: ; Now at the answer. There may be several answers, ; find the right one ( TYPE = 0x0001 ) call skipName mov ax,[esi] cmp ax,0x0100 ; Is this the IP address answer? jne ctr002c ; Yes! Point esi to the first byte of the IP address add esi,10 mov eax,[esi] mov [server_ip],eax ret ctr002c: ; Skip through the answer, move to the next add esi,8 movzx eax,byte [esi+1] mov ah,[esi] add esi,eax add esi,2 ; Have we reached the end of the msg? ; This is an error condition, should not happen cmp esi,[dnsMsgLen] jl ctr002z ; Check next answer jmp ctr002a ; abort ctr002a: jmp ctr001 ctr003: ; redraw call draw_window jmp ctr001 ctr004: ; key mcall 2 ; just read it and ignore jmp ctr001 ctr005: ; button mcall 17 ; get id mov dl,ah ; close socket mcall 53,1,[socketNum] cmp dl,1 je exit mov [socketNum],dword 0xFFFF mov [server_ip],dword 0 ret ;*************************************************************************** ; Function ; skipName ; ; Description ; Increment esi to the first byte past the name field ; Names may use compressed labels. Normally do. ; RFC 1035 page 30 gives details ; ;*************************************************************************** skipName: mov al,[esi] cmp al,0 je sn_exit and al,0xc0 cmp al,0xc0 je sn001 movzx eax,byte [esi] inc eax add esi,eax jmp skipName sn001: add esi,2 ; A pointer is always at the end ret sn_exit: inc esi ret ;*************************************************************************** ; Function ; load_settings ; ; Description ; Load settings from configuration file network.ini ; ;*************************************************************************** load_settings: stdcall dll.Load,@IMPORT test eax,eax jnz ls001 invoke ini.get_str,inifile,sec_proxy,key_proxy,proxyAddr,256,proxyAddr invoke ini.get_int,inifile,sec_proxy,key_proxyport,80 mov [proxyPort],eax invoke ini.get_str,inifile,sec_proxy,key_user, proxyUser,256,proxyUser invoke ini.get_str,inifile,sec_proxy,key_password,proxyPassword,256,proxyPassword ls001: ret ;*************************************************************************** ; Function ; append_proxy_auth_header ; ; Description ; Append header to HTTP request for proxy authentification ; ;*************************************************************************** append_proxy_auth_header: mov esi,proxy_auth_basic mov ecx,proxy_auth_basic_end - proxy_auth_basic rep movsb ; base64-encode string : mov esi,proxyUser apah000: lodsb test al,al jz apah001 call encode_base64_byte jmp apah000 apah001: mov al,':' call encode_base64_byte mov esi,proxyPassword apah002: lodsb test al,al jz apah003 call encode_base64_byte jmp apah002 apah003: call encode_base64_final ret encode_base64_byte: inc ecx shl edx,8 mov dl,al cmp ecx,3 je ebb001 ret ebb001: shl edx,8 inc ecx ebb002: rol edx,6 xor eax,eax xchg al,dl mov al,[base64_table+eax] stosb loop ebb002 ret encode_base64_final: mov al,0 test ecx,ecx jz ebf000 call encode_base64_byte test ecx,ecx jz ebf001 call encode_base64_byte mov byte [edi-2],'=' ebf001: mov byte [edi-1],'=' ebf000: ret if DEBUGGING_STATE = DEBUGGING_ENABLED ;**************************************************************************** ; Function ; debug_print_string ; ; Description ; prints a string to the debug board, in quotes ; ; esi holds ptr to msg to display, which is space or 0 terminated ; ; Nothing preserved; I'm assuming a pusha/popa is done before calling ; ;**************************************************************************** debug_print_string: push esi mov cl,'"' mcall 63,1 pop esi dps_000: mov cl,[esi] cmp cl,0 je dps_exit cmp cl,' ' je dps_exit jmp dps_001 dps_exit: mov cl,'"' mcall 63,1 mov cl,13 mcall mov cl,10 mcall ret dps_001: push esi mcall 63,1 pop esi inc esi jmp dps_000 end if ;**************************************************************************** ; Function ; print_text ; ; Description ; display the url (full path) text ; ;**************************************************************************** print_text: ; Draw a bar to blank out previous text mov ebx,30*65536+URLMAXLEN*6 ; 50 should really be [len] and 103 [xa] mov ecx,[ya] shl ecx,16 mov cx,9 mcall 13,,,0xFFFFFF ; write text mov ebx,30*65536 add ebx,[ya] xor ecx,ecx mcall 4,,,[addr],URLMAXLEN ret ; ********************************************* ; ******* WINDOW DEFINITIONS AND DRAW ******** ; ********************************************* draw_window: ; function 12: tell os about windowdraw ; 1 start of draw mcall 12,1 ; cmp [params],byte 0 ; jz .noret ; это несколько загадочно, но если не рисовать окошко совсем, прога не пашет. ; DRAW WINDOW ; eax function 0 : define and draw window ; xor eax,eax ; ebx [x start] *65536 + [x size] ; xor ebx,ebx ; ecx [y start] *65536 + [y size] ; xor ecx,ecx ; edx color of work area RRGGBB,8->color gl ; esi color of bar and flags ; xor esi,esi ; mcall ,,,0x14ffffff,,title ; function 12: tell os about windowdraw ; 2, end of draw ; mcall 12,2 ; ret ;.noret: ; DRAW WINDOW ; eax function 0 : define and draw window xor eax,eax ; ebx [x start] *65536 + [x size] ; ecx [y start] *65536 + [y size] ; edx color of work area RRGGBB,8->color gl ; esi color of bar and flags xor esi,esi ; edi WINDOW LABEL mcall ,<50,600>,<350,200>,0x14ffffff,,title ; eax function 4: write text to window ; ebx [x start] *65536 + [y start] ; ecx color of text RRGGBB ; edx pointer to text beginning ; esi max lenght xor ecx,ecx mcall 4,<30,38>,,document_user,URLMAXLEN ; xor edx,edx ; mcall 38,<5,545>,<60,60> ; mov ecx,[winys] ; shl ecx,16 ; add ecx,[winys] ; sub ecx,26*65536+26 ; mcall 38,<5,545> ; RELOAD ; eax function 8 : define and draw button ; ebx [x start] *65536 + [x size] ; ecx [y start] *65536 + [y size] ; edx button id ; esi button color RRGGBB mcall 8,<388,50>,<34,14>,22,0x5588dd ; URL mcall ,<10,12>,<34,12>,10 ; STOP mcall ,<443,50>,<34,14>,24 ; SAVE mcall ,<498,50>,,26 ; BUTTON TEXT ; eax function 4 : write text to window ; ebx [x start] *65536 + [y start] ; ecx color of text RRGGBB ; edx pointer to text beginning ; esi text length mcall 4,<390,38>,0xffffff,button_text,30 call display_page ; function 12: tell os about windowdraw ; 2, end of draw mcall 12,2 ret ;----------------------------------------------------------------------------- ; Data area ;----------------------------------------------------------------------------- align 4 @IMPORT: library libini,'libini.obj' import libini, \ ini.get_str,'ini_get_str', \ ini.get_int,'ini_get_int' ;--------------------------------------------------------------------- fileinfo dd 2,0,0 final_size dd 0 final_buffer dd 0 db '/rd/1/.download',0 body_pos dd 0 ;fileinfo_tmp dd 2,0,0 buf_size dd 0 buf_ptr dd 0 ; db '/rd/1/1',0 deba dd 0 db 0 ;--------------------------------------------------------------------- if DEBUGGING_STATE = DEBUGGING_ENABLED str1: db "Resolving...",0 str3: db "Resolved",0 str2: db "GotIP",0 str4: db "GotResponse",0 end if ;--------------------------------------------------------------------- button_text db ' RELOAD STOP SAVE ' dpx dd 25 ; x - start of html page in pixels in window dpy dd 65 ; for y lastletter db 0 pageyinc dd 0 display_from dd 20 pos dd 0x0 pagex dd 0x0 pagey dd 0x0 pagexs dd 80 command_on_off dd 0x0 text_type db 1 com2 dd 0x0 script dd 0x0 socket dd 0x0 addr dd 0x0 ya dd 0x0 len dd 0x00 title db 'Downloader',0 server_ip: db 207,44,212,20 ;dns_ip: db 194,145,128,1 ;--------------------------------------------------------------------- ;webAddr: ;times URLMAXLEN db ' ' ;db 0 ;document_user: db 'Click on the button to the left to enter a URL',0 ;times URLMAXLEN+document_user-$ db 0 ;document: db '/' ;times URLMAXLEN-1 db ' ' ;--------------------------------------------------------------------- s_contentlength db 'Content-Length:' len_contentlength = 15 s_chunked db 'Transfer-Encoding: chunked' len_chunked = $ - s_chunked is_body dd 0 ; 0 if headers, 1 if content is_chunked dd 0 prev_chunk_end dd 0 cur_chunk_size dd 0 string0: db 'GET ' stringh: db ' HTTP/1.1',13,10,'Host: ' stringh_end: proxy_auth_basic: db 13,10,'Proxy-Authorization: Basic ' proxy_auth_basic_end: connclose: db 13,10,'User-Agent: Kolibrios Downloader',13,10,'Connection: Close',13,10,13,10 connclose_end: base64_table db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' db '0123456789+/' inifile db '/sys/network/zeroconf.ini',0 sec_proxy: key_proxy db 'proxy',0 key_proxyport db 'port',0 key_user db 'user',0 key_password db 'password',0 proxyPort dd 80 shared_name dd 0 ;yandex: db 'menuetos.net' ;yandex_end: status dd 0x0 prev_status dd 0x0 onoff dd 0x0 nextupdate: dd 0 winys: dd 400 dnsMsgLen: dd 0 socketNum: dd 0xFFFF ;--------------------------------------------------------------------- document_user: db 'Click on the button to the left to enter a URL',0 ;--------------------------------------------------------------------- IM_END: rb URLMAXLEN-(IM_END - document_user) ;--------------------------------------------------------------------- align 4 document: rb URLMAXLEN ;--------------------------------------------------------------------- align 4 webAddr: rb URLMAXLEN+1 ;--------------------------------------------------------------------- align 4 primary_buf: rb primary_buffer_size ;--------------------------------------------------------------------- align 4 params: ; db 1024 dup(0) rb 1024 ;--------------------------------------------------------------------- align 4 request: ; db 256 dup(0) rb 256 ;--------------------------------------------------------------------- align 4 proxyAddr: ; db 256 dup(0) rb 256 ;--------------------------------------------------------------------- align 4 proxyUser: ; db 256 dup(0) rb 256 ;--------------------------------------------------------------------- align 4 proxyPassword: ; db 256 dup(0) rb 256 ;--------------------------------------------------------------------- align 4 dnsMsg: rb 4096 ; rb 0x100000 ;--------------------------------------------------------------------- align 4 rb 4096 stacktop: ;--------------------------------------------------------------------- I_END: ;---------------------------------------------------------------------