Reading web Pages
Blitz3D Forums/Blitz3D Programming/Reading web Pages
| ||
I'd like to write up a program that reads a web page to parse the information from it. I'm assuming that it would require the user32 decls commands, but I really don't understand any of them and there are so many that trying to research which ones I would need seems daunting. My intent is that the program would run in the background and would recognize a specific page (tab) and if the contents of that page changes then it would record it, probably into the clipboard? Or even a direct read into a string file which I could then parse and process. A lesser and acceptable solution would be that I could cause the read with some kind of command keypress (like shft-F1 or something that wouldn't conflict with windows or other applications) Can anyone help me by explaining what user32 commands I would use? And how to use them properly? When I look through the code archives and read the comments in the user32.decl archive there is a reference to http://msdn.microsoft.com/ to find information on the commands, but the site itself is so vast that I quickly get lost and overwhelmed. |
| ||
if i remember there was a few html parsers in the code archive, couple that with one o fthe other code snippets for retrieving a file from the internet and you got what you need. i'm not sure why you would need a user32 lib for that, it could be done without using the windows api. |
| ||
here is a snippet by mark to get an html page http://www.blitzbasic.com/codearcs/codearcs.php?code=21 i didnt see any html parsers for anything before blitzmax :( thats ok, if your dynamically creating websites using asp.net, php for example then you can output the page as xml, then you can use the xml parser offered here http://www.blitzbasic.com/codearcs/codearcs.php?code=1393 to parse the data into your game from your site. then when you need to send updates back to the site you could use the post http functions here http://www.blitzbasic.com/codearcs/codearcs.php?code=1278 then on your website just parse the post variables and update your database or whatever your using. there are other code snippets in the archive for doing that this is just a couple examples. |
| ||
I'm not too worried about parsers. What I've got is an online game that plays through facebook. The game itself allows you to run it without facebook. Basically its a text style wargame. One of the pages lists the planets in a system with information on each planet (who owns it, their ranking, player status, etc). There are 15 planets in each system. The player can then page through the "galaxy" which contains 499 pages, each page holding a system of 15 planets. there are about 100 galaxies and those grow as more players join. In game you can scan the planets and get information with a probe, but what I'm looking to try to do is just to collect the information presented on that system page so that I can use it. Each player is allowed to control 9 planets, but players generally place their planets apart so that they are in different systems. It is a huge hassle to write down where you find a players planet so that if you attack that player you know where all his other planets are to monitor them to see if they are online, or if the ships on those planets suddenly disapear suggesting they are going to reinforce a planet you are attacking. What I was looking to do was to have a program that would run in the background and as you changed pages (systems) by clicking the next and previous button it would record all the viewable planet data and who owns them and their status, etc. Then I would just flip through the pages and record that info so I could then call up information on a specific player. I thought that i would have to use the windows api commands to first identify the firefox tab I am using. It would monitor it for page changes and then record (parse) the info into a database. I've figured out how to read from the clipboard and one option was to just do a copy/paste type style, but I'd like to eliminate that manual interaction if possible. Is that making sense? I thought that I'd need the windows api to identify the window or tab i was working from and to be able to read from that window/tab. I'd rather not make calls to the game server itself because they are very strict on bot cheating. Simply READING information on a screen for data use is not illegal, but automatic actions to the server could be construed as botting, or cheating. |
| ||
ah i got ya. but im not sure on a couple things. the program you are making is it just a background service or is there and actual game that goes with it. otherwise why not just make it in php. but i know where you're coming from i decided pretty recently to start making games for facebook myself but realized blitzmax and even blitz i was having just too many obstacles to keep the facebook app and the game synced up. One thing i did do similar to what your doing is i had set up a small server app on my webserver and ran my facebook app as an iframe. anytime someone made a change on the webpage it was posted to my server app and then my Blitz app would be sent the info from the server. I suppose its a decent way around using windows api. I figure if your going to go that far perhaps you should just create a sandbox and run your blitz3d app as a browser object. I gave up on the hassle recently and decided it was easier to write a game in java. lol |
| ||
The game already exists, Starfleet Commander, and I'm just trying to figure a way to manage the data so that i can use it in game by reading the information out of firefox. If you are interested to try it, then use this link and I'll get credit for a new crew member (you can only get crew member credits from new players, its not one of those spam whore games where you have to get all your friends to join with you like Mafia Wars and such) http://apps.facebook.com/starfleet_commander/?ref_id=620769623&ref_type=link If you do go into it then look at the "Fleets" page and you can see what I'm trying to capture to sift through. The only reason I post the link is so you can see what I'm talking about. Not trying to promote the game in some way that would be contrary to spamming rules. I will get the benefit of a new crew member, but that is not the intent, just a useful side effect for me. Being a new player you won't have much fuel to explore the galaxy with (it costs 10 hydro to change pages) but you should get the idea. I'm interested in collecting that planet data to track other players. |
| ||
very cool app |
| ||
I used to play an MMO in which certain stats were available through a webpage. I wrote a simple program that would etract tehe info I needed by downloading the page (with Blitzget I think it was) and then reading through the download (which was pure ascii saved as a .dat file and read with the basic OpenFile() and ReadLine() etc. I would search for the required html tags and so on, then extract the correct parts from strings. Most certainly not the best or most efficient means of accomplishing this but it was simple enough and did the trick. I could dig out my old code if you needed to see it, though it was only gfor my own personal use and was very rough and did not look at all prettified :) |
| ||
Thanks malice! the only thing I'm concerned about is it calling their site for the information. These guys are fanatical against any kind of external programs that run things in the game with automatic commands. It's ok compile the data, run sims, etc, but anything that would automatically push buttons, send fleets, probe, load pages, etc would probably be construed as cheating and their methods to handle what they consider as cheaters is pretty draconian. The reset your stuff back to 0 and make you start over. Because of the nature of the game they can't give you your stuff back if they screw up (many have claimed they have but they claim they haven't) because other players could move into the areas you once "lived". I'm just afriad that if they detected a call to their website that wasn't from something recognizeable like firefox, explorer, etc they'd just assume it was some form of cheat. That's why I'm looking for a way to read the data unobtrusively. At this point I'm just working with copy/paste and plan to have the clipboard monitored for changes to automatically parse new info and store it. If I can get the time to sit down and do it, lol. |
| ||
Look up where each browser's cache is stored -- you should be able to read pages from there. You may have to parse an index file to determine which cached page relates to which site. This whole idea probably won't be easy. This program does it, for example, and you'll see links to readers for other browser caches too: http://www.nirsoft.net/utils/chrome_cache_view.html Another way to do it might be to just read through the whole cache (bear in mind that it won't be in the same hard-coded path for everybody), discarding files over a certain size, and check for the <TITLE> tag, and/or some other more reliable information from the page. |
| ||
the only thing I'm concerned about is it calling their site for the information. These guys are fanatical against any kind of external programs that run things in the game with automatic commands. Right.. In my case the website where I was 'grabbing' the info from was purely game-related stats that were available fdor that purpose. Since even through blitz, the effect is the same as with a browser* then there shouldn't be any problem. No activity was done to the data and nothing was sent as any form of message to the server except the standard "I am retrieving info" stuff that the Browser would do on viewing the page. However, I'm no expert and don't know just how fanatical your games' guys are, so I agree with erring on the side of caution. My code did not even locate or associate itself with the database per se, because it just grabbed the final pager source after phop scripts and so on had run to provide the web output. If you would need to acccess data directly rather than from a more accessible web page, then yeah likely to be a lot more complex and risky if such methiods are frowned upon by the server people :S _________ *That is - a connection is made through port 80 for Downloadig only, the content is read and copied to the client machine. |
| ||
Here's the code I used anyway... I havent made any notes or anything as it was just something 'quick and easy' for my own use. It's pretty horrible to look at, but if you need to asak anything about it, feel free :D Graphics 640, 480, 16, 2 SetBuffer FrontBuffer() Global Upd%=Input$("Update Frequency (Minutes): ") Upd=Upd*60000 Global Fix$=" * " Const JOSSH1$="http://www.jossh.com/jgeng/PilotViewer.aspx?list=onlinepilotsonly" Const JOSSH2$="http://www.jossh.com/jgeng/PilotViewer.aspx?p=" Const TempFileName$="~temp.TMP" Global Logfile=WriteFile("Log.txt") Global FirstRun=True Global StartOfSol$="td bgcolor="+Chr$(34)+"#000022" Global StartOfOct$="td bgcolor="+Chr$(34)+"#220000" Global StartOfQuant$="td bgcolor="+Chr$(34)+"#002200" Const EndOfTable$="</tr>" Const PilotStartString$="/media/registry" Const RegistryEndString$=".gif" Const PilotNamePrefix$="/jgeng/pilotviewer.aspx?p=" Const PilotNameSuffix$="</a><br>" Const PilotKillSolLINEPref$=">solrain kills</td>" Const PilotKillOctLINEPref$=">octavius kills</td>" Const PilotKillQuantLINEPref$=">quantar kills</td>" Const DeathLINEPref$=">deaths</td>" Const LandingLINEPref$=">landings</td>" Const LaunchLINEPref$=">launches</td>" Const MissionLINEPref$=">missions complete</td>" Const DiscoLINEPref$=">disconnects</td>" Const ValuePref$=">" Const ValueSuf$="</td>" Const PilotLaunchPref$="</a><br>" Const PilotDeathPref$="</a><br>" Const PilotLandingPref$="</a><br>" Const PilotDiscoPref$="</a><br>" Const PilotMissionPref$="</a><br>" Const FactionSol$="Solrain" Const FactionOct$="Octavius" Const FactionQuant$="Quantar" Const convertCiv$="none" Const convertHG$="honor_guard" Const convertPirate$="pirate" Const Reg_Civ$="Civillian" Const Reg_HG$="Military" Const Reg_Rat$="Pirate" Global Pilot$ Global Faction$ Global Registry$ Global OpenTemp Global OpenTemp2 Global delname$ Type LastPilots Field Name$ Field Fact$ Field Reg$ Field Docked% Field DockCount% Field LaunchCount% Field MissionCount% Field DeathCount% Field KillCountS% Field KillCountO% Field KillCountQ% Field DiscoCount% End Type Type Pilots Field Name$ Field Fact$ Field Reg$ Field Docked% Field DockCount% Field LaunchCount% Field MissionCount% Field DeathCount% Field KillCountS% Field KillCountO% Field KillCountQ% Field DiscoCount% End Type Global Begin=False Global UpdateTime=MilliSecs()-(Upd+5000) LogData("COMMENCE","TRACKER","START LOG","NO DATA",True) While Not KeyDown(1) Delay 5 If ((MilliSecs()-UpdateTime)>Upd) UpdateTime=MilliSecs() LogData("UPDATE","CONNECTING", "JOSSH","START",True) If (FileType(CurrentDir$()+"~Temp.TMP")) DeleteFile CurrentDir$()+"~Temp.TMP" End If Download(JOSSH1$,CurrentDir$(),TempFileName$) LogData("DOWNLOADED","JOSSH SERVER", "ONLINE ONLY","END",False) OpenTemp=ReadFile(TempFileName$) LogData("PROCESSING","JOSSH DATA", "ALL PILOTS","START",False) While Not Eof(OpenTemp) Delay 5 Registry$="INVALID REGISTRY ERROR" Pilot$="" t$=ReadLine$(OpenTemp) ;t$=Lower$(t$) If Instr(Lower$(t$),StartOfSol$) Begin=True Faction$=FactionSol$ LogData("RETRIEVING","JOSSH DATA", "SOLRAIN","PILOTS",False) CharPosition=FindPilotEnd(t$) While (Len(t$)>90) Delay 5 Registry$=FindPilotReg$(t$) Pilot$=FindPilotName$(t$) Color 0,0,255 LogData("ONLINE PILOT",Pilot$,Faction$,Registry$,False) OnlinePilots(Pilot$,Faction$,Registry$) t$=Right$(t$,Len(t$)-CharPosition) CharPosition=FindPilotEnd(t$) Wend End If If Instr(Lower$(t$),StartOfOct$) Faction$=FactionOct$ LogData("RETRIEVING","JOSSH DATA", "OCTAVIUS","PILOTS",False) Color 255,0,0 CharPosition=FindPilotEnd(t$) While (Len(t$)>90) Delay 5 Registry$=FindPilotReg$(t$) Pilot$=FindPilotName$(t$) LogData("ONLINE PILOT",Pilot$,Faction$,Registry$,False) OnlinePilots(Pilot$,Faction$,Registry$) t$=Right$(t$,Len(t$)-CharPosition) CharPosition=FindPilotEnd(t$) Wend EndIf If Instr(Lower$(t$),StartOfQuant$) Faction$=FactionQuant$ LogData("RETRIEVING","JOSSH DATA", "QUANTAR","PILOTS",False) Color 0,255,0 CharPosition=FindPilotEnd(t$) While (Len(t$)>90) Delay 5 Registry$=FindPilotReg$(t$) Pilot$=FindPilotName$(t$) LogData("ONLINE PILOT",Pilot$,Faction$,Registry$,False) OnlinePilots(Pilot$,Faction$,Registry$) t$=Right$(t$,Len(t$)-CharPosition) CharPosition=FindPilotEnd(t$) Wend End If If (Instr(Lower$(t$),EndOfTable$) And (Begin)) LogData("PROCESSING","JOSSH DATA", "END OF FILE","END",False) Begin=False SeekFile(OpenTemp,Eof(OpenTemp)) Exit End If Wend Begin=False CloseFile OpenTemp DeleteFile TempFileName$ If (FirstRun) FirstRun=False End If Color 255,255,255 LogData("PROCESSING","JOSSH DATA", "ALL PILOTS","END",False) LogData("CHECKING","PILOTS", "LOGGED","OFF",False) CheckOffline() For ResetPs.LastPilots=Each LastPilots Delete ResetPs Next For SwapP.Pilots = Each Pilots Delay 5 NewOP.LastPilots=New LastPilots NewOP\Name$=SwapP\Name$ NewOP\Reg$=SwapP\Reg$ NewOP\Fact$=SwapP\Fact$ NewOP\Docked%=SwapP\Docked% NewOP\DockCount%=SwapP\DockCount% NewOP\KillCountS%=SwapP\KillCountS% NewOP\KillCountO%=SwapP\KillCountO% NewOP\KillCountQ%=SwapP\KillCountQ% NewOP\DeathCount%=SwapP\DeathCount% NewOP\MissionCount%=SwapP\MissionCount% NewOP\LaunchCount%=SwapP\LaunchCount% NewOP\DiscoCount%=SwapP\DiscoCount% Next For ResetnPs.Pilots=Each Pilots Delete ResetnPs Next LogData("IDLE","WAITING", "NEXT UPDATE","IDLE",True) Delay 45 End If Delay 5 ;Flip Wend End Function FindPilotReg$(FactionString$) Delay 5 Local nStart=Instr(Lower$(FactionString$),PilotStartString$) If nStart=0 Then nStart=1 Local nEnd=Instr(Lower$(FactionString$),RegistryEndString$,nStart) Local Substring$=Mid$(Lower$(FactionString$),nStart,(nEnd-nStart)) Return Convert$(Right$(Substring$,Len(Substring$)-16)) End Function Function FindPilotName$(FactionString$) Delay 5 Local nStart=Instr(Lower$(FactionString$),PilotNamePrefix$) nStart=nStart+26 Local nEnd=Instr(Lower$(FactionString$),PilotNameSuffix$,nStart) Local Substring$=Mid$(FactionString$,nStart,(nEnd-nStart)) Return Left$(Substring$,(Len(Substring$)/2)-1) End Function Function FindPilotEnd(FactionString$) Return Instr(Lower$(FactionString$),PilotNameSuffix$) End Function Function Convert$(registrystring$) registrystring$=Lower$(registrystring$) Select registrystring$ Case convertCiv$ Return Reg_Civ$ Case convertHG$ Return Reg_HG$ Default Return Reg_Rat$ End Select End Function Function OnlinePilots(PilotName$,PilotFact$,PilotReg$) Local Found=False Fix$=" * " If PilotReg$=Reg_Civ$ Fix$=" " End If NewP.Pilots=New Pilots NewP\Name$=PilotName$ NewP\Fact$=PilotFact$ NewP\Reg$=PilotReg$ If (FileType(CurrentDir$()+"~Temp.TMP")) DeleteFile CurrentDir$()+"~Temp.TMP" End If UpdateKDL(NewP.Pilots) If (FirstRun) LogData(PilotName$,PilotFact$,PilotReg$,"ALREADY ON",True) Else For CheckP.LastPilots=Each LastPilots If CheckP\Name$=PilotName$ LogData(PilotName$,PilotFact$,PilotReg$,"ON PREV",False) Found=True CheckKDL(NewP.Pilots,CheckP.LastPilots) If PilotReg$<>CheckP\Reg$ LogData(PilotName$,PilotFact$,"CHANGED","REGISTRY",True) EndIf Exit End If Next If Not (Found) LogData(PilotName$,PilotFact$,PilotReg$,"NOT ON PRV",False) LogData(PilotName$,PilotFact$,PilotReg$,"NOW ONLINE",True) End If End If End Function Function CheckOffline() For iterOld.LastPilots=Each LastPilots Online=False ThisName$=iterOld\Name$ OldFaction$=iterOld\Fact$ For iterNew.Pilots =Each Pilots Delay 5 If ThisName$=iterNew\Name$ Online=True Exit End If Next If (Not(Online) ) Select OldFaction$ Case FactionSol$ Color 0,0,255 Case FactionOct$ Color 255,0,0 Case FactionQuant$ Color 0,255,0 End Select LogData(ThisName$,"IS NOT","ONLINE","ANYMORE",True) End If Color 255,255,255 Next End Function Function UpdateKDL(GetPilot.Pilots) Delay 5 LogData("CONNECT","JOSSH DATA","PILOT",GetPilot\Name$,False) Download(JOSSH2$+GetPilot\Name$,CurrentDir$(),TempFileName$) LogData("UPDATING","JOSSH DATA","PILOT",GetPilot\Name$,False) OpenTemp2=ReadFile(CurrentDir$()+TempFileName$) While Not Eof(OpenTemp2) Delay 5 r$=ReadLine$(OpenTemp2) If Instr(Lower$(r$),PilotKillSolLINEPref$) r2$=ReadLine$(OpenTemp2) GetPilot\KillCountS%=GetResult%(r2$) LogData("NEW DATA",GetPilot\Name$,"SOL KILLS",GetPilot\KillCountS,False) End If If Instr(Lower$(r$),PilotKillOctLINEPref$) r2$=ReadLine$(OpenTemp2) GetPilot\KillCountO%=GetResult%(r2$) LogData("NEW DATA",GetPilot\Name$,"OCT KILLS",GetPilot\KillCountO,False) End If If Instr(Lower$(r$),PilotKillQuantLINEPref$) r2$=ReadLine$(OpenTemp2) GetPilot\KillCountQ%=GetResult%(r2$) LogData("NEW DATA",GetPilot\Name$,"QUANT KILLS",GetPilot\KillCountQ,False) End If If Instr(Lower$(r$),DeathLINEPref$) r2$=ReadLine$(OpenTemp2) GetPilot\DeathCount%=GetResult%(r2$) LogData("NEW DATA",GetPilot\Name$,"DEATHS",GetPilot\DeathCount,False) End If If Instr(Lower$(r$),LaunchLINEPref$) r2$=ReadLine$(OpenTemp2) GetPilot\LaunchCount%=GetResult%(r2$) LogData("NEW DATA",GetPilot\Name$,"LAUNCHES",GetPilot\LaunchCount,False) End If If Instr(Lower$(r$),LandingLINEPref$) r2$=ReadLine$(OpenTemp2) GetPilot\DockCount%=GetResult%(r2$) LogData("NEW DATA",GetPilot\Name$,"LANDINGS",GetPilot\DockCount,False) End If If Instr(Lower$(r$),DiscoLINEPref$) r2$=ReadLine$(OpenTemp2) GetPilot\DiscoCount%=GetResult%(r2$) LogData("NEW DATA",GetPilot\Name$,"DISCONNECTS",GetPilot\DiscoCount,False) End If If Instr(Lower$(r$),MissionLINEPref$) r2$=ReadLine$(OpenTemp2) GetPilot\MissionCount%=GetResult%(r2$) LogData("NEW DATA",GetPilot\Name$,"MISSIONS",GetPilot\MissionCount,False) ;NO MORE TO FIND SeekFile(OpenTemp2,FileSize(OpenTemp2)) Exit End If Wend LogData("COMPLETED","JOSSH DATA","PILOT",GetPilot\Name$,False) CloseFile OpenTemp2 DeleteFile TempFileName$ End Function Function CheckKDL(CheckN.Pilots,CheckO.LastPilots) Delay 5 Local KillSolDiff=0 Local KillOctDiff=0 Local KillQuantDiff=0 Local LaunchDiff=0 Local DeathDiff=0 Local DockDiff=0 Local MissionDiff=0 Local DiscoDiff=0 If CheckO\Name$=CheckN\Name$ LogData("CHECKING",CheckN\Name$,"FOR STAT","UPDATES",False) KillSolDiff=(CheckN\KillCountS%-CheckN\KillCountS%) LogData("NEW S KILL",CheckN\KillCountS%,"OLD S KILL",CheckO\KillCountS%,False) KillOctDiff=(CheckN\KillCountO%-CheckN\KillCountO%) LogData("NEW O KILL",CheckN\KillCountO%,"OLD O KILL",CheckO\KillCountO%,False) KillQuantDiff=(CheckN\KillCountQ%-CheckN\KillCountQ%) LogData("NEW Q KILL",CheckN\KillCountQ%,"OLD Q KILL",CheckO\KillCountQ%,False) LaunchDiff=(CheckN\LaunchCount%-CheckN\LaunchCount%) LogData("NEW LAUNCH",CheckN\LaunchCount%,"OLD LAUNCH",CheckO\LaunchCount%,False) DeathDiff=(CheckN\DeathCount%-CheckN\DeathCount%) LogData("NEW DEATH",CheckN\DeathCount%,"OLD DEATH",CheckO\DeathCount%,False) DockDiff=(CheckN\DockCount%-CheckN\DockCount%) LogData("NEW LANDING",CheckN\DockCount%,"OLD LANDING",CheckO\DockCount%,False) MissionDiff=(CheckN\MissionCount%-CheckO\MissionCount%) LogData("NEW MISSION",CheckN\MissionCount%,"OLD MISSION",CheckO\MissionCount%,False) DiscoDiff=(CheckN\DiscoCount%-CheckO\DiscoCount%) LogData("NEW DISCO",CheckN\DiscoCount%,"OLD DISCO",CheckO\DiscoCount%,False) If KillSolDiff>0 Color 128,128,255 LogData(CheckN\Name$,"HAS KILLED",KillSolDiff,"SOLRAINS",True) End If If KillOctDiff>0 Color 255,128,128 LogData(CheckN\Name$,"HAS KILLED",KillOctDiff,"OCTAVIANS",True) End If If KillQuantDiff>0 Color 128,255,128 LogData(CheckN\Name$,"HAS KILLED",KillQuantDiff,"QUANTARS",True) End If If LaunchDiff>0 Color 128,255,255 LogData(CheckN\Name$,"LAUNCHED",LaunchDiff,"TIMES",True) EndIf If DockDiff>0 Color 128,255,255 LogData(CheckN\Name$,"DOCKED",DockDiff,"TIMES",True) EndIf If DeathDiff>0 Color 255,255,128 LogData(CheckN\Name$,"DIED",DeathDiff,"TIMES",True) EndIf If DiscoDiff>0 Color 255,128,255 LogData(CheckN\Name$,"DISCONNECTED",DiscoDiff,"TIMES",True) EndIf If MissionDiff>0 Color 128,128,128 LogData(CheckN\Name$,"COMPLETED",MissionDiff,"MISSIONS",True) LogData("COMPARISON",CheckN\Name$,"COMPLETE","OKAY",True) EndIf End If End Function Function GetResult%(Statstring$) nstart=Instr(Lower$(Statstring$),ValuePref$) nend=Instr(Lower$(Statstring$),ValueSuf$) Return Int%(Mid$(Statstring$,nstart+1,((nEnd)-nStart))) End Function ; NETWORK CODE ;============================================================================================= ;link$ - The link. You may enter the link just like you enter it ; in your browser. Very tolerant. No http:// required. ;savepath$ - The path where the file should be saved ;savefile$ - The filename of the saved file. When given "", it will ; be named like the file in the link$. Function Download(link$, savepath$ = "", savefile$ = "") ;Strip protocol and return false if not "http" inst = Instr(link$, "://") If inst Then If Lower(Trim(Left(link$, inst - 1))) <> "http" Then Return False link$ = Right(link$, Len(link$) - inst - 2) EndIf ;Seperate host from link inst = Instr(link$, "/") If inst = 0 Then Return False host$ = Trim(Left(link$, inst - 1)) link$ = Trim(Right(link$, Len(link$) - inst + 1)) ;Seperate path and file from the link For i = Len(link$) To 1 Step -1 If Mid(link$, i, 1) = "/" Then link_path$ = Trim(Left(link$, i)) link_file$ = Right(link$, Len(link$) - i) Exit EndIf Next If link_file$ = "" Then Return False If savefile$ = "" Then savefile$ = link_file$ ;Open TCP stream tcp = OpenTCPStream(host$, 80) If tcp = 0 Then Return False WriteLine tcp, "GET " + link_path$ + link_file$ + " HTTP/1.1" + Chr(13) + Chr(10) + "Host: " + host$ + Chr(13) + Chr(10) + "User-Agent: Download_Function_By_DevilsChild" + Chr(13) + Chr(10) ;Download file l$ = ReadLine(tcp) inst1 = Instr(l$, " ") inst2 = Instr(l$, " ", inst1 + 1) num = Mid(l$, inst1, inst2 - inst1) Select num Case 200 conlen = -1 chunk = False Repeat l$ = Trim(ReadLine(tcp)) If l$ = "" Then Exit inst = Instr(l$, ":") l1$ = Trim(Left(l$, inst - 1)) l2$ = Trim(Right(l$, Len(l$) - inst)) Select Lower(l1$) Case "content-length" conlen = l2$ Case "transfer-encoding" If Lower(l2$) = "chunked" Then chunk = True End Select checkstream(tcp) Forever If conlen = 0 Then file = WriteFile(savepath$ + savefile$) CloseFile file CloseTCPStream tcp Return True ElseIf conlen > 0 Then file = WriteFile(savepath$ + savefile$) bnk = CreateBank(4096) pos = 0 Repeat avail = conlen - pos If avail > 4096 Then ReadBytes bnk, tcp, 0, 4096 WriteBytes bnk, file, 0, 4096 pos = pos + 4096 Else ReadBytes bnk, tcp, 0, avail WriteBytes bnk, file, 0, avail Exit EndIf checkstream(tcp) Forever FreeBank bnk CloseFile file CloseTCPStream tcp Return True ElseIf chunk Then file = WriteFile(savepath$ + savefile$) bnk = CreateBank(4096) Repeat l$ = Trim(Upper(ReadLine(tcp))) ln = 0 For i = 1 To Len(l$) ln = 16 * ln + Instr("123456789ABCDEF", Mid$(l$, i, 1)) Next If ln = 0 Then Exit If BankSize(bnk) < ln Then ResizeBank bnk, ln ReadBytes bnk, tcp, 0, ln WriteBytes bnk, file, 0, ln ReadShort(tcp) checkstream(tcp) Forever FreeBank bnk CloseFile file CloseTCPStream tcp Return True Else CloseTCPStream tcp Return False EndIf Case 301, 302 Repeat l$ = Trim(ReadLine(tcp)) If l$ = "" Then Exit inst = Instr(l$, ":") l1$ = Trim(Left(l$, inst - 1)) l2$ = Trim(Right(l$, Len(l$) - inst)) Select Lower(l1$) Case "location" CloseTCPStream tcp Return Download(l2$, savepath$, savefile$) End Select checkstream(tcp) Forever Default CloseTCPStream tcp Return False End Select End Function Function checkstream(stream) Delay 5 If Eof(stream)<=-1 RuntimeError "Connection Lost. Download failed" End End If End Function Function LogData(dt1$,dt2$,dt3$,dt4$,PrintToScreen=False) Local concatA$=Fix$+Chr$(9)+" "+LSet(CurrentTime$(),9) Local concatB$=" "+Chr$(9)+" " Local concatC$=LSet(dt1$,12)+concatB$ Local concatD$=LSet(dt2$,12)+concatB$ Local concatE$=LSet(dt3$,12)+concatB$ Local concatF$=LSet(dt4$,12)+concatB$+Right$(Fix$,Len(Fix$)-1) Local Concat$=concatA$+concatB$+concatC$+concatD$+concatE$+concatF$ Logfile=OpenFile("Log.txt") SeekFile(Logfile,FileSize("Log.txt")) WriteLine(Logfile,Concat$) CloseFile(Logfile) If (PrintToScreen) Print Concat$ End If End Function |