dR gave me a script and as I tested it with ia, I got several unhandled Exceptions, mostly in VarSetCapacy and NumPut/Get Functions.
Please have a look after it.
; show topix
SetBatchLines, -1
Gosub, InitVars
Gui,Add,Tab2,w780 h450 vForumTabs,
Gui,Tab
Gui,Add,CheckBox, y+10 x10 vAnnouncements Checked, Announcements
Gui,Add,CheckBox, yp x+10 vSticky Checked, Sticky
Gui,Add,CheckBox, yp x+10 vLocked Checked, Locked
Gui,Add,Radio, Group vMode x+10 yp Checked, All
Gui,Add,Radio,yp x+10, New only
Gui,Add,Statusbar
Gui,Show,w800,AHK Forum Tool
SB_SetParts(100,500,200)
SB_SetProgress(0,3,"Range1-100000 ")
SB_SetText( "Loading and parsing forum index file...", 2)
p := 0, url := ForumUrl, html := httpQuery( url )
while ( p := RegExMatch( html, "Jism`a)" forum_idx_needle ,M_, p == 0 ? 1 : p + strlen( M_ ) ) )
l_idx .= ( StrLen( l_Idx ) == 0 ? "" : "|" ) m_id, t_idx .= ( StrLen( t_Idx ) == 0 ? "" : "|" ) m_name
t_idx := RegExReplace( t_idx, "&", "&&" )
GuiControl,,ForumTabs, % "|" t_idx
Loop,Parse,l_idx,|
{
Gui,Tab, % A_Index
Gui, Add, ListView, h400 w760 x+10 y+10 Checked -Multi NoSortHdr NoSort ReadOnly -WantF2 vLV%A_LoopField%, DeleteID|Title|Created by|LastPoster|Posts|Views
url := ForumURL "viewforum.php?f=" A_LoopField
SB_SetText( "Getting data from " url, 2 )
SetTimer,showSize,10
html := httpQuery( url ), p := 0
SetTimer,showSize,Off
SB_SetText( "", 2 )
UpdateList( html, "LV" A_LoopField )
Gui,Tab
}
SB_SetProgress( 0, 3, "Hide" )
return
GuiClose:
GuiEscape:
Esc::
ExitApp
InitVars:
forum_idx_needle=
(LTrim Join Comments
(?<=class..forumlink..).*?(?<=a href..)(forum-(?P<ID>\d+)|viewforum.php.f.(?P<ID>\d+))
.*?(?<=class..forumlink..)(?P<Name>[^<]+)
)
allTopixNeedle=
(LTrim Join
((?<=href..viewtopic.php\?t=)(?P<ID>\d+)|(?<=href..topic)(?P<ID>\d+))
.*?(?<=class..topictitle..)(?P<Title>[^<]+)
.*?(?<=class..postdetails..)(?P<Cnt>\d+)
.*?(?<=class..name..)(<a[^>]+>)?(?P<PostCreator>[^<]+)
.*?(?<=class..postdetails..)(?P<Views>\d+)
.*?(?<=<span.class..postdetails.>).*?<[^>]+>(<a[^>]+>)?(?P<LastPoster>[^<]+)
)
ForumURL := "http://de.autohotkey.com/forum/"
httpQueryOps := "updateSize storeHeader"
Return
showSize:
SB_SetProgress(HttpQueryCurrentSize,3)
return
UpdateList( html, LV, p=0 ) {
Global allTopixNeedle
Gui, ListView, % LV
while ( p := RegExMatch( html, "Jism`a)" AllTopixNeedle ,M_, p == 0 ? 1 : p + strlen( M_ ) ) )
LV_Add( "", M_ID, M_Title, M_PostCreator, M_LastPoster, M_Cnt, M_Views )
Loop, 6
LV_ModifyCol( A_Index, "AutoHdr" )
}
; SB_SetProgress
; (w) by DerRaphael / Released under the Terms of EUPL 1.0
; see http://ec.europa.eu/idabc/en/document/7330 for details
SB_SetProgress(Value=0,Seg=1,Ops="")
{
; Definition of Constants
Static SB_GETRECT := 0x40a ; (WM_USER:=0x400) + 10
, SB_GETPARTS := 0x406
, SB_PROGRESS ; Container for all used hwndBar:Seg:hProgress
, PBM_SETPOS := 0x402 ; (WM_USER:=0x400) + 2
, PBM_SETRANGE32 := 0x406
, PBM_SETBARCOLOR := 0x409
, PBM_SETBKCOLOR := 0x2001
, dwStyle := 0x50000001 ; forced dwStyle WS_CHILD|WS_VISIBLE|PBS_SMOOTH
; Find the hWnd of the currentGui's StatusbarControl
Gui,+LastFound
ControlGet,hwndBar,hWnd,,msctls_statusbar321
if (!StrLen(hwndBar)) {
rErrorLevel := "FAIL: No StatusBar Control" ; Drop ErrorLevel on Error
} else If (Seg<=0) {
rErrorLevel := "FAIL: Wrong Segment Parameter" ; Drop ErrorLevel on Error
} else if (Seg>0) {
; Segment count
SendMessage, SB_GETPARTS, 0, 0,, ahk_id %hwndBar%
SB_Parts := ErrorLevel - 1
If ((SB_Parts!=0) && (SB_Parts<Seg)) {
rErrorLevel := "FAIL: Wrong Segment Count" ; Drop ErrorLevel on Error
} else {
; Get Segment Dimensions in any case, so that the progress control
; can be readjusted in position if neccessary
if (SB_Parts) {
VarSetCapacity(RECT,16,0) ; RECT = 4*4 Bytes / 4 Byte <=> Int
; Segment Size :: 0-base Index => 1. Element -> #0
SendMessage,SB_GETRECT,Seg-1,&RECT,,ahk_id %hwndBar%
If ErrorLevel
Loop,4
n%A_index% := NumGet(RECT,(a_index-1)*4,"Int")
else
rErrorLevel := "FAIL: Segmentdimensions" ; Drop ErrorLevel on Error
} else { ; We dont have any parts, so use the entire statusbar for our progress
n1 := n2 := 0
ControlGetPos,,,n3,n4,,ahk_id %hwndBar%
} ; if SB_Parts
If (InStr(SB_Progress,":" Seg ":")) {
hWndProg := (RegExMatch(SB_Progress, hwndBar "\:" seg "\:(?P<hWnd>([^,]+|.+))",p)) ? phWnd :
} else {
If (RegExMatch(Ops,"i)-smooth"))
dwStyle ^= 0x1
hWndProg := DllCall("CreateWindowEx","uint",0,"str","msctls_progress32"
,"uint",0,"uint", dwStyle
,"int",0,"int",0,"int",0,"int",0 ; segment-progress :: X/Y/W/H
,"uint",DllCall("GetAncestor","uInt",hwndBar,"uInt",1) ; gui hwnd
,"uint",0,"uint",0,"uint",0)
SB_Progress .= (StrLen(SB_Progress) ? "," : "") hwndBar ":" Seg ":" hWndProg
} ; If InStr Prog <-> Seg
; HTML Colors
Black:=0x000000,Green:=0x008000,Silver:=0xC0C0C0,Lime:=0x00FF00,Gray:=0x808080
Olive:=0x808000,White:=0xFFFFFF,Yellow:=0xFFFF00,Maroon:=0x800000,Navy:=0x000080
Red:=0xFF0000,Blue:=0x0000FF,Fuchsia:=0xFF00FF,Aqua:=0x00FFFF
If (RegExMatch(ops,"i)\bBackground(?P<C>[a-z0-9]+)\b",bg)) {
if ((strlen(bgC)=6)&&(RegExMatch(bgC,"i)([0-9a-f]{6})")))
bgC := "0x" bgC
else if !(RegExMatch(bgC,"i)^0x([0-9a-f]{1,6})"))
bgC := %bgC%
if (bgC+0!="")
SendMessage, PBM_SETBKCOLOR, 0
, ((bgC&255)<<16)+(((bgC>>8)&255)<<8)+(bgC>>16) ; BGR
,, ahk_id %hwndProg%
} ; If RegEx BGC
If (RegExMatch(ops,"i)\bc(?P<C>[a-z0-9]+)\b",fg)) {
if ((strlen(fgC)=6)&&(RegExMatch(fgC,"i)([0-9a-f]{6})")))
fgC := "0x" fgC
else if !(RegExMatch(fgC,"i)^0x([0-9a-f]{1,6})"))
fgC := %fgC%
if (fgC+0!="")
SendMessage, PBM_SETBARCOLOR, 0
, ((fgC&255)<<16)+(((fgC>>8)&255)<<8)+(fgC>>16) ; BGR
,, ahk_id %hwndProg%
} ; If RegEx FGC
If ((RegExMatch(ops,"(?P<In>[^ ])?range((?P<Lo>\-?\d+)\-(?P<Hi>\-?\d+))?",r))
&& (rIn!="-") && (rHi>rLo)) { ; Set new LowRange and HighRange
SendMessage,0x406,rLo,rHi,,ahk_id %hWndProg%
} else if ((rIn="-") || (rLo>rHi)) { ; restore defaults on remove or invalid values
SendMessage,0x406,0,100,,ahk_id %hWndProg%
} ; If RegEx Range
If (RegExMatch(ops,"i)\bEnable\b"))
Control, Enable,,, ahk_id %hWndProg%
If (RegExMatch(ops,"i)\bDisable\b"))
Control, Disable,,, ahk_id %hWndProg%
If (RegExMatch(ops,"i)\bHide\b"))
Control, Hide,,, ahk_id %hWndProg%
If (RegExMatch(ops,"i)\bShow\b"))
Control, Show,,, ahk_id %hWndProg%
ControlGetPos,xb,yb,,,,ahk_id %hwndBar%
ControlMove,,xb+n1,yb+n2,n3-n1,n4-n2,ahk_id %hwndProg%
SendMessage,PBM_SETPOS,value,0,,ahk_id %hWndProg%
} ; if Seg greater than count
} ; if Seg greater zero
If (regExMatch(rErrorLevel,"^FAIL")) {
ErrorLevel := rErrorLevel
Return -1
} else
Return hWndProg
}
; httpQuery-0-3-6.ahk
httpQuery(byref p1 = "", p2 = "", p3="", p4="")
{ ; v0.3.6 (w) Oct, 26 2010 by derRaphael / zLib-Style release
; currently the verbs showHeader, storeHeader, and updateSize are supported in httpQueryOps
; in case u need a different UserAgent, Proxy, ProxyByPass, Referrer, and AcceptType just
; specify them as global variables - mind the varname for referrer is httpQueryReferer [sic].
; Also if any special dwFlags are needed such as INTERNET_FLAG_NO_AUTO_REDIRECT or cache
; handling this might be set using the httpQueryDwFlags variable as global
global httpQueryOps, httpAgent, httpProxy, httpProxyByPass, httpQueryReferer, httpQueryAcceptType
, httpQueryDwFlags
; Get any missing default Values
;v0.3.6
; check for syntax
if ( VarSetCapacity(p1) != 0 )
dReturn:=true, result := "", lpszUrl := p1, POSTDATA := p2, HEADERS := p3
else
result := p1, lpszUrl := p2, POSTDATA := p3, HEADERS := p4
defaultOps =
(LTrim Join|
httpAgent=AutoHotkeyScript|httpProxy=0|httpProxyByPass=0|INTERNET_FLAG_SECURE=0x00800000
SECURITY_FLAG_IGNORE_UNKNOWN_CA=0x00000100|SECURITY_FLAG_IGNORE_CERT_CN_INVALID=0x00001000
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID=0x00002000|SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE=0x00000200
INTERNET_OPEN_TYPE_PROXY=3|INTERNET_OPEN_TYPE_DIRECT=1|INTERNET_SERVICE_HTTP=3
)
Loop,Parse,defaultOps,|
{
RegExMatch(A_LoopField,"(?P<Option>[^=]+)=(?P<Default>.*)",http)
if StrLen(%httpOption%)=0
%httpOption% := httpDefault
}
; Load Library
hModule := DllCall("LoadLibrary", "Str", "WinINet.Dll")
; SetUpStructures for URL_COMPONENTS / needed for InternetCrackURL
; http://msdn.microsoft.com/en-us/library/aa385420(VS.85).aspx
offset_name_length:= "4-lpszScheme-255|16-lpszHostName-1024|28-lpszUserName-1024|"
. "36-lpszPassword-1024|44-lpszUrlPath-1024|52-lpszExtrainfo-1024"
VarSetCapacity(URL_COMPONENTS,60,0)
; Struc Size ; Scheme Size ; Max Port Number
NumPut(60,URL_COMPONENTS,0), NumPut(255,URL_COMPONENTS,12), NumPut(0xffff,URL_COMPONENTS,24)
Loop,Parse,offset_name_length,|
{
RegExMatch(A_LoopField,"(?P<Offset>\d+)-(?P<Name>[a-zA-Z]+)-(?P<Size>\d+)",iCU_)
VarSetCapacity(%iCU_Name%,iCU_Size,0)
NumPut(&%iCU_Name%,URL_COMPONENTS,iCU_Offset)
NumPut(iCU_Size,URL_COMPONENTS,iCU_Offset+4)
}
; Split the given URL; extract scheme, user, pass, authotity (host), port, path, and query (extrainfo)
; http://msdn.microsoft.com/en-us/library/aa384376(VS.85).aspx
DllCall("WinINet\InternetCrackUrlA","Str",lpszUrl,"uInt",StrLen(lpszUrl),"uInt",0,"uInt",&URL_COMPONENTS)
; Update variables to retrieve results
Loop,Parse,offset_name_length,|
{
RegExMatch(A_LoopField,"-(?P<Name>[a-zA-Z]+)-",iCU_)
VarSetCapacity(%iCU_Name%,-1)
}
nPort:=NumGet(URL_COMPONENTS,24,"uInt")
; Import any set dwFlags
dwFlags := httpQueryDwFlags
; For some reasons using a selfsigned https certificates doesnt work
; such as an own webmin service - even though every security is turned off
; https with valid certificates works when
if (lpszScheme = "https")
dwFlags |= (INTERNET_FLAG_SECURE|SECURITY_FLAG_IGNORE_CERT_CN_INVALID
|SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)
; Check for Header and drop exception if unknown or invalid URL
if (lpszScheme="unknown") {
Result := "ERR: No Valid URL supplied."
Return StrLen(Result)
}
; Initialise httpQuery's use of the WinINet functions.
; http://msdn.microsoft.com/en-us/library/aa385096(VS.85).aspx
hInternet := DllCall("WinINet\InternetOpenA"
,"Str",httpAgent,"UInt"
,(httpProxy != 0 ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_DIRECT )
,"Str",httpProxy,"Str",httpProxyBypass,"Uint",0)
; Open HTTP session for the given URL
; http://msdn.microsoft.com/en-us/library/aa384363(VS.85).aspx
hConnect := DllCall("WinINet\InternetConnectA"
,"uInt",hInternet,"Str",lpszHostname, "Int",nPort
,"Str",lpszUserName, "Str",lpszPassword,"uInt",INTERNET_SERVICE_HTTP
,"uInt",0,"uInt*",0)
; Do we POST? If so, check for header handling and set default
if (Strlen(POSTDATA)>0) {
HTTPVerb:="POST"
if StrLen(Headers)=0
Headers:="Content-Type: application/x-www-form-urlencoded"
} else ; otherwise mode must be GET - no header defaults needed
HTTPVerb:="GET"
; Form the request with proper HTTP protocol version and create the request handle
; http://msdn.microsoft.com/en-us/library/aa384233(VS.85).aspx
hRequest := DllCall("WinINet\HttpOpenRequestA"
,"uInt",hConnect,"Str",HTTPVerb,"Str",lpszUrlPath . lpszExtrainfo
,"Str",ProVer := "HTTP/1.1", "Str",httpQueryReferer,"Str",httpQueryAcceptTypes
,"uInt",dwFlags,"uInt",Context:=0 )
; Send the specified request to the server
; http://msdn.microsoft.com/en-us/library/aa384247(VS.85).aspx
sRequest := DllCall("WinINet\HttpSendRequestA"
, "uInt",hRequest,"Str",Headers, "uInt",Strlen(Headers)
, "Str",POSTData,"uInt",Strlen(POSTData))
VarSetCapacity(header, 2048, 0) ; max 2K header data for httpResponseHeader
VarSetCapacity(header_len, 4, 0)
; Check for returned server response-header (works only _after_ request been sent)
; http://msdn.microsoft.com/en-us/library/aa384238.aspx
Loop, 5
if ((headerRequest:=DllCall("WinINet\HttpQueryInfoA","uint",hRequest
,"uint",21,"uint",&header,"uint",&header_len,"uint",0))=1)
break
If (headerRequest=1) {
VarSetCapacity(res,headerLength:=NumGet(header_len),32)
DllCall("RtlMoveMemory","uInt",&res,"uInt",&header,"uInt",headerLength)
Loop,% headerLength
if (*(&res-1+a_index)=0) ; Change binary zero to linefeed
NumPut(Asc("`n"),res,a_index-1,"uChar")
VarSetCapacity(res,-1)
} else
res := "timeout"
; Get 1st Line of Full Response
Loop,Parse,res,`n,`r
{
RetValue := A_LoopField
break
}
; No Connection established - drop exception
If (RetValue="timeout") {
html := "Error: timeout"
return -1
}
; Strip protocol version from return value
RetValue := RegExReplace(RetValue,"HTTP/1\.[01]\s+")
; List taken from http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
HttpRetCodes := "100=Continue|101=Switching Protocols|102=Processing (WebDAV) (RFC 2518)|"
. "200=OK|201=Created|202=Accepted|203=Non-Authoritative Information|204=No"
. " Content|205=Reset Content|206=Partial Content|207=Multi-Status (WebDAV)"
. "|300=Multiple Choices|301=Moved Permanently|302=Found|303=See Other|304="
. "Not Modified|305=Use Proxy|306=Switch Proxy|307=Temporary Redirect|400=B"
. "ad Request|401=Unauthorized|402=Payment Required|403=Forbidden|404=Not F"
. "ound|405=Method Not Allowed|406=Not Acceptable|407=Proxy Authentication "
. "Required|408=Request Timeout|409=Conflict|410=Gone|411=Length Required|4"
. "12=Precondition Failed|413=Request Entity Too Large|414=Request-URI Too "
. "Long|415=Unsupported Media Type|416=Requested Range Not Satisfiable|417="
. "Expectation Failed|418=I'm a teapot (RFC 2324)|422=Unprocessable Entity "
. "(WebDAV) (RFC 4918)|423=Locked (WebDAV) (RFC 4918)|424=Failed Dependency"
. " (WebDAV) (RFC 4918)|425=Unordered Collection (RFC 3648)|426=Upgrade Req"
. "uired (RFC 2817)|449=Retry With|500=Internal Server Error|501=Not Implem"
. "ented|502=Bad Gateway|503=Service Unavailable|504=Gateway Timeout|505=HT"
. "TP Version Not Supported|506=Variant Also Negotiates (RFC 2295)|507=Insu"
. "fficient Storage (WebDAV) (RFC 4918)|509=Bandwidth Limit Exceeded|510=No"
. "t Extended (RFC 2774)"
; Gather numeric response value
RetValue := SubStr(RetValue,1,3)
; Parse through return codes and set according informations
Loop,Parse,HttpRetCodes,|
{
HttpReturnCode := SubStr(A_LoopField,1,3) ; Numeric return value see above
HttpReturnMsg := SubStr(A_LoopField,5) ; link for additional information
if (RetValue=HttpReturnCode) {
RetMsg := HttpReturnMsg
break
}
}
; Global HttpQueryOps handling
if strlen(HTTPQueryOps)>0 {
; Show full Header response (usefull for debugging)
if (instr(HTTPQueryOps,"showHeader"))
MsgBox % res
; Save the full Header response in a global Variable
if (instr(HTTPQueryOps,"storeHeader"))
global HttpQueryHeader := res
; Check for size updates to export to a global Var
if (instr(HTTPQueryOps,"updateSize")) {
Loop,Parse,res,`n
If RegExMatch(A_LoopField,"Content-Length:\s+?(?P<Size>\d+)",full) {
global HttpQueryFullSize := fullSize
break
}
if (fullSize+0=0)
HttpQueryFullSize := "size unavailable"
}
}
; Check for valid codes and drop exception if suspicious
if !(InStr("100 200 201 202 302",RetValue)) {
Result := RetValue " " RetMsg
return StrLen(Result)
}
VarSetCapacity(BytesRead,4,0)
fsize := 0
Loop ; the receiver loop - rewritten in the need to enable
{ ; support for larger file downloads
bc := A_Index
VarSetCapacity(buffer%bc%,1024,0) ; setup new chunk for this receive round
ReadFile := DllCall("wininet\InternetReadFile"
,"uInt",hRequest,"uInt",&buffer%bc%,"uInt",1024,"uInt",&BytesRead)
ReadBytes := NumGet(BytesRead) ; how many bytes were received?
If ((ReadFile!=0)&&(!ReadBytes)) ; we have had no error yet and received no more bytes
break ; we must be done! so lets break the receiver loop
Else {
fsize += ReadBytes ; sum up all chunk sizes for correct return size
sizeArray .= ReadBytes "|"
}
if (instr(HTTPQueryOps,"updateSize"))
Global HttpQueryCurrentSize := fsize
}
sizeArray := SubStr(sizeArray,1,-1) ; trim last PipeChar
VarSetCapacity( ( dReturn == true ) ? result : p1 ,fSize+1,0) ; reconstruct the result from above generated chunkblocks
Dest := ( dReturn == true ) ? &result : &p1 ; to a our ByRef result variable
Loop,Parse,SizeArray,|
DllCall("RtlMoveMemory","uInt",Dest,"uInt",&buffer%A_Index%,"uInt",A_LoopField)
, Dest += A_LoopField
DllCall("WinINet\InternetCloseHandle", "uInt", hRequest) ; close all opened
DllCall("WinINet\InternetCloseHandle", "uInt", hInternet)
DllCall("WinINet\InternetCloseHandle", "uInt", hConnect)
DllCall("FreeLibrary", "UInt", hModule) ; unload the library
if ( dReturn == true ) {
VarSetCapacity( result, -1 )
ErrorLevel := fSize
return Result
} else
return fSize ; return the size - strings need update via VarSetCapacity(res,-1)
}