📄 http.asm
字号:
.ELSEIF eax==WM_TIMER
invoke ShowDownloadSpeed
.ELSEIF eax==WM_CREATE
invoke CreateStatusWindow,WS_CHILD+WS_VISIBLE+SBARS_SIZEGRIP,NULL,hWnd,IDC_STATUS ; Create the status bar
mov hwndStatus,eax ; Create the status bar
invoke SendMessage,hwndStatus,SB_SETPARTS,2,addr PartWidth
.ELSEIF eax==WM_SOCKET
mov eax,lParam
.if ax==FD_CONNECT ; if the socket is connected
push eax
pop eax
shr eax,16 ; If there is an error during connect process, the error code is returned in the high word of lParam
.if ax==NULL ; If there is no error, proceed to send the request
invoke SendRequest
.else
invoke ReconnectIfPossible
.endif
.elseif ax==FD_READ
shr eax,16 ; Check if there is an error code in the high word of lParam
.if eax==0
invoke ReadSocket
.else
invoke ShowSocketError
.endif
.elseif ax==FD_CLOSE ; When the connection is closed from the other end, it marks the end of the file
shr eax,16
.if eax==0 ; Check if there is some error
invoke CloseTheSock
.else
.if eax==WSAECONNRESET || eax==WSAECONNABORTED
invoke CloseTheSock
.else
invoke ShowSocketError
.endif
.endif
.endif
.ELSEIF eax==WM_COMMAND
mov eax,wParam
.if lParam==0
.if ax==IDM_CONNECT ; When the user presses connect button or connect menu item.
mov Resuming,FALSE ; Assume that the server cannot resume download
mov FileHandle,0 ; We use the value of FileHandle to check whether the file was closed
mov TimerID,0 ; We use the value of TimerID in the same manner as FileHandle
mov eax,OFFSET URLProc
invoke DialogBoxParam,hInstance,addr URLDialogName,hWnd,eax,0
.if eax==TRUE ; If the user types in a url
invoke ConnectSocket
.endif
.elseif ax==IDM_EXIT
invoke DestroyWindow,hWnd
.else
invoke MessageBox,hWnd, addr AboutMessage, addr AppName,MB_OK or MB_ICONINFORMATION
.endif
.else
.if ax==IDC_CONNECT
invoke SendMessage,hWnd,WM_COMMAND,IDM_CONNECT,0
.elseif ax==IDC_EXIT
invoke DestroyWindow,hWnd
.endif
.endif
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
;======================================================================
; ShowSocketError
;======================================================================
; This procedure is called to display the error message on the screen in
; case of FD_CONNECT, FD_READ and FD_CLOSE notification.
;======================================================================
ShowSocketError PROC
invoke TranslateErrorCode,eax,addr ErrorString
invoke MessageBox,NULL,addr ErrorString,addr AppName,MB_OK+MB_ICONERROR
invoke CloseSock
invoke EnableControls
ret
ShowSocketError ENDP
;========================================================================
; URLProc
;========================================================================
; This is the dialog procedure of the dialog that receives url from the
; user
;========================================================================
URLProc PROC hDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
.if uMsg==WM_CLOSE
invoke EndDialog,hDlg,0
.elseif uMsg==WM_INITDIALOG
mov wParam,IDC_EDIT1 ; Set the focus to the edit control
.elseif uMsg==WM_COMMAND
mov eax,wParam
.if ax==IDC_OK
shr eax,16
.if ax==BN_CLICKED ; If the user clicks ok button
invoke GetDlgItemText,hDlg,IDC_EDIT1,addr URLString,512
.if eax!=0 ; If the user doesn't type in some string, don't close the dialog box
invoke EndDialog,hDlg,1
.else
invoke GetDlgItem,hDlg,IDC_EDIT1
invoke SetFocus,eax
.endif
.endif
.elseif ax==IDC_CANCEL
shr eax,16
.if ax==BN_CLICKED
invoke SendMessage,hDlg,WM_CLOSE,0,0
.endif
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
URLProc ENDP
;======================================================================
; String2Dword
;======================================================================
; This procedure takes an address of a string and converts it to a dword
; value which it returns in eax
;======================================================================
String2Dword proc uses ecx edi edx esi String:DWORD
xor ecx,ecx
mov edi,String
invoke lstrlen,String
.while eax!=0
xor edx,edx
mov dl,byte ptr [edi]
sub dl,"0" ; subtrack each digit with "0" to convert it to hex value
mov esi,eax
dec esi
push eax
mov eax,edx
push ebx
mov ebx,10
.while esi > 0
mul ebx
dec esi
.endw
pop ebx
add ecx,eax
pop eax
inc edi
dec eax
.endw
mov eax,ecx
ret
String2Dword endp
;======================================================================
; ParseHeader
;======================================================================
; This procedure takes the address of HTTP header and finds the file size
;======================================================================
ParseHeader PROC uses esi ecx edi Header:DWORD
LOCAL MyHeader[512]:BYTE
invoke lstrcpy,addr MyHeader,Header
invoke CharLower,addr MyHeader ; Convert the http header to lower case
.if Resuming==FALSE ; in the case that we resume download, we don't have to
; search the header for content length again
invoke lstrlen,addr MyHeader
mov ecx,eax
lea edi,MyHeader ; begin searching for "content-length:"
Rescan:
mov al,"c" ; by scanning for its first char, "c"
repne scasb
jne NoLength ; If not found, something is wrong
push ecx ; If "c" is found, it's still not certain
; that it's the start of the
; "content-length:" string. So we must
; save all registers so that we can
; resume scanning.
push edi
dec edi ; move back to the "c" character
mov ecx,15 ; 15 --> the length of "content-length:"
mov esi,offset Content
repe cmpsb ; compare if the string that starts with "c"
; is identical to "content-length"
mov esi,edi ; save edi which points to the first byte
; of the length (if it's "content-length")
pop edi
pop ecx
jne Rescan ; if the strings didn't match, rescan the http header
mov edi,offset ContentString
.while (byte ptr [esi]!=0Dh)
.if byte ptr [esi]!=20h
mov al,byte ptr [esi]
mov byte ptr [edi],al
inc edi
.endif
inc esi
.endw
mov byte ptr [edi],0
invoke String2Dword,addr ContentString
mov ContentLength,eax
.endif
Find_status_code:
invoke lstrlen,addr MyHeader
mov ecx,eax
lea edi,MyHeader
mov al," "
repne scasb
.if byte ptr [edi]==" "
repe scasb
dec edi
.endif
mov ecx,3
mov esi,edi
mov edi,offset StatusCode
rep movsb
mov eax,TRUE
ret
NoLength:
mov ContentLength,0
jmp Find_status_code
Unsuccessful:
mov eax,FALSE
ret
ParseHeader endp
;=========================================================================
; ParseURL
;=========================================================================
; This function parses the url string for host name, relative URL and http
; port
;-------------------------------------------------------------------------
ParseURL PROC uses esi edi URL:DWORD
LOCAL MyURL[512]:BYTE
LOCAL URLLength:DWORD
invoke lstrlen,URL
mov URLLength,eax
mov ecx,eax ; Trim the spaces at the start of the url string, if any
mov edi,URL
mov al,20h
repe scasb
dec edi
invoke lstrcpy,addr MyURL,edi ; We don't want to modify the original url string since we have to modify the cases of the url
invoke lstrcpy,URL,addr MyURL
invoke lstrlen,URL
mov URLLength,eax
invoke RtlFillMemory,addr HostName,501,0 ; fill HostName and RelativeURL with zeroes
invoke CharLower,addr MyURL ; change to lower case for ease of comparison
lea edi,MyURL
mov esi,offset HTTP ; check if the url starts with "http://"
mov ecx,7
repe cmpsb
jne No_HTTP
mov eax,URLLength ; if it is, substract the length of url string by 7 to
sub eax,7 ; account for the length of "http://" string
mov URLLength,eax
jmp Common_parse
No_HTTP:
lea edi,MyURL
Common_parse:
push edi
invoke lstrcpy,addr MyURL,URL
pop edi
xor ecx,ecx
mov esi,offset HostName
mov HTTPPort,80 ; Default port =80
.while ecx < URLLength
.if byte ptr [edi]=="/" ; if "/" is found, it denotes the end of the host name string
invoke lstrcpy,addr RelativeURL,edi ; and the start of the relative url string
.break
.elseif byte ptr [edi]==":" ; if ":" is found, it means an HTTP port is specified in the url
inc ecx
inc edi
invoke RtlFillMemory,addr PortString,10,0
mov eax,offset PortString
.while (byte ptr [edi]!="/") && (byte ptr [edi]!=0)
mov dl,byte ptr [edi]
mov byte ptr [eax],dl
inc eax
inc ecx
inc edi
.endw
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -