#include-once
#include <FileConstants.au3>
#include <InetConstants.au3>
#include <WinAPIEx.au3>
Global $bTCPINET_INITIALIZED = False
Global $iTCPINET_OPTTTO = 100
Global $aTCPINET_DATA[1][1]
Global Enum _
$iTI_DATA_iSOCKET, $iTI_DATA_hFILE, $iTI_DATA_sFILE, $iTI_DATA_iREAD, $iTI_DATA_iSIZE, $iTI_DATA_bCOMPLETE, $iTI_DATA_bPAUSED, _
$iTI_DATA_iTOTAL
Global Const $INET_DOWNLOADPAUSED = 3
Global Const $sTCPINET_UA = 'Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0'
Global Const $iTCPINET_MAXBYTES = 1024
Global Const $iTCPINET_TIMEOUT = 10000
Global Const $iTCPINET_PORT = 80
Func _TCPInet_GetFile($sURL, $sFile, $iBackground = $INET_DOWNLOADWAIT)
__TCPInet_Init()
Local $aHostPage = __TCPInet_SplitURL($sURL)
Local $sHost = $aHostPage[0], $sPage = $aHostPage[1]
Local $iSocket = __TCPInet_Connect($sHost)
If @error Then
Return SetError(1, 0, 0)
EndIf
__TCPInet_Request($sHost, $sPage, $iSocket, 'GET')
If @error Then
TCPCloseSocket($iSocket)
Return SetError(2, 0, 0)
EndIf
Local $iFO_Flags = $FO_OVERWRITE
Local $sHeader = __TCPInet_GetHeader($sHost, $sPage)
Local $sContent_Type = __TCPInet_GetTagHeader($sHeader, 'Content-Type')
Local $iContent_Length = Number(__TCPInet_GetTagHeader($sHeader, 'Content-Length'))
If _WinAPI_PathIsDirectory($sFile) Then
$sFile &= '\' & __TCPInet_GetValidFileName(StringRegExpReplace($sURL, '^.*/', ''))
ElseIf _WinAPI_PathIsFileSpec($sFile) Then
$sFile = __TCPInet_GetValidFileName(StringRegExpReplace($sURL, '^.*/', ''))
EndIf
If Not StringRegExp($sHeader, '(?i)^HTTP/\d.\d 200 OK') Then
Return SetError(3, 0, 0)
EndIf
If StringInStr($sContent_Type, 'charset=UTF-8') Then
$iFO_Flags = BitOR($iFO_Flags, $FO_UTF8)
EndIf
Local $sData, $hFile = FileOpen($sFile, $iFO_Flags)
If $iBackground = $INET_DOWNLOADBACKGROUND Then
$aTCPINET_DATA[0][0] += 1
ReDim $aTCPINET_DATA[$aTCPINET_DATA[0][0] + 1][$iTI_DATA_iTOTAL]
$aTCPINET_DATA[$aTCPINET_DATA[0][0]][$iTI_DATA_iSOCKET] = $iSocket
$aTCPINET_DATA[$aTCPINET_DATA[0][0]][$iTI_DATA_hFILE] = $hFile
$aTCPINET_DATA[$aTCPINET_DATA[0][0]][$iTI_DATA_sFILE] = $sFile
$aTCPINET_DATA[$aTCPINET_DATA[0][0]][$iTI_DATA_iSIZE] = $iContent_Length
$aTCPINET_DATA[$aTCPINET_DATA[0][0]][$iTI_DATA_bCOMPLETE] = False
$aTCPINET_DATA[$aTCPINET_DATA[0][0]][$iTI_DATA_bPAUSED] = False
AdlibRegister('__TCPInet_SetDataProc', 1)
Return $aTCPINET_DATA[0][0]
EndIf
While 1
$sData = TCPRecv($iSocket, $iTCPINET_MAXBYTES)
If @error <> 0 Then
ExitLoop
EndIf
FileWrite($hFile, $sData)
WEnd
TCPCloseSocket($iSocket)
FileClose($hFile)
$sRead = StringRegExpReplace(FileRead($sFile), '(?s)^.*?\r\n\r\n', '')
$hFile = FileOpen($sFile, 2 + FileGetEncoding($sFile))
FileWrite($hFile, $sRead)
FileClose($hFile)
Return 1
EndFunc
Func _TCPInet_GetSize($sURL)
__TCPInet_Init()
Local $aHostPage = __TCPInet_SplitURL($sURL)
Local $sHost = $aHostPage[0], $sPage = $aHostPage[1]
Local $sHeader = __TCPInet_GetHeader($sHost, $sPage)
If @error Then
Return SetError(1, 0, 0)
EndIf
Local $iContent_Lenght = __TCPInet_GetTagHeader($sHeader, 'Content-Length')
If @error Then
Return SetError(2, 0, 0)
EndIf
Return Number($iContent_Lenght)
EndFunc
Func _TCPInet_GetInfo($hTCPInet, $iIndex = -1)
If $hTCPInet > $aTCPINET_DATA[0][0] Or $hTCPInet < 1 Then
Return SetError(1, 0, '')
EndIf
Local $aRet[4] = [$aTCPINET_DATA[$hTCPInet][$iTI_DATA_iREAD], $aTCPINET_DATA[$hTCPInet][$iTI_DATA_iSIZE], $aTCPINET_DATA[$hTCPInet][$iTI_DATA_bCOMPLETE], $aTCPINET_DATA[$hTCPInet][$iTI_DATA_bPAUSED]]
If $iIndex = -1 Then
Return $aRet
Else
If $iIndex >= 0 And $iIndex <= 4 Then
Return $aRet[$iIndex]
EndIf
EndIf
Return SetError(2, 0, '')
EndFunc
Func _TCPInet_Close($hTCPInet)
Local $aTmp[1][1]
For $i = 1 To $aTCPINET_DATA[0][0]
If $i <> $hTCPInet Then
$aTmp[0][0] += 1
ReDim $aTmp[$aTmp[0][0] + 1][$iTI_DATA_iTOTAL]
$aTmp[$aTmp[0][0]][$iTI_DATA_iSOCKET] = $aTCPINET_DATA[$i][$iTI_DATA_iSOCKET]
$aTmp[$aTmp[0][0]][$iTI_DATA_hFILE] = $aTCPINET_DATA[$i][$iTI_DATA_hFILE]
$aTmp[$aTmp[0][0]][$iTI_DATA_sFILE] = $aTCPINET_DATA[$i][$iTI_DATA_sFILE]
$aTmp[$aTmp[0][0]][$iTI_DATA_iREAD] = $aTCPINET_DATA[$i][$iTI_DATA_iREAD]
$aTmp[$aTmp[0][0]][$iTI_DATA_iSIZE] = $aTCPINET_DATA[$i][$iTI_DATA_iSIZE]
$aTmp[$aTmp[0][0]][$iTI_DATA_bCOMPLETE] = $aTCPINET_DATA[$i][$iTI_DATA_bCOMPLETE]
$aTmp[$aTmp[0][0]][$iTI_DATA_bPAUSED] = $aTCPINET_DATA[$i][$iTI_DATA_bPAUSED]
Else
TCPCloseSocket($aTCPINET_DATA[$i][$iTI_DATA_iSOCKET])
FileClose($aTCPINET_DATA[$i][$iTI_DATA_hFILE])
EndIf
Next
If $aTmp[0][0] = 0 Then
AdlibUnRegister('__TCPInet_SetDataProc')
__TCPInet_UnInit()
EndIf
$aTCPINET_DATA = $aTmp
EndFunc
Func _TCPInet_SetPause($hTCPInet, $bPause = True)
If $hTCPInet > $aTCPINET_DATA[0][0] Or $hTCPInet < 1 Then
Return SetError(1, 0, '')
EndIf
$aTCPINET_DATA[$hTCPInet][$iTI_DATA_bPAUSED] = $bPause
EndFunc
Func __TCPInet_Init()
If Not $bTCPINET_INITIALIZED Then
$bTCPINET_INITIALIZED = True
$iTCPINET_OPTTTO = Opt('TCPTimeOut', $iTCPINET_TIMEOUT)
TCPStartup()
EndIf
EndFunc
Func __TCPInet_UnInit()
If $bTCPINET_INITIALIZED Then
$bTCPINET_INITIALIZED = False
Opt('TCPTimeOut', $iTCPINET_OPTTTO)
TCPShutdown()
EndIf
EndFunc
Func __TCPInet_SetDataProc()
For $i = 1 To $aTCPINET_DATA[0][0]
If $aTCPINET_DATA[$i][$iTI_DATA_bCOMPLETE] Or $aTCPINET_DATA[$i][$iTI_DATA_bPAUSED] Then
ContinueLoop
EndIf
$iSocket = $aTCPINET_DATA[$i][$iTI_DATA_iSOCKET]
$hFile = $aTCPINET_DATA[$i][$iTI_DATA_hFILE]
$sFile = $aTCPINET_DATA[$i][$iTI_DATA_sFILE]
$sData = TCPRecv($iSocket, $iTCPINET_MAXBYTES)
If @error <> 0 Then
$aTCPINET_DATA[$i][$iTI_DATA_bCOMPLETE] = True
TCPCloseSocket($iSocket)
FileClose($hFile)
$sRead = StringRegExpReplace(FileRead($sFile), '(?s)^.*?\r\n\r\n', '', 1)
$hFile = FileOpen($sFile, 2 + FileGetEncoding($sFile))
FileWrite($hFile, $sRead)
FileClose($hFile)
ContinueLoop
EndIf
$aTCPINET_DATA[$i][$iTI_DATA_iREAD] += $iTCPINET_MAXBYTES
If $aTCPINET_DATA[$i][$iTI_DATA_iSIZE] > 0 And $aTCPINET_DATA[$i][$iTI_DATA_iREAD] > $aTCPINET_DATA[$i][$iTI_DATA_iSIZE] Then
$aTCPINET_DATA[$i][$iTI_DATA_iREAD] = $aTCPINET_DATA[$i][$iTI_DATA_iSIZE]
EndIf
FileWrite($hFile, $sData)
Next
EndFunc
Func __TCPInet_Connect($sHost)
Local $sName_To_IP = TCPNameToIP($sHost)
Local $iSocket = TCPConnect($sName_To_IP, $iTCPINET_PORT)
If $iSocket = -1 Then
TCPCloseSocket($iSocket)
Return SetError(1, 0, '')
EndIf
Return $iSocket
EndFunc
Func __TCPInet_Request($sHost, $sPage, $iSocket, $sRequest = 'GET', $sReferrer = '')
Local $sCommand = ''
$sCommand &= $sRequest & ' ' & $sPage & ' HTTP/1.0' & @CRLF
$sCommand &= 'Host: ' & $sHost & @CRLF
$sCommand &= 'User-Agent: ' & $sTCPINET_UA & @CRLF
$sCommand &= 'Referer: ' & $sReferrer & @CRLF
$sCommand &= 'Connection: close' & @CRLF & @CRLF
Local $iBytesSent = TCPSend($iSocket, $sCommand)
If $iBytesSent = 0 Then
Return SetError(1, @error, 0)
EndIf
Return $iBytesSent
EndFunc
Func __TCPInet_GetHeader($sHost, $sPage)
Local $sData, $iSocket = __TCPInet_Connect($sHost)
If @error Then
Return SetError(1, 0, '')
EndIf
__TCPInet_Request($sHost, $sPage, $iSocket, 'HEAD')
If @error Then
Return SetError(2, 0, '')
EndIf
While 1
$sData &= TCPRecv($iSocket, $iTCPINET_MAXBYTES)
If @error <> 0 Then
ExitLoop
EndIf
WEnd
TCPCloseSocket($iSocket)
Return $sData
EndFunc
Func __TCPInet_GetTagHeader($sHeader, $sTag)
Local $aRet = StringRegExp($sHeader, '(?i)' & $sTag & ': ([^\r\n]+)', 3)
If @error Or Not IsArray($aRet) Then
Return SetError(1, 0, '')
EndIf
Return $aRet[0]
EndFunc
Func __TCPInet_SplitURL($sURL)
Local $aHostPage[2]
$aHostPage[0] = _WinAPI_UrlGetPart($sURL, $URL_PART_HOSTNAME)
$aHostPage[1] = StringRegExpReplace($sURL, '(?is).*?' & $aHostPage[0] & '(.*?)$', '\1')
$aHostPage[1] = '/' & StringRegExpReplace($aHostPage[1], '^/+', '')
Return $aHostPage
EndFunc
Func __TCPInet_GetValidFileName($sString, $sPattern = '[*?\\/|:<>"]', $sReplace = '_')
If StringStripWS($sString, 8) = '' Then Return $sString
$sString = StringRegExpReplace($sString, $sPattern, $sReplace)
Return SetExtended(@extended, StringRegExpReplace($sString, '(' & $sReplace & '+)', $sReplace))
EndFunc