Seite 1 von 1

HTTP Requests

Verfasst: 13.02.2006 15:47
von real
Hi,

ich habe folgenden Code:

Code: Alles auswählen

Enumeration
  #wMain      ; Window
  #lSource    ; ListViewGadget
  #bRequest   ; Button
EndEnumeration

CreateGadgetList(OpenWindow(#wMain, 0, 0, 600, 400, #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget, "Pimp-The-Pimps")) 
AddKeyboardShortcut(#wMain,#PB_Shortcut_Return,13) 
ListViewGadget(#lSource,0,0,600,350)
ClearGadgetItemList(#lSource) 
ButtonGadget(#bRequest,0,350,600,50,"Nächster Schritt!") 

InitNetwork()

Repeat 
  Select WaitWindowEvent() 
    Case #PB_Event_CloseWindow
      End
    Case #PB_Event_Gadget 
      Select EventGadgetID() 
        Case #bRequest 
          Header.s = "GET http://www.the-pimps.de/ HTTP/1.0"+#CRLF$ 
          Header   + "Accept: image/gif, image/x-xbitmap, image/jpeg"+#CRLF$
          Header   + "Accept-Language: de"+#CRLF$
          Header   + "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1; .NET CLR 2.0.50727)"+#CRLF$
          Header   + "Host: www.the-pimps.de"+#CRLF$
          Header   + "Proxy-Connection: Keep-Alive"+#CRLF$+#CRLF$
          If CID: CloseNetworkConnection(CID):EndIf 
          CID = OpenNetworkConnection("www.the-pimps.de", 80) 
          If CID 
            SendNetworkString(CID,Header) 
          EndIf 
      EndSelect 
    Case #PB_Event_CloseWindow 
      quit = 1
  EndSelect 
  If CID
    Select NetworkClientEvent(CID)
    Case 2 
      Antwort.s = Space(8192) 
      If ReceiveNetworkData(CID, @Antwort, 8192)
        SID.s = Mid(Antwort, FindString (Antwort,"sid",0)+4, FindString (Antwort,Chr(34),FindString (Antwort,"sid",0))-FindString (Antwort,"sid",0)-4)
        AddGadgetItem(#lSource, -1, "SID "+SID+" erhalten!")
      EndIf
    EndSelect 
  EndIf
ForEver
Was soll es tun?
Es soll die Webseite www.the-pimps.de aufrufen und aus der html-Datei die sid ermitteln.

Wobei brauche ich Hilfe?
Wenn die Seite gelesen wird soll einmal die sid ausgegeben werden. Allerdings gibt er mir die scheinbar mehrmals aus.

Wie kann ich das zuverlässsig hinbekommen? Oder generell die Frage: Wie rufe ich erst die HTML-Datei KOMPLETT ab und werte sie dann aus?

P.S. Kompiliert mit PureBasic 3.94!

Dank & Gruß
René

Verfasst: 13.02.2006 16:54
von Laurin
Also bei mir funktioniert dein Code soweit. Eine SID kommt allerdings erst, wenn ich ein zweites Mal auf den Button geklickt habe.

Verfasst: 13.02.2006 17:05
von DarkDragon
Hab hier schon was, eventuell hilfts:

Code: Alles auswählen

InitNetwork()

#TIMEOUT = 1500

Procedure.s ReceiveLine(ConnectionID)
  Text.s = ""
  While char.b <> #LF
    char = 0
    ReceiveNetworkData(ConnectionID, @char, 1)
    If char <> 0
      Text.s + Chr(char)
    EndIf
  Wend
  
  ProcedureReturn RemoveString(RemoveString(Text, #CR$), #LF$)
EndProcedure

Procedure HTTPRequest(URL.s, *EndSize.LONG, PacketSize, *Callback)
  Protected Size.l, Data_.s, s.l, Method.s, File.s, Content.s, Text.s, Length.l, Line.s
  Protected CurSize.l, oSize.l, t.l, ConnectionID.l
  
  If Left(URL, 7) = "http://" : URL = Right(URL, Len(URL)-7) : EndIf
  s = FindString(URL, "/", 1)
  Host.s = "" : File.s = ""
  If s <> 0 : Host.s = Left(URL, s-1) : File.s = Right(URL, Len(URL)-s) : Else : Host = URL : EndIf
  
  s = FindString(File, "?", 1)
  If s <> 0
    Method.s = "POST"
    File = Left(File, s)
    Content.s = Right(File, Len(File)-(s+1))
  Else
    Method.s = "GET"
    Content.s = ""
  EndIf
  
  
  ConnectionID = OpenNetworkConnection(Host, 80)
  If ConnectionID
    Data_.s = Method+" /"+File+" HTTP/1.0"+#CRLF$
    Data_.s + "Host: "+Host+#CRLF$
    Data_.s + "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7"+#CRLF$
    If Content <> ""
      Data_.s + "Connection: close"+#CRLF$
      Data_.s + "Content-Type: text/html"+#CRLF$
      Data_.s + "Content: "+Content.s+#CRLF$+#CRLF$
    Else
      Data_.s + "Connection: close"+#CRLF$+#CRLF$
    EndIf
    
    SendNetworkString(ConnectionID, Data_)
    While NetworkClientEvent(ConnectionID) <> 2 : Delay(10) : Wend
    
    Length = 0
    Line.s = ""
    Repeat
      Line = ReceiveLine(ConnectionID)
      Select LCase(StringField(Line, 1, ":"))
        Case "content-length"
          
          Length = Val(Trim(StringField(Line, 2, ":")))
      EndSelect
    Until Len(Trim(Line)) <= 4
    
    Size = 0
    If Length <> 0
      
      *Result = AllocateMemory(Length)
      
      While Size < Length
        If CurSize > 0
          Size + CurSize
          If *Callback
            CallFunctionFast(*Callback, Size, Length)
          EndIf
        EndIf
        If Size > (Length-PacketSize)
          PacketSize = Length-Size
        EndIf
        If PacketSize > 0
        CurSize = ReceiveNetworkData(ConnectionID, *Result+Size, PacketSize)
        EndIf
      Wend
      
    Else
      
      *Buffer = AllocateMemory(PacketSize)
      *Result = AllocateMemory(1)
      t = ElapsedMilliseconds()
      While ElapsedMilliseconds()-t <= #TIMEOUT
        If NetworkClientEvent(ConnectionID) = 2
          CurSize = ReceiveNetworkData(ConnectionID, *Buffer, PacketSize)
          If CurSize > 0
            oSize = Size
            Size + CurSize
            *Result = ReAllocateMemory(*Result, Size)
            CopyMemory(*Buffer, *Result+oSize, CurSize)
            If *Callback
              CallFunctionFast(*Callback, Size, 0)
            EndIf
          EndIf
          t = ElapsedMilliseconds()
        EndIf
      Wend
      Length = Size
      
    EndIf
    
    *EndSize\l = Length
    If *Callback
      CallFunctionFast(*Callback, Size, Length)
    EndIf
    
    CloseNetworkConnection(ConnectionID)
    
    ProcedureReturn *Result
  EndIf
EndProcedure

Procedure HTTPRequest_Password(URL.s, *EndSize.LONG, PacketSize, Username.s, Password.s, *Callback)
  Protected Size.l, Data_.s, s.l, Method.s, File.s, Content.s, Text.s, Length.l, Line.s
  Protected CurSize.l, oSize.l, t.l, ConnectionID.l
  
  If Left(URL, 7) = "http://" : URL = Right(URL, Len(URL)-7) : EndIf
  s = FindString(URL, "/", 1)
  Host.s = "" : File.s = ""
  If s <> 0 : Host.s = Left(URL, s-1) : File.s = Right(URL, Len(URL)-s) : Else : Host = URL : EndIf
  
  s = FindString(File, "?", 1)
  If s <> 0
    Method.s = "POST"
    File = Left(File, s)
    Content.s = Right(File, Len(File)-(s+1))
  Else
    Method.s = "GET"
    Content.s = ""
  EndIf
  
  InputBuffer.s = Username+":"+Password
  OutputBuffer.s = Space(256)
  Base64Encoder(@InputBuffer, Len(InputBuffer), @OutputBuffer, 255)
  
  ConnectionID = OpenNetworkConnection(Host, 80)
  If ConnectionID
    Data_.s = Method+" /"+File+" HTTP/1.0" + #CRLF$
    Data_.s + "Host: "+Host + #CRLF$
    Data_.s + "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7" + #CRLF$
    Data_.s + "Authorization: Basic "+ OutputBuffer + #CRLF$
    If Content <> ""
      Data_.s + "Connection: close" + #CRLF$
      Data_.s + "Content-Type: text/html" + #CRLF$
      Data_.s + "Content: "+Content.s +#CRLF$ + #CRLF$
    Else
      Data_.s + "Connection: close" + #CRLF$ + #CRLF$
    EndIf
    
    SendNetworkString(ConnectionID, Data_)
    While NetworkClientEvent(ConnectionID) <> 2 : Delay(10) : Wend
    
    Length = 0
    Line.s = ""
    Repeat
      Line = ReceiveLine(ConnectionID)
      Select LCase(StringField(Line, 1, ":"))
        Case "content-length"
          
          Length = Val(Trim(StringField(Line, 2, ":")))
      EndSelect
    Until Len(Trim(Line)) <= 4
    
    Size = 0
    If Length <> 0
      
      *Result = AllocateMemory(Length)
      
      While Size < Length
        If CurSize > 0
          Size + CurSize
          If *Callback
            CallFunctionFast(*Callback, Size, Length)
          EndIf
        EndIf
        If Size > (Length-PacketSize)
          PacketSize = Length-Size
        EndIf
        If PacketSize > 0
        CurSize = ReceiveNetworkData(ConnectionID, *Result+Size, PacketSize)
        EndIf
      Wend
      
    Else
      
      *Buffer = AllocateMemory(PacketSize)
      *Result = AllocateMemory(1)
      t = ElapsedMilliseconds()
      While ElapsedMilliseconds()-t <= #TIMEOUT
        If NetworkClientEvent(ConnectionID) = 2
          CurSize = ReceiveNetworkData(ConnectionID, *Buffer, PacketSize)
          If CurSize > 0
            oSize = Size
            Size + CurSize
            *Result = ReAllocateMemory(*Result, Size)
            CopyMemory(*Buffer, *Result+oSize, CurSize)
            If *Callback
              CallFunctionFast(*Callback, Size, 0)
            EndIf
          EndIf
          t = ElapsedMilliseconds()
        EndIf
      Wend
      Length = Size
      
    EndIf
    
    *EndSize\l = Length
    If *Callback
      CallFunctionFast(*Callback, Size, Length)
    EndIf
    
    CloseNetworkConnection(ConnectionID)
    
    ProcedureReturn *Result
  EndIf
EndProcedure

*Buffer = HTTPRequest("http://www.bradan.net/", @Size, 16, 0)
Debug Size
Debug PeekS(*Buffer, Size)
FreeMemory(*Buffer)

Verfasst: 13.02.2006 17:34
von real
Oh Gott... Für mich als Anfänger ist der Code ziemlich schwer zu lesen. :( (zumal die Kommentierung fehlt) Außerdem zeigt mir das Debug-Fenster jedesmal nur eine "20575" an, die zweile Zeile - wo laut meiner Interpretation der HTML-Text stehen sollte - ist leer... Hab's mit verschiedenen URLs probiert.

Kannst Du die Vorgehensweise ein wenig erklären?

Danke

Verfasst: 13.02.2006 17:54
von DarkDragon
real hat geschrieben:Oh Gott... Für mich als Anfänger ist der Code ziemlich schwer zu lesen. :( (zumal die Kommentierung fehlt) Außerdem zeigt mir das Debug-Fenster jedesmal nur eine "20575" an, die zweile Zeile - wo laut meiner Interpretation der HTML-Text stehen sollte - ist leer... Hab's mit verschiedenen URLs probiert.

Kannst Du die Vorgehensweise ein wenig erklären?

Danke
Ja da hast du recht. In der Prozedur HTTPRequest wird zuerst die URL.s zerlegt für den Request:

Code: Alles auswählen

  If Left(URL, 7) = "http://" : URL = Right(URL, Len(URL)-7) : EndIf
  s = FindString(URL, "/", 1)
  Host.s = "" : File.s = ""
  If s <> 0 : Host.s = Left(URL, s-1) : File.s = Right(URL, Len(URL)-s) : Else : Host = URL : EndIf
 
  s = FindString(File, "?", 1)
  If s <> 0
    Method.s = "POST"
    File = Left(File, s)
    Content.s = Right(File, Len(File)-(s+1))
  Else
    Method.s = "GET"
    Content.s = ""
  EndIf
Dann wird die Verbindung geöffnet und der Request zusammengeklebt und gesendet:

Code: Alles auswählen

  ConnectionID = OpenNetworkConnection(Host, 80)
  If ConnectionID
    Data_.s = Method+" /"+File+" HTTP/1.0"+#CRLF$
    Data_.s + "Host: "+Host+#CRLF$
    Data_.s + "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7"+#CRLF$
    If Content <> ""
      Data_.s + "Connection: close"+#CRLF$
      Data_.s + "Content-Type: text/html"+#CRLF$
      Data_.s + "Content: "+Content.s+#CRLF$+#CRLF$
    Else
      Data_.s + "Connection: close"+#CRLF$+#CRLF$
    EndIf
   
    SendNetworkString(ConnectionID, Data_)
    While NetworkClientEvent(ConnectionID) <> 2 : Delay(10) : Wend
Dann wird der Header empfangen. ReceiveLine empfängt dabei eine Zeile(wird byte für byte gefiltert):

Code: Alles auswählen

    Length = 0
    Line.s = ""
    Repeat
      Line = ReceiveLine(ConnectionID)
      Select LCase(StringField(Line, 1, ":"))
        Case "content-length"
          
          ;Bei vielen Headern wird die Länge der Datei mitgesendet, diese
          ;methode ist dann sicherer.
          Length = Val(Trim(StringField(Line, 2, ":")))
      EndSelect
    Until Len(Trim(Line)) <= 4
Im nächsten Teil wird die sicherere Methode zum runterladen angewandt, wenn Length schon vorgegeben wurde:

Code: Alles auswählen

    Size = 0
    If Length <> 0
      
      *Result = AllocateMemory(Length)
     
      While Size < Length
        If CurSize > 0
          Size + CurSize
          If *Callback
            CallFunctionFast(*Callback, Size, Length)
          EndIf
        EndIf
        If Size > (Length-PacketSize)
          PacketSize = Length-Size
        EndIf
        If PacketSize > 0
        CurSize = ReceiveNetworkData(ConnectionID, *Result+Size, PacketSize)
        EndIf
      Wend
Die unsichere Methode folgt zugleich, wird meistens von Webservern bei HTML Dateien nicht mitgesendet:

Code: Alles auswählen

    Else
     
      *Buffer = AllocateMemory(PacketSize)
      *Result = AllocateMemory(1)
      t = ElapsedMilliseconds()
      While ElapsedMilliseconds()-t <= #TIMEOUT
        If NetworkClientEvent(ConnectionID) = 2
          CurSize = ReceiveNetworkData(ConnectionID, *Buffer, PacketSize)
          If CurSize > 0
            oSize = Size
            Size + CurSize
            *Result = ReAllocateMemory(*Result, Size)
            CopyMemory(*Buffer, *Result+oSize, CurSize)
            If *Callback
              CallFunctionFast(*Callback, Size, 0)
            EndIf
          EndIf
          t = ElapsedMilliseconds()
        EndIf
      Wend
      Length = Size
     
    EndIf
Im nachfolgenden wird die Datei, die nun im RAM liegt von der Prozedur zurückgegeben. Außerdem wird die Verbindung geschlossen.

Code: Alles auswählen

    *EndSize\l = Length
    If *Callback
      CallFunctionFast(*Callback, Size, Length)
    EndIf
    
    CloseNetworkConnection(ConnectionID)
    
    ProcedureReturn *Result
  EndIf
EndProcedure
HTTPRequest_Password() ist das selber für geschützte Verzeichnisse.

Wenn du bei der Debug-Ausgabe mal auf Kopieren klickst und das ganze was nun in der Zwischenablage in Notepad Einfügst siehst du den HTML code. Die Zahl bei der Debug Ausgabe ist die größe der Datei.

Ich weiß, ist ein wenig kurz erklärt, aber ich hoffe ich konnte helfen(hab gerade wenig Zeit und Kopfschmerzen).

Verfasst: 20.02.2006 10:27
von real
Funktioniert ganz super - leider wird der #LF nicht korrekt ausgegeben. (sondern als Rechteck) :(