From 87333d238d9a7d335f248a4bb8a5a03b9f9953b2 Mon Sep 17 00:00:00 2001 From: CleverMouse Date: Wed, 6 Oct 2010 13:29:55 +0000 Subject: [PATCH] upload downloader git-svn-id: svn://kolibrios.org@1645 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/network/downloader/trunk/debug.inc | 137 ++ programs/network/downloader/trunk/dll.inc | 124 ++ .../network/downloader/trunk/downloader.asm | 1910 +++++++++++++++++ programs/network/downloader/trunk/lang.inc | 1 + 4 files changed, 2172 insertions(+) create mode 100644 programs/network/downloader/trunk/debug.inc create mode 100644 programs/network/downloader/trunk/dll.inc create mode 100644 programs/network/downloader/trunk/downloader.asm create mode 100644 programs/network/downloader/trunk/lang.inc diff --git a/programs/network/downloader/trunk/debug.inc b/programs/network/downloader/trunk/debug.inc new file mode 100644 index 0000000000..1f43e064a7 --- /dev/null +++ b/programs/network/downloader/trunk/debug.inc @@ -0,0 +1,137 @@ +macro debug_print str +{ + local ..string, ..label + + jmp ..label + ..string db str,0 + ..label: + + pushf + pushad + mov edx,..string + call debug_outstr + popad + popf +} + +dps fix debug_print + +macro debug_print_dec arg +{ + pushf + pushad + if ~arg eq eax + mov eax,arg + end if + call debug_outdec + popad + popf +} + +dpd fix debug_print_dec + +;--------------------------------- +debug_outdec: ;(eax - num, edi-str) + push 10 ;2 + pop ecx ;1 + push -'0' ;2 + .l0: + xor edx,edx ;2 + div ecx ;2 + push edx ;1 + test eax,eax ;2 + jnz .l0 ;2 + .l1: + pop eax ;1 + add al,'0' ;2 + call debug_outchar ; stosb + jnz .l1 ;2 + ret ;1 +;--------------------------------- + +debug_outchar: ; al - char + pushf + pushad + mov cl,al + mov eax,63 + mov ebx,1 + int 0x40 + popad + popf +ret + +debug_outstr: + mov eax,63 + mov ebx,1 + @@: + mov cl,[edx] + test cl,cl + jz @f + int 40h + inc edx + jmp @b + @@: + ret + +_debug_crlf db 13, 10, 0 + +macro newline +{ + pushf + pushad + mov edx, _debug_crlf + call debug_outstr + popad + popf +} + +macro print message +{ + dps message + newline +} + +macro pregs +{ + dps "EAX: " + dpd eax + dps " EBX: " + dpd ebx + newline + dps "ECX: " + dpd ecx + dps " EDX: " + dpd edx + newline +} + +macro debug_print_hex arg +{ + pushf + pushad + if ~arg eq eax + mov eax, arg + end if + call debug_outhex + popad + popf +} +dph fix debug_print_hex + +debug_outhex: + ; eax - number + mov edx, 8 + .new_char: + rol eax, 4 + movzx ecx, al + and cl, 0x0f + mov cl, [__hexdigits + ecx] + pushad + mcall 63, 1 + popad + dec edx + jnz .new_char +ret + +__hexdigits: + db '0123456789ABCDEF' \ No newline at end of file diff --git a/programs/network/downloader/trunk/dll.inc b/programs/network/downloader/trunk/dll.inc new file mode 100644 index 0000000000..d29b04c964 --- /dev/null +++ b/programs/network/downloader/trunk/dll.inc @@ -0,0 +1,124 @@ + +proc dll.Load, import_table:dword + mov esi,[import_table] + .next_lib: mov edx,[esi] + or edx,edx + jz .exit + push esi + mov esi,[esi+4] + mov edi,s_libdir.fname + @@: lodsb + stosb + or al,al + jnz @b + mcall 68,19,s_libdir + or eax,eax + jz .fail + stdcall dll.Link,eax,edx + push eax + mov eax, [eax] + cmp dword [eax], 'lib_' + pop eax + jnz @f + stdcall dll.Init,[eax+4] + @@: + pop esi + add esi,8 + jmp .next_lib + .exit: xor eax,eax + ret + .fail: add esp,4 + xor eax,eax + inc eax + ret +endp + +proc dll.Link, exp:dword,imp:dword + push eax + mov esi,[imp] + test esi,esi + jz .done + .next: lodsd + test eax,eax + jz .done + stdcall dll.GetProcAddress,[exp],eax + or eax,eax + jz @f + mov [esi-4],eax + jmp .next + @@: mov dword[esp],0 + .done: pop eax + ret +endp + +proc dll.Init, dllentry:dword + pushad + mov eax,mem.Alloc + mov ebx,mem.Free + mov ecx,mem.ReAlloc + mov edx,dll.Load + stdcall [dllentry] + popad + ret +endp + +proc dll.GetProcAddress, exp:dword,sz_name:dword + mov edx,[exp] + xor eax,eax + .next: or edx,edx + jz .end + cmp dword[edx],0 + jz .end + stdcall strcmp,[edx],[sz_name] + test eax,eax + jz .ok + add edx,8 + jmp .next + .ok: mov eax,[edx+4] + .end: ret +endp + +proc strcmp, str1:dword,str2:dword + push esi edi + mov esi,[str1] + mov edi,[str2] + xor eax,eax + @@: lodsb + scasb + jne .fail + or al,al + jnz @b + jmp .ok + .fail: or eax,-1 + .ok: pop edi esi + ret +endp + +; void* __stdcall mem.Alloc(unsigned size); +mem.Alloc: + push ebx ecx + mov ecx, [esp+12] + mcall 68, 12 + pop ecx ebx + ret 4 + +; void* __stdcall mem.ReAlloc(void* mptr, unsigned size); +mem.ReAlloc: + push ebx ecx edx + mov edx, [esp+16] + mov ecx, [esp+20] + mcall 68, 20 + pop edx ecx ebx + ret 8 + +; void __stdcall mem.Free(void* mptr); +mem.Free: + push ebx ecx + mov ecx, [esp+12] + mcall 68, 13 + pop ecx ebx + ret 4 + +s_libdir: + db '/sys/lib/' + .fname rb 32 diff --git a/programs/network/downloader/trunk/downloader.asm b/programs/network/downloader/trunk/downloader.asm new file mode 100644 index 0000000000..30c3cc193b --- /dev/null +++ b/programs/network/downloader/trunk/downloader.asm @@ -0,0 +1,1910 @@ +; 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 I_END ; image size + dd 0x100000 ; required memory + dd 0x100000 ; esp + dd params ; I_PARAM + dd 0x0 ;I_Path + +include 'lang.inc' +include '../../../macros.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> + + mov eax,40 ; Report events + mov ebx,10000111b ; Stack 8 + defaults + mcall + + mov eax, 68 ; create local heap + mov ebx, 11 + mcall + + call load_settings + + cmp byte [params], 0 + jz red + + ; 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 + +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,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 + mov eax, 70 + mov ebx, fileinfo + mcall +;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: + 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.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 byte [proxyAddr], 0 + jz .noproxy + mov dword [edi], 'http' + mov byte [edi+4], ':' + mov word [edi+5], '//' + add edi, 7 + mov esi, webAddr +.copy_host_loop: + lodsb + cmp al, ' ' + jz .noproxy + stosb + jmp .copy_host_loop +.noproxy: + + mov 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 + + mov 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 byte [proxyUser], 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 + int 40h + inc edx + jmp @b +@@: + popa + + mov edx, edi + sub edx, request + + ;;;;now write \r\nConnection: Close \r\n\r\n + mov eax, 53 ; ' HTTP/1.1 .. ' + mov ebx, 7 + mov ecx, [socket] + mov esi, request + 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: + + push esi + push edi +dps "rid" +newline + +newbyteread: + + ;call print_status + + mov eax, 53 + mov ebx, 2 + mov ecx, [socket] + mcall + + cmp eax,0 + je no_more_data + + mov eax, 53 + mov ebx, 11 + mov edx, primary_buf + mov ecx, [socket] + mov esi, primary_buffer_size + mcall + +;dps "part " +;dph eax +;newline + + mov edi, [pos] + + add [pos], eax + push eax + + mov eax, 68 + mov ebx, 20 + mov ecx, [pos] + mov edx, [buf_ptr] + mcall + + 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: + + mov eax, 53 + mov ebx, 6 + mov ecx, [socket] + mcall + cmp eax, 4 + jne no_more_data.finish + + jmp newbyteread + +.finish: + +;dps "finish " +;pregs + + call parse_result + + mov ecx, [shared_name] + cmp byte [ecx], 0 + jnz save_in_shared + mov eax, 70 + mov ebx, fileinfo + mcall +;dps "saving " +;pregs + + ;jmp close_end_exit + + pop edi + pop esi + + ; if called from command line, then exit + cmp byte [params], 0 + jnz exit + + ret + +save_in_shared: + mov eax, 68 + mov ebx, 22 + mov esi, 1 ; SHM_OPEN+SHM_WRITE + mcall + 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 + mov eax, 53 + mov ebx, 8 + mov ecx, [socket] + mcall + +dps "close socket: " +dph eax +newline + + mov edi, [buf_ptr] + mov edx, [pos] + + mov [buf_size], edx + ;mov eax, 70 + ;mov ebx, fileinfo_tmp + ;mcall + +dps "pos = " +dph edx +newline + + ; first, find end of headers + +.next_byte: + cmp dword [edi], 0x0d0a0d0a ; мне лень читать стандарт, пусть будут оба варианта + je .end_of_headers + cmp dword [edi], 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] + mov 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: + mov 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] + mov 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: + mov 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 + + mov [final_buffer], 0 + mov [final_size], 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 + + mov eax, 68 + mov ebx, 20 + mov ecx, [final_size] + mov edx, [final_buffer] + mcall + 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 + + mov eax, 68 + mov ebx, 13 + mov ecx, [buf_ptr] + mcall + + ; 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 + + mov [prev_chunk_end], 0 + + cmp [buf_ptr], 0 + jz no_free + mov eax, 68 ; free buffer + mov ebx, 13 + mov ecx, [buf_ptr] + mcall +no_free: + mov [buf_size], 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 + mov eax, 53 + mov ebx, 9 + mcall + pop ecx + cmp eax, 0 ; is this local port in use? + jz getlp1 ; yes - so try next + + mov eax,53 + mov ebx,5 + mov edx,80 + cmp [proxyAddr], 0 + jz sc000 + mov edx,[proxyPort] +sc000: + mov esi,dword [server_ip] + mov edi,1 + mcall + mov [socket], eax + + mov [pos],0 + mov [pagex],0 + mov [pagey],0 + mov [pagexs],80 + mov [command_on_off],0 + + mov [is_body], 0 + + ret + +tst3: + cmp ah,24 ; close socket + jnz no_24 + + mov eax,53 + mov ebx,8 + mov ecx,[socket] + mcall + + call draw_page + + ret + +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 word [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 + +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 + +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 + mov eax, 53 + mov ebx, 9 + mcall + pop ecx + cmp eax, 0 ; is this local port in use? + jz getlp ; yes - so try next + + ; Get DNS IP + mov eax, 52 + mov ebx, 13 + mcall + mov esi, eax + ; First, open socket + mov eax, 53 + mov ebx, 0 + mov edx, 53 ; remote port - dns +; mov esi, dword [dns_ip] + mcall + + mov [socketNum], eax + + ; write to socket ( request DNS lookup ) + mov eax, 53 + mov ebx, 4 + mov ecx, [socketNum] + mov edx, [dnsMsgLen] + mov esi, dnsMsg + mcall + + ; Setup the DNS response buffer + + mov eax, dnsMsg + mov [dnsMsgLen], eax + + ; now, we wait for + ; UI redraw + ; UI close + ; or data from remote + +ctr001: + mov eax,10 ; wait here for event + mcall + + 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? + mov eax, 53 + mov ebx, 2 + mov ecx, [socketNum] + mcall + + cmp eax, 0 + je ctr001 + + ; we have data - this will be the response +ctr002: + mov eax, 53 + mov ebx, 3 + mov ecx, [socketNum] + mcall ; read byte - block (high byte) + + ; Store the data in the response buffer + mov eax, [dnsMsgLen] + mov [eax], bl + inc dword [dnsMsgLen] + + mov eax, 53 + mov ebx, 2 + mov ecx, [socketNum] + mcall ; any more data? + + cmp eax, 0 + jne ctr002 ; yes, so get it + + ; close socket + mov eax, 53 + mov ebx, 1 + mov ecx, [socketNum] + mcall + + 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 validated. 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 + mov eax,2 ; just read it and ignore + mcall + jmp ctr001 + +ctr005: ; button + mov eax,17 ; get id + mcall + + mov dl, ah + + ; close socket + mov eax, 53 + mov ebx, 1 + mov ecx, [socketNum] + mcall + + 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 +; +;*************************************************************************** +include "proc32.inc" +include "dll.inc" +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, '"' + mov eax,63 + mov ebx, 1 + mcall + 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, '"' + mov eax,63 + mov ebx, 1 + mcall + mov cl, 13 + mov eax,63 + mov ebx, 1 + mcall + mov cl, 10 + mov eax,63 + mov ebx, 1 + mcall + ret + +dps_001: + mov eax,63 + mov ebx, 1 + push esi + mcall + + 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 eax,13 + mov ebx,30*65536+URLMAXLEN*6 ; 50 should really be [len], and 103 [xa] + mov ecx,[ya] + shl ecx,16 + mov cx,9 + mov edx,0xFFFFFF + mcall + + ; write text + mov eax,4 + mov ebx,30*65536 + add ebx,[ya] + mov ecx,0x000000 + mov edx,[addr] + mov esi,URLMAXLEN + mcall + + ret + +; ********************************************* +; ******* WINDOW DEFINITIONS AND DRAW ******** +; ********************************************* + +draw_window: + + cmp byte [params], 0 + jz .noret + + mov eax,12 ; function 12:tell os about windowdraw + mov ebx,1 ; 1, start of draw + mcall + + ; это несколько загадочно, но если не рисовать окошко совсем, прога не пашет. + + mov eax,0 ; function 0 : define and draw window + mov ebx,0 ; [x start] *65536 + [x size] + mov ecx,0 ; [y start] *65536 + [y size] + mov edx,0x14ffffff ; color of work area RRGGBB,8->color gl + mov edi,title ; WINDOW LABEL + mcall + + mov eax,12 ; function 12:tell os about windowdraw + mov ebx,2 ; 2, end of draw + mcall + + ret + +.noret: + mov eax,12 ; function 12:tell os about windowdraw + mov ebx,1 ; 1, start of draw + mcall + + ; DRAW WINDOW + mov eax,0 ; function 0 : define and draw window + mov ebx,50*65536+600 ; [x start] *65536 + [x size] + mov ecx,350*65536+200 ; [y start] *65536 + [y size] + mov edx,0x14ffffff ; color of work area RRGGBB,8->color gl + mov edi,title ; WINDOW LABEL + mcall + + + mov esi, URLMAXLEN ; URL + mov eax,4 ; function 4 : write text to window + mov ebx,30*65536+38 ; [x start] *65536 + [y start] + mov ecx,0x000000 ; color of text RRGGBB + mov edx,document_user ; pointer to text beginning + mcall + + ; mov eax,38 + ; mov ebx,5*65536+545 + ; mov ecx,60*65536+60 + ; mov edx,0x000000 + ; mcall + + ;mov eax,38 + ;mov ebx,5*65536+545 + ; mov ecx,[winys] + ; shl ecx,16 + ; add ecx,[winys] + ; sub ecx,26*65536+26 + ;mov edx,0x000000 + ;mcall + ; RELOAD + mov eax,8 ; function 8 : define and draw button + mov ebx,388*65536+50 ; [x start] *65536 + [x size] + mov ecx,34*65536+14 ; [y start] *65536 + [y size] + mov edx,22 ; button id + mov esi,0x5588dd ; button color RRGGBB + mcall + + ; URL + ;mov eax,8 ; function 8 : define and draw button + mov ebx,10*65536+12 ; [x start] *65536 + [x size] + mov ecx,34*65536+12 ; [y start] *65536 + [y size] + mov edx,10 ; button id + ;mov esi,0x5588dd ; button color RRGGBB + mcall + + ; STOP + ;mov eax,8 ; function 8 : define and draw button + mov ebx,443*65536+50 ; [x start] *65536 + [x size] + mov ecx,34*65536+14 ; [y start] *65536 + [y size] + mov edx,24 ; button id + ;mov esi,0x5588dd ; button color RRGGBB + mcall + + ; SAVE + mov ebx,(443+55)*65536+50 ; [x start] *65536 + [x size] + mov ecx,34*65536+14 ; [y start] *65536 + [y size] + mov edx,26 ; button id + ;mov esi,0x5588dd ; button color RRGGBB + mcall + + ; BUTTON TEXT + mov eax,4 ; function 4 : write text to window + mov ebx,390*65536+38 ; [x start] *65536 + [y start] + mov ecx,0xffffff ; color of text RRGGBB + mov edx,button_text ; pointer to text beginning + mov esi,30 ; text length + mcall + + call display_page + + mov eax,12 ; function 12:tell os about windowdraw + mov ebx,2 ; 2, end of draw + mcall + + ret + +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 + +params db 1024 dup(0) + +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 + +request db 256 dup(0) + +proxyAddr db 256 dup(0) +proxyUser db 256 dup(0) +proxyPassword db 256 dup(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 + +primary_buf rb primary_buffer_size + +dnsMsgLen: dd 0 +socketNum: dd 0xFFFF +dnsMsg: +I_END: diff --git a/programs/network/downloader/trunk/lang.inc b/programs/network/downloader/trunk/lang.inc new file mode 100644 index 0000000000..30c0149bd9 --- /dev/null +++ b/programs/network/downloader/trunk/lang.inc @@ -0,0 +1 @@ +lang fix ru \ No newline at end of file