sunny: Externe Seite einer Axis-Kamera-Applikation auslesen

Guten Morgen,

wahrscheinlich gibt es hier wohl kaum jemanden der dasselbe wie ich schon einmal "basteln" hat müssen, aber vielleicht kann mir trotzdem jemand auf die Sprünge helfen.

Es geht darum dass wir mehrere Axis-Networkcams haben deren Stream wir auch auf unserer Website anbieten, das habe ich soweit inklusive "Fernsteuerung" der Cam per PTZ Tools mit Hilfe des Axis-Supports bereits hinbekommen. Nun geht es aber darum auch noch die Steuerungsqueue zu implentieren, und da stehe ich vor einem Problem.

Es gibt eine Axis-Seite die die jeweils benötigten Variablen ausgibt, allerdings wenn ich in meinem Frameset (ja, muss leider sein) einen Frame hinzufüge der diese Seite lädt dann kann ich von "meinem" Frame (der AxisPlugin, Steuerung etc. beinhaltet) per JavaScript darauf nicht zugreifen (da das ja domainübergreifend wäre).

Deshalb habe ich mir überlegt in  meinem Frame nicht direkt die "fremde" Seite zu laden sondern diese per PHP auszulesen und den Inhalt in meine Frameseite zu schreiben. Das wäre auch gar nicht viel, die Zeile sieht zB wie folgt aus:

<html><body><a name="1"></a><a name="60"></a><a name="4"></a></body></html>

Ich habe jetzt versucht einfach per fopen auf die Datei zuzugreifen, allerdings kommt dann ein Fehler:

Error:
<title>You must have cookies enabled in your webbrowser.</title>

Daraufhin habe ich mal nachgesehen ob die Seite etwa ein Cookie schreiben möchte, und ja, das macht sie. Allerdings nicht wenn sie per Script aufgerufen wird. Und das Cookie beinhaltet bei jedem Aufruf einen anderen Wert.

Hab mir dann auch noch den Header angeschaut und dabei festgestellt dass die Seite wohl eine Weiterleitung verursacht wenn das mit dem Cookie nicht klappt:

HTTP/1.0 302 Found
Location: /axis-cgi/ptz/cookietest.cgi?cgipathref=ptzqueue

Set-Cookie: ptz_ctl_id=17464; path=/axis-cgi/;expires=Wed, 01-Feb-2006 08:02:19 GMT

Tja, meine Frage nun, wie kann ich das lösen auf die Seite zuzugreifen sodass Sie mir denselben Inhalt ausgibt wie wenn ich per Browser darauf zugreife? Ich könnte zwar wahrscheinlich irgendwie Cookies beim Request mitsenden, allerdings ich weiß ja gar nicht was in dem Moment drinstehen muss, da ja erst die Seite selbst beim Aufruf das Cookie generiert. Oder denk ich jetzt viel zu kompliziert?

Falls es weiterhelft, ursprünglich wollte ich die Seite wie folgt auslesen:

  
//Set values  
$host = "http://85.199.1.130";  
$path = "/axis-cgi/com/ptzqueue.cgi";  
$query = "?control=request";  
$buffer = "";  
  
//Set connection  
$fp = fopen($host.$path.$query, "r");  
  
//If connection could not be established  
if (!$fp) {  
    echo("Ein Fehler ist aufgetreten, Queue derzeit nicht verfügbar");  
}  
//Connection established successfully  
else {  
    while (!feof($fp)) {  
        $buffer = fgets($fp, 4096);  
        echo($buffer);  
    }  
    fclose ($fp);  
}  

Der Axis-Support hilft mir hier leider nicht mehr weiter, außer mit der Aussage dass ich das eben selber coden muss, allerdings nicht "wie". Es gibt wohl nur einen Support für "Häufig gestellte Anfragen" wie mir mitgeteilt wurde ...

Liebe Grüße
sunny

  1. Guten Morgen sunny,

    welche PHP-Version kommt zum Einsatz?
    (Lösungswege gibt es einige, welche genau, hängt von der Version ab ;)

    Gruß aus Berlin!
    eddi

    --
    Wer Rechtschreibfehler findet, darf sie behalten.
    1. Hallo XaraX,

      welche PHP-Version kommt zum Einsatz?
      (Lösungswege gibt es einige, welche genau, hängt von der Version ab ;)

      sorry, das hatte ich vergessen: PHP 4.3.10

      Liebe Grüße
      sunny

      1. Re:

        PHP 4.3.10

        Dann bleiben nur die guten alten Netwerkfunktionen übrig...

        Zur Erläuterung:

        Wenn mittels fopen('http://.....','r'); ein Stream geöffnet wird, schaltet sich intern ein Wrapper für das HTT-Protokoll dazwischen. Der Wrapper kann auch mit Redirekts (Status 30(1|2|3) + Location) umgehen und fordert die Resource von der vom Server benannten Quelle an. Allerdings werden Set-Cookie-Header dabei nicht berücksichtigt. Mit anderen Worten: Der Wrapper arbeitet wie ein Browser mit deaktivierter Cookie-Funktionalität.

          
        //Set values  
        $host = "http://85.199.1.130";  
        $path = "/axis-cgi/com/ptzqueue.cgi";  
        $query = "?control=request";  
        $buffer = "";  
          
        //Set connection  
        $fp = fsockopen($host,80);  
        if(!is_resource($fp)) die('FEHLERMELDUNG: Melde gehorsamst einen Fehler!');  
          
        fwrite($fp,'GET '.$path.$query." HTTP/1.1\r\nHost: ".substr($host,7)."\r\n\r\n");  
          
        $h=explode("\r\n",fread($fp,2048));  
        $c=count($h);  
        for($i=0;$i<$c;$i++){  
           if($h[$i][0]=='') break;  
          
           $h[$i][0]=explode(': ',$h[$i],2);  
           $res[strtolower($h[$i][0])]=$h[$i][1];  
        }  
        if(array_key_exists('location',$res))  
           $new_host=$res['location'];  
        if(array_key_exists('set-cookie',$res))  
           $cookie =trim(substr($res['set-cookie'],0,strpos($res['set-cookie'],';'));  
          
        # bitte selbst debuggen und bei Fragen die RFCs [link:http://www.w3.org/Protocols/rfc2616/rfc2616.html@title=2616] und [link:http://www.ietf.org/rfc/rfc2965.txt@title=2965] aufsuchen  
        
        

        Gruß aus Berlin!
        eddi

        --
        Wer Rechtschreibfehler findet, darf sie behalten.
        1. Vielen Dank!

          Allerdings könntest Du mir bitte kurz erläutern was da gemacht wird? Ab der Schleife versteh ich nicht mehr so ganz genau was getan wird.

          Die beiden Zeilen verursachen bei mir eine "Array to string conversion".

          $h[$i][0]=explode(': ',$h[$i],2);
             $res[strtolower($h[$i][0])]=$h[$i][1];

          Vielleicht kannst Du mir das nochmal näher erläutern damit ich weiß was ich mit Array wirklich machen muss.

          Und noch eine Frage hätte ich: Darf man eigentlich bei fsockopen nie das "http://" mit dazu nehmen? Dann funktioniert bei mir der Zugriff nämlich gar nicht. Erst wenn ich nur die IP verwende (oder natürlich einen ganzen Domainnamen, aber in diesem Fall gibt es ja keinen). Dazu habe ich in der Doku leider nichts gefunden.

          Liebe Grüße
          sunny

          1. Moin!

            Und noch eine Frage hätte ich: Darf man eigentlich bei fsockopen nie das "http://" mit dazu nehmen?

            Nein. fsockopen() öffnet einen Kommunikationskanal auf Basis von TCP - ein Protokoll wie HTTP, FTP oder SMTP ist damit noch nicht verbunden, dass muss man dann selbst realisieren und mit dem Server sprechen.

            - Sven Rautenberg

            --
            My sssignature, my preciousssss!
            1. Hallo,

              Nein. fsockopen() öffnet einen Kommunikationskanal auf Basis von TCP - ein Protokoll wie HTTP, FTP oder SMTP ist damit noch nicht verbunden, dass muss man dann selbst realisieren und mit dem Server sprechen.

              Ah, vielen Dank, das hatte ich in der Doku leider überlesen, obwohls da doch sogar drinsteht - jetzt ist's mir klar!

              Liebe Grüße
              sunny

          2. Re:

            Da waren Fehler drin:

              
            # Spalten in einzele Responseheaderzeilen  
            $h=explode("\r\n",fread($fp,2048));  
            $c=count($h);  
            # durchlaufen der Header ohne Status-Header ($i=1)  
            for($i=1;$i<$c;$i++){  
               # die Zeile <CR><LF> trennt Header von Content  
               # da durch explode("\r\n",fread($fp,2048)); <CR><LF>  
               # entfernt wurde, ist diese spezielle Zeile also leer  
               if($h[$i]=='') break;  
              
               # Trennen nach Header-Token und Header-Content  
               $h[$i]=explode(': ',$h[$i],2);  
               $res[strtolower($h[$i][0])]=$h[$i][1];  
            }  
            # auffinden von Location- und Set-Cookie-Token  
            if(array_key_exists('location',$res))  
               $new_host=$res['location'];  
            if(array_key_exists('set-cookie',$res))  
               $cookie =trim(substr($res['set-cookie'],0,strpos($res['set-cookie'],';'));  
              
            # ACHTUNG: Script geht von einem Cookie aus!  
            
            

            Gruß aus Berlin!
            eddi

            --
            Wer Rechtschreibfehler findet, darf sie behalten.
            1. Sorry, leider muss ich nochmal nachfragen.

              Also dank Deiner Kommentare hab ich zwar, glaube ich, verstanden was das Script macht, habe nun also alle Header-Informationen zusammen, die ich brauche. Aber was ich jetzt trotz allem nicht hinbekomme, ist das Auslesen der Seite selbst, ich sollte ja dazu gleich beim Request auf die Seite diese Header-Informationen wieder mitsenden, oder?
              Allerdings die Weiterleitung ja eigentlich nicht da die Information die ich brauche ja nicht in der Weiterleitung steckt, die soll ja vermieden werden, also irgendwie verhaspel ich mich da gerade immer noch ziemlich ...?

              Kannst Du mir da nochmal weiterhelfen?

              1. Re:

                Also dank Deiner Kommentare hab ich zwar, glaube ich, verstanden was das Script macht, habe nun also alle Header-Informationen zusammen, die ich brauche. Aber was ich jetzt trotz allem nicht hinbekomme, ist das Auslesen der Seite selbst, ich sollte ja dazu gleich beim Request auf die Seite diese Header-Informationen wieder mitsenden, oder?

                Richtig.

                Allerdings die Weiterleitung ja eigentlich nicht da die Information die ich brauche ja nicht in der Weiterleitung steckt, die soll ja vermieden werden, also irgendwie verhaspel ich mich da gerade immer noch ziemlich ...?

                Richtig.

                ----------                           ----------
                 | CLIENT | -------- REQUEST -------> | SERVER |
                 ----------                           ----------
                                                           |
                 ----------       (status 302)             |
                 | CLIENT | <------- RESPOSE --------------/
                 ----------
                     |         (mit Cookie an
                     |            URI von Location)   ----------
                     -------------- REQUEST -------> | SERVER |
                                                      ----------
                                                           |
                 ----------       (status 200)             |
                 | CLIENT | <------- RESPOSE --------------/
                 ----------

                Bitte post Dein jetziges Script, oder wenn möglich, gibt die URI des der entsprechenden Resource bekann, damit ich mir die Header auslesen kann.

                Gruß aus Berlin!
                eddi

                --
                Wer Rechtschreibfehler findet, darf sie behalten.
                1. Allerdings die Weiterleitung ja eigentlich nicht da die Information die ich brauche ja nicht in der Weiterleitung steckt, die soll ja vermieden werden, also irgendwie verhaspel ich mich da gerade immer noch ziemlich ...?

                  Richtig.

                  ----------                           ----------
                  | CLIENT | -------- REQUEST -------> | SERVER |
                  ----------                           ----------
                                                             |
                  ----------       (status 302)             |
                  | CLIENT | <------- RESPOSE --------------/

                  |         (mit Cookie an
                       |            URI von Location)   ----------
                       -------------- REQUEST -------> | SERVER |
                                                        ----------
                                                             |
                  ----------       (status 200)             |
                  | CLIENT | <------- RESPOSE --------------/

                  Bitte post Dein jetziges Script, oder wenn möglich, gibt die URI des der entsprechenden Resource bekann, damit ich mir die Header auslesen kann.

                  Oh, ja. Da hab ich tatsächlich zu wenig bedacht. Ich wollte den Header einfach nur gleich mal an die Seite mitsenden und dann per fgets auslesen ... so geht das natürlich nicht.

                  Also die gesamte URI lautet zusammengesetzt: http://85.199.1.130//axis-cgi/com/ptzqueue.cgi?control=request

                  Liebe Grüße
                  sunny

                  1. Sorry, da war ein Slash zu viel enthalten ...

                    Also die gesamte URI lautet zusammengesetzt: http://85.199.1.130/axis-cgi/com/ptzqueue.cgi?control=request

                    Liebe Grüße
                    sunny

                    1. Re:

                      Also die gesamte URI lautet zusammengesetzt: http://85.199.1.130/axis-cgi/com/ptzqueue.cgi?control=request

                      was ist das denn wieder für eine Frikelsoftware?!? /axis-cgi/com/ptzqueue.cgi senden keinen HTTP-gerechten Location-Header...

                        
                      $url="http://85.199.1.130/axis-cgi/com/ptzqueue.cgi?control=request";  
                        
                      function cookie_trans($url,$redi=5,$cookie=''){  
                       $url =(substr(strtolower($url),0,7)=='http://') ? substr($url,7) : $url;  
                       $t   =explode('/',$url,2);  
                       $host=$t[0];  
                       $pfad='/'.(array_key_exists(1,$t) ? $t[1] : '');  
                        
                       if(!is_resource($s=fsockopen($host,80)))  
                        die('Server nicht erreichbar');  
                        
                       fwrite($s,'GET '.$pfad." HTTP/1.1\r\nHost: ".$host."\r\n".$cookie."\r\n");  
                       if(substr(fgets($s),9,2)=='30'){  
                        if($redi==0)  
                         return(false);  
                        
                        for($i=0;$i<20;$i++){  
                         $t=explode(': ',fgets($s,2200),2);  
                        
                         if(strtolower($t[0])=='location')  
                          $url=$t[1];  
                         elseif(strtolower($t[0])=='set-cookie')  
                          # hier müsste noch eine ordentlich  
                          # Cookie-Behandlung hinein  
                          # sollte aber für deine Zwecke ausreichen  
                          $cookie.=trim(substr($t[1],0,strpos($t[1],';')))."\r\n";  
                         elseif($t[0]=='')  
                          break;  
                        }  
                        if($url{0}=='/')  
                         $url=$host.$url;  
                        
                        return(cookie_trans($url,--$redi,$cookie));  
                       }  
                       else{  
                        for($i=0;$i<20;$i++){  
                         $t=fgets($s,2200);  
                         if($t[0]=="\r\n")  
                          break;  
                        }  
                        return(fread($s,300000));  
                       }  
                      }  
                      $content=cookie_trans($url);  
                      
                      

                      Das Script liefert nichts zurück, weil dort nichts zu sehen ist.

                      Gruß aus Berlin!
                      eddi

                      --
                      Wer Rechtschreibfehler findet, darf sie behalten.
                      1. Das Script liefert nichts zurück, weil dort nichts zu sehen ist.

                        Ohne es (das Script) mir jetzt genauer angesehen zu haben (was ich gleich machen werde), die Seite liefert aber schon was zurück wenn man sie selbst über den Browser aufruft, nämlich den folgenden HTML-Quelltext (die Namen sind jeweils unterschiedlich je nach Status und genau das was ich später auslesen müsste - dafür hat sich auch einmal irgendein Kerl diese Seite überhaupt ausgedacht, damit man den Status irgendwie abfragen kann):

                        <html><body><a name="1"></a><a name="60"></a><a name="4"></a></body></html>

                        Und genau den Quelltext müsste ich irgendwie in mein Frameset bekommen ... Ist das nun gar nicht möglich? Meine Verwirrung lässt leider nicht nach im Moment ...

                        Also auf jeden Fall aber mal vielen Dank für Deine Mühe trotz meiner "Verwirrungszustände", ich werde jetzt erst einmal Dein Script durcharbeiten, vielleicht sehe ich danach wieder irgendetwas klarer wie das jetzt zu bewerkstelligen wäre.

                        Liebe Grüße aus Salzburg
                        sunny

                        1. Guten Morgen!

                          Das Script liefert nichts zurück, weil dort nichts zu sehen ist.

                          Ohne es (das Script) mir jetzt genauer angesehen zu haben (was ich gleich machen werde), die Seite liefert aber schon was zurück wenn man sie selbst über den Browser aufruft, nämlich den folgenden HTML-Quelltext (die Namen sind jeweils unterschiedlich je nach Status und genau das was ich später auslesen müsste - dafür hat sich auch einmal irgendein Kerl diese Seite überhaupt ausgedacht, damit man den Status irgendwie abfragen kann):

                          <html><body><a name="1"></a><a name="60"></a><a name="4"></a></body></html>

                          Und genau den Quelltext müsste ich irgendwie in mein Frameset bekommen ... Ist das nun gar nicht möglich? Meine Verwirrung lässt leider nicht nach im Moment ...

                          So, also das Script habe ich jetzt durchgearbeitet und mir auch genau angesehen was wo passiert.

                          Und, wenn man sich beim Versuch des Auslesens der Seite in der for-Schleife gleich mal $t ausgeben lässt so kommt wieder das alte Problem zu Tage. Nämlich dass die Seite nur Folgendes zurückgibt:

                          Error:
                          <title>You must have cookies enabled in your webbrowser.</title>

                          Genau so, wie wenn man die Seite eben gleich direkt aufruft und den Content per Script auslesen möchte.

                          Liebe Grüße
                          sunny

                          1. Guten Morgen!

                            Und, wenn man sich beim Versuch des Auslesens der Seite in der for-Schleife gleich mal $t ausgeben lässt so kommt wieder das alte Problem zu Tage. Nämlich dass die Seite nur Folgendes zurückgibt:

                            Error:
                            <title>You must have cookies enabled in your webbrowser.</title>

                            Genau so, wie wenn man die Seite eben gleich direkt aufruft und den Content per Script auslesen möchte.

                            Vorsicht: Das habe ich alles nur schnell aus der Hüfte zusammengenagelt; und das beim ersten Aufruf der Seite diese Meldung kommt, sollte klar sein. Es ist viel wichtiger für Dich zu verstehen, wie HTTP und das Setzen von Cookies funktioniert. Mehr soll auch gar nicht rüberkommen. Der Rest, tut mir leid, ist Deine Arbeit!

                            Im Übrigen hatte ich vergessen den ResourcenHandler zu schließen - das solltest Du als erstes überarbeiten.

                            Gruß aus Berlin!
                            eddi

                            --
                            Wer Rechtschreibfehler findet, darf sie behalten.