httpQuery-0-3-6.ahk


SUBMITTED BY: Guest

DATE: March 26, 2014, 11:37 p.m.

FORMAT: Text only

SIZE: 12.4 kB

HITS: 2368

  1. ; httpQuery-0-3-6.ahk
  2. httpQuery(byref p1 = "", p2 = "", p3="", p4="")
  3. { ; v0.3.6 (w) Oct, 26 2010 by derRaphael / zLib-Style release
  4. ; currently the verbs showHeader, storeHeader, and updateSize are supported in httpQueryOps
  5. ; in case u need a different UserAgent, Proxy, ProxyByPass, Referrer, and AcceptType just
  6. ; specify them as global variables - mind the varname for referrer is httpQueryReferer [sic].
  7. ; Also if any special dwFlags are needed such as INTERNET_FLAG_NO_AUTO_REDIRECT or cache
  8. ; handling this might be set using the httpQueryDwFlags variable as global
  9. global httpQueryOps, httpAgent, httpProxy, httpProxyByPass, httpQueryReferer, httpQueryAcceptType
  10. , httpQueryDwFlags
  11. ; Get any missing default Values
  12. ;v0.3.6
  13. ; check for syntax
  14. if ( VarSetCapacity(p1) != 0 )
  15. dReturn:=true, result := "", lpszUrl := p1, POSTDATA := p2, HEADERS := p3
  16. else
  17. result := p1, lpszUrl := p2, POSTDATA := p3, HEADERS := p4
  18. defaultOps =
  19. (LTrim Join|
  20. httpAgent=AutoHotkeyScript|httpProxy=0|httpProxyByPass=0|INTERNET_FLAG_SECURE=0x00800000
  21. SECURITY_FLAG_IGNORE_UNKNOWN_CA=0x00000100|SECURITY_FLAG_IGNORE_CERT_CN_INVALID=0x00001000
  22. SECURITY_FLAG_IGNORE_CERT_DATE_INVALID=0x00002000|SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE=0x00000200
  23. INTERNET_OPEN_TYPE_PROXY=3|INTERNET_OPEN_TYPE_DIRECT=1|INTERNET_SERVICE_HTTP=3
  24. )
  25. Loop,Parse,defaultOps,|
  26. {
  27. RegExMatch(A_LoopField,"(?P<Option>[^=]+)=(?P<Default>.*)",http)
  28. if StrLen(%httpOption%)=0
  29. %httpOption% := httpDefault
  30. }
  31. ; Load Library
  32. hModule := DllCall("LoadLibrary", "Str", "WinINet.Dll")
  33. ; SetUpStructures for URL_COMPONENTS / needed for InternetCrackURL
  34. ; http://msdn.microsoft.com/en-us/library/aa385420(VS.85).aspx
  35. offset_name_length:= "4-lpszScheme-255|16-lpszHostName-1024|28-lpszUserName-1024|"
  36. . "36-lpszPassword-1024|44-lpszUrlPath-1024|52-lpszExtrainfo-1024"
  37. VarSetCapacity(URL_COMPONENTS,60,0)
  38. ; Struc Size ; Scheme Size ; Max Port Number
  39. NumPut(60,URL_COMPONENTS,0), NumPut(255,URL_COMPONENTS,12), NumPut(0xffff,URL_COMPONENTS,24)
  40. Loop,Parse,offset_name_length,|
  41. {
  42. RegExMatch(A_LoopField,"(?P<Offset>\d+)-(?P<Name>[a-zA-Z]+)-(?P<Size>\d+)",iCU_)
  43. VarSetCapacity(%iCU_Name%,iCU_Size,0)
  44. NumPut(&%iCU_Name%,URL_COMPONENTS,iCU_Offset)
  45. NumPut(iCU_Size,URL_COMPONENTS,iCU_Offset+4)
  46. }
  47. ; Split the given URL; extract scheme, user, pass, authotity (host), port, path, and query (extrainfo)
  48. ; http://msdn.microsoft.com/en-us/library/aa384376(VS.85).aspx
  49. DllCall("WinINet\InternetCrackUrlA","Str",lpszUrl,"uInt",StrLen(lpszUrl),"uInt",0,"uInt",&URL_COMPONENTS)
  50. ; Update variables to retrieve results
  51. Loop,Parse,offset_name_length,|
  52. {
  53. RegExMatch(A_LoopField,"-(?P<Name>[a-zA-Z]+)-",iCU_)
  54. VarSetCapacity(%iCU_Name%,-1)
  55. }
  56. nPort:=NumGet(URL_COMPONENTS,24,"uInt")
  57. ; Import any set dwFlags
  58. dwFlags := httpQueryDwFlags
  59. ; For some reasons using a selfsigned https certificates doesnt work
  60. ; such as an own webmin service - even though every security is turned off
  61. ; https with valid certificates works when
  62. if (lpszScheme = "https")
  63. dwFlags |= (INTERNET_FLAG_SECURE|SECURITY_FLAG_IGNORE_CERT_CN_INVALID
  64. |SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)
  65. ; Check for Header and drop exception if unknown or invalid URL
  66. if (lpszScheme="unknown") {
  67. Result := "ERR: No Valid URL supplied."
  68. Return StrLen(Result)
  69. }
  70. ; Initialise httpQuery's use of the WinINet functions.
  71. ; http://msdn.microsoft.com/en-us/library/aa385096(VS.85).aspx
  72. hInternet := DllCall("WinINet\InternetOpenA"
  73. ,"Str",httpAgent,"UInt"
  74. ,(httpProxy != 0 ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_DIRECT )
  75. ,"Str",httpProxy,"Str",httpProxyBypass,"Uint",0)
  76. ; Open HTTP session for the given URL
  77. ; http://msdn.microsoft.com/en-us/library/aa384363(VS.85).aspx
  78. hConnect := DllCall("WinINet\InternetConnectA"
  79. ,"uInt",hInternet,"Str",lpszHostname, "Int",nPort
  80. ,"Str",lpszUserName, "Str",lpszPassword,"uInt",INTERNET_SERVICE_HTTP
  81. ,"uInt",0,"uInt*",0)
  82. ; Do we POST? If so, check for header handling and set default
  83. if (Strlen(POSTDATA)>0) {
  84. HTTPVerb:="POST"
  85. if StrLen(Headers)=0
  86. Headers:="Content-Type: application/x-www-form-urlencoded"
  87. } else ; otherwise mode must be GET - no header defaults needed
  88. HTTPVerb:="GET"
  89. ; Form the request with proper HTTP protocol version and create the request handle
  90. ; http://msdn.microsoft.com/en-us/library/aa384233(VS.85).aspx
  91. hRequest := DllCall("WinINet\HttpOpenRequestA"
  92. ,"uInt",hConnect,"Str",HTTPVerb,"Str",lpszUrlPath . lpszExtrainfo
  93. ,"Str",ProVer := "HTTP/1.1", "Str",httpQueryReferer,"Str",httpQueryAcceptTypes
  94. ,"uInt",dwFlags,"uInt",Context:=0 )
  95. ; Send the specified request to the server
  96. ; http://msdn.microsoft.com/en-us/library/aa384247(VS.85).aspx
  97. sRequest := DllCall("WinINet\HttpSendRequestA"
  98. , "uInt",hRequest,"Str",Headers, "uInt",Strlen(Headers)
  99. , "Str",POSTData,"uInt",Strlen(POSTData))
  100. VarSetCapacity(header, 2048, 0) ; max 2K header data for httpResponseHeader
  101. VarSetCapacity(header_len, 4, 0)
  102. ; Check for returned server response-header (works only _after_ request been sent)
  103. ; http://msdn.microsoft.com/en-us/library/aa384238.aspx
  104. Loop, 5
  105. if ((headerRequest:=DllCall("WinINet\HttpQueryInfoA","uint",hRequest
  106. ,"uint",21,"uint",&header,"uint",&header_len,"uint",0))=1)
  107. break
  108. If (headerRequest=1) {
  109. VarSetCapacity(res,headerLength:=NumGet(header_len),32)
  110. DllCall("RtlMoveMemory","uInt",&res,"uInt",&header,"uInt",headerLength)
  111. Loop,% headerLength
  112. if (*(&res-1+a_index)=0) ; Change binary zero to linefeed
  113. NumPut(Asc("`n"),res,a_index-1,"uChar")
  114. VarSetCapacity(res,-1)
  115. } else
  116. res := "timeout"
  117. ; Get 1st Line of Full Response
  118. Loop,Parse,res,`n,`r
  119. {
  120. RetValue := A_LoopField
  121. break
  122. }
  123. ; No Connection established - drop exception
  124. If (RetValue="timeout") {
  125. html := "Error: timeout"
  126. return -1
  127. }
  128. ; Strip protocol version from return value
  129. RetValue := RegExReplace(RetValue,"HTTP/1\.[01]\s+")
  130. ; List taken from http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
  131. HttpRetCodes := "100=Continue|101=Switching Protocols|102=Processing (WebDAV) (RFC 2518)|"
  132. . "200=OK|201=Created|202=Accepted|203=Non-Authoritative Information|204=No"
  133. . " Content|205=Reset Content|206=Partial Content|207=Multi-Status (WebDAV)"
  134. . "|300=Multiple Choices|301=Moved Permanently|302=Found|303=See Other|304="
  135. . "Not Modified|305=Use Proxy|306=Switch Proxy|307=Temporary Redirect|400=B"
  136. . "ad Request|401=Unauthorized|402=Payment Required|403=Forbidden|404=Not F"
  137. . "ound|405=Method Not Allowed|406=Not Acceptable|407=Proxy Authentication "
  138. . "Required|408=Request Timeout|409=Conflict|410=Gone|411=Length Required|4"
  139. . "12=Precondition Failed|413=Request Entity Too Large|414=Request-URI Too "
  140. . "Long|415=Unsupported Media Type|416=Requested Range Not Satisfiable|417="
  141. . "Expectation Failed|418=I'm a teapot (RFC 2324)|422=Unprocessable Entity "
  142. . "(WebDAV) (RFC 4918)|423=Locked (WebDAV) (RFC 4918)|424=Failed Dependency"
  143. . " (WebDAV) (RFC 4918)|425=Unordered Collection (RFC 3648)|426=Upgrade Req"
  144. . "uired (RFC 2817)|449=Retry With|500=Internal Server Error|501=Not Implem"
  145. . "ented|502=Bad Gateway|503=Service Unavailable|504=Gateway Timeout|505=HT"
  146. . "TP Version Not Supported|506=Variant Also Negotiates (RFC 2295)|507=Insu"
  147. . "fficient Storage (WebDAV) (RFC 4918)|509=Bandwidth Limit Exceeded|510=No"
  148. . "t Extended (RFC 2774)"
  149. ; Gather numeric response value
  150. RetValue := SubStr(RetValue,1,3)
  151. ; Parse through return codes and set according informations
  152. Loop,Parse,HttpRetCodes,|
  153. {
  154. HttpReturnCode := SubStr(A_LoopField,1,3) ; Numeric return value see above
  155. HttpReturnMsg := SubStr(A_LoopField,5) ; link for additional information
  156. if (RetValue=HttpReturnCode) {
  157. RetMsg := HttpReturnMsg
  158. break
  159. }
  160. }
  161. ; Global HttpQueryOps handling
  162. if strlen(HTTPQueryOps)>0 {
  163. ; Show full Header response (usefull for debugging)
  164. if (instr(HTTPQueryOps,"showHeader"))
  165. MsgBox % res
  166. ; Save the full Header response in a global Variable
  167. if (instr(HTTPQueryOps,"storeHeader"))
  168. global HttpQueryHeader := res
  169. ; Check for size updates to export to a global Var
  170. if (instr(HTTPQueryOps,"updateSize")) {
  171. Loop,Parse,res,`n
  172. If RegExMatch(A_LoopField,"Content-Length:\s+?(?P<Size>\d+)",full) {
  173. global HttpQueryFullSize := fullSize
  174. break
  175. }
  176. if (fullSize+0=0)
  177. HttpQueryFullSize := "size unavailable"
  178. }
  179. }
  180. ; Check for valid codes and drop exception if suspicious
  181. if !(InStr("100 200 201 202 302",RetValue)) {
  182. Result := RetValue " " RetMsg
  183. return StrLen(Result)
  184. }
  185. VarSetCapacity(BytesRead,4,0)
  186. fsize := 0
  187. Loop ; the receiver loop - rewritten in the need to enable
  188. { ; support for larger file downloads
  189. bc := A_Index
  190. VarSetCapacity(buffer%bc%,1024,0) ; setup new chunk for this receive round
  191. ReadFile := DllCall("wininet\InternetReadFile"
  192. ,"uInt",hRequest,"uInt",&buffer%bc%,"uInt",1024,"uInt",&BytesRead)
  193. ReadBytes := NumGet(BytesRead) ; how many bytes were received?
  194. If ((ReadFile!=0)&&(!ReadBytes)) ; we have had no error yet and received no more bytes
  195. break ; we must be done! so lets break the receiver loop
  196. Else {
  197. fsize += ReadBytes ; sum up all chunk sizes for correct return size
  198. sizeArray .= ReadBytes "|"
  199. }
  200. if (instr(HTTPQueryOps,"updateSize"))
  201. Global HttpQueryCurrentSize := fsize
  202. }
  203. sizeArray := SubStr(sizeArray,1,-1) ; trim last PipeChar
  204. VarSetCapacity( ( dReturn == true ) ? result : p1 ,fSize+1,0) ; reconstruct the result from above generated chunkblocks
  205. Dest := ( dReturn == true ) ? &result : &p1 ; to a our ByRef result variable
  206. Loop,Parse,SizeArray,|
  207. DllCall("RtlMoveMemory","uInt",Dest,"uInt",&buffer%A_Index%,"uInt",A_LoopField)
  208. , Dest += A_LoopField
  209. DllCall("WinINet\InternetCloseHandle", "uInt", hRequest) ; close all opened
  210. DllCall("WinINet\InternetCloseHandle", "uInt", hInternet)
  211. DllCall("WinINet\InternetCloseHandle", "uInt", hConnect)
  212. DllCall("FreeLibrary", "UInt", hModule) ; unload the library
  213. if ( dReturn == true ) {
  214. VarSetCapacity( result, -1 )
  215. ErrorLevel := fSize
  216. return Result
  217. } else
  218. return fSize ; return the size - strings need update via VarSetCapacity(res,-1)
  219. }

comments powered by Disqus