#NoEnv #SingleInstance force #Persistent SetWorkingDir %A_ScriptDir% FileEncoding UTF-8 SetBatchLines, -1 ver := "1.1" url := "http://www.vpngate.net/api/iphone/" dst := A_Temp "\vpngate_servers.txt" tmpCfgPath := "C:\" Gui, Add, Text, x10 y10, Store .ovpn file(s) here: Gui, Add, Edit, r1 vCfgPath w340 x+m y+-18 ReadOnly, % tmpCfgPath Gui, Add, Button, x+m gSelectPath w60 Default, Choose Gui, Add, ListView, x10 r20 w530 Grid -LV0x10, ID|Country|IP|Score|Speed|Total users Gui, Add, Button, w110 x+m vDownloadServers gDownloadServers, Download servers Gui, Add, Button, w110 vSaveConfig gSaveConfig, Save config(s) Gui, Add, StatusBar, , Download servers first! LV_ModifyCol(1, "35 Integer Center") LV_ModifyCol(2, "80 Center") LV_ModifyCol(3, "100 Center") LV_ModifyCol(4, "90 Integer Center") LV_ModifyCol(5, "100 Center") LV_ModifyCol(6, "100 Integer Center") Gui, Show GuiControl, Disable, SaveConfig return SelectPath: FileSelectFolder, configurationPath, ::{20d04fe0-3aea-1069-a2d8-08002b30309d} if (configurationPath) GuiControl, Text, CfgPath, % configurationPath return DownloadServers: GuiControl, Disable, DownloadServers SB_SetText("Downloading list of servers. Please stand by...") DownloadFile(url, dst) FileRead, serverList, % dst GuiControl, Enable, DownloadServers GuiControl, Enable, SaveConfig SB_SetText("Servers downloaded!") ; Create an array out of the data with a leading cnt (as an id) ; to be able to retrieve the base64 later on from the listview entry cnt := 0 serverData := [] GuiControl, -Redraw, ServersLV Loop, Parse, serverList, `n, `r { line := A_LoopField ; Skip unnecessary lines (header, column definition, end, empty lines) StringLeft, firstChar, line, 1 if (firstChar = "*" or firstChar = "#" or firstChar = "") continue cnt += 1 ; Add the cnt as the first item for the current line line := cnt "," line ; Fill the array serverData.Push(line) ; Fill the listview parts := StrSplit(line, ",") speed := Format("{:.2f}", (parts[6] / (1024*1024))) " MB" ; ID (1), Country (8), IP (3), Score (4), Speed (6), Total users (11) LV_Add("", parts[1], parts[8], parts[3], parts[4], speed, parts[11]) } GuiControl, +Redraw, ServersLV return SaveConfig: ; Make sure our destination path exists! GuiControlGet, configurationPath, , CfgPath if (InStr(FileExist(configurationPath), "D")) { ; Make sure it end with a trailing backslash lastChar := SubStr(configurationPath, 0, 1) if (lastChar != "\") configurationPath .= "\" ControlGet, selectedItems, List, Selected, SysListView321 cntSelected := 0 saveSuccess := false Loop, Parse, selectedItems, `n { cntSelected += 1 parts := StrSplit(A_LoopField, A_Tab) serverID := parts[1] ; Get the base64 field from the serverData array via the serverID arrayEntry := serverData[serverID] entryParts := StrSplit(arrayEntry, ",") ; _.ovpn dstFile := configurationPath . entryParts[8] . "_" . entryParts[3] . ".ovpn" nBytes := Base64Dec(entryParts[16], bin) ; Write ovpn file File := FileOpen(dstFile, "w") File.RawWrite(bin, nBytes) File.Close() if (FileExist(dstFile)) saveSuccess := true } if (saveSuccess) SB_SetText(cntSelected . " server profile(s) saved!") else Msgbox, Unable to save the profile(s) in the chosen path!`nMaybe a permission problem? } else { Msgbox, First you have to choose a path to store the .ovpn file(s) in! } return GuiClose: ExitApp return ; By SKAN / 18-Aug-2017 ; https://www.autohotkey.com/boards/viewtopic.php?t=35964 Base64Dec(ByRef B64, ByRef Bin) { Local Rqd := 0, BLen := StrLen(B64) DllCall("Crypt32.dll\CryptStringToBinary", "Str", B64, "UInt", BLen, "UInt", 0x1 , "UInt", 0, "UIntP", Rqd, "Int", 0, "Int", 0) VarSetCapacity(Bin, 128), VarSetCapacity(Bin, 0), VarSetCapacity(Bin, Rqd, 0) DllCall("Crypt32.dll\CryptStringToBinary", "Str", B64, "UInt", BLen, "UInt", 0x1 , "Ptr", &Bin, "UIntP", Rqd, "Int", 0, "Int", 0) Return Rqd } ; https://autohotkey.com/board/topic/101007-super-simple-download-with-progress-bar/ DownloadFile(url, saveFileAs, overwrite:=True, useProgressBar:=True) { ; Check if the file already exists and if return if overwriting it isn't requested If (!overwrite && FileExist(saveFileAs)) return ; Check if the user wants a progressbar If (useProgressBar) { ; Initialize the WinHttpRequest Object webRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1") ; Download the header webRequest.Open("HEAD", url) webRequest.Send() ; Store the header which holds the file size in a variable finalSize := webRequest.GetResponseHeader("Content-Length") ; Create the progressbar and the timer Progress, H80, , Downloading..., %url% SetTimer, _UpdateProgressBar, 100 } ; Download the file UrlDownloadToFile, %url%, %saveFileAs% ; Remove the timer and the progressbar because the download has finished If (useProgressBar) { Progress, Off SetTimer, _UpdateProgressBar, Off } return ; The label that updates the progressbar _UpdateProgressBar: ; Get the current file size and tick currentSize := FileOpen(saveFileAs, "r").Length ; FileGetSize wouldn't return reliable results! currentSizeTick := A_TickCount ; Calculate the downloadspeed speed := Round((currentSize / 1024 - lastSize / 1024) / ((currentSizeTick - lastSizeTick) / 1000)) . " Kb/s" ; Store the current file size and tick for the next run lastSizeTick := currentSizeTick lastSize := FileOpen(saveFileAs, "r").Length ; Calculate percent done percentDone := Round(currentSize / finalSize * 100) ; Update the progress bar Progress, % percentDone, % percentDone "% done", % "Downloading... (" speed ")", % "Downloading (" percentDone "%)" return }