Gelöst: Exchange EWS und PHP SOAP

Hallo,


UPDATE 2010-01-10:
mit Version 2.2 funktioniert es, da hier PHP 5.3.1 an Board ist.


habe zuhause Exchange 2007 und würde gerne meine Termine und Mails über PHP und IPS anschauen. Nach einigem googlen habe ich dann die folgende Seite gefunden: Talking-SOAP-with-Exchange und war dann zum Teil erfolgreich

Kurze Erklärung:
Man braucht natürlich php_soap.dll und php_curl.dll und noch die ssleay32.dll Hier runterzuladen

Im Verzeichnis „scripts“ fehlen jetzt noch drei Dateien.
Services.wsdl, types.xsd und messages.xsd
Alle drei runter zu laden vom Exchange Server:
https://exchange.example.com/EWS/types.xsd
https://exchange.example.com/EWS/messages.xsd
https://exchange.example.com/EWS/Services.wsdl

Bei Services.wsdl noch das nächste Textblock VOR der letzten Zeile hinzufügen:

        <wsdl:service name="ExchangeServices">
            <wsdl:port name="ExchangeServicePort" binding="tns:ExchangeServiceBinding">
                <soap:address location="https://exchange.example.com/EWS/Exchange.asmx"/>
            </wsdl:port>
        </wsdl:service>

Der PHP Quellcode ist folgender: (Achtung:2x Mailadresse ändern)

<?
/*
*******************************
 IP-SYMCON Event Scripting
*******************************
File     : calendar_pb.ips.php
Trigger  : 
Interval : 
*/

class NTLMSoapClient extends SoapClient {
    function __doRequest($request, $location, $action, $version) {
        $headers = array(
            'Method: POST',
            'Connection: Keep-Alive',
            'User-Agent: PHP-SOAP-CURL',
            'Content-Type: text/xml; charset=utf-8',
            'SOAPAction: "'.$action.'"',
        );
        $this->__last_request_headers = $headers;
        $ch = curl_init($location);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, true );
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
        curl_setopt($ch, CURLOPT_USERPWD, $this->user.':'.$this->password);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        $response = curl_exec($ch);
        return $response;
    }
    function __getLastRequestHeaders() {
        return implode("n", $this->__last_request_headers)."n";
    }
}



class ExchangeNTLMSoapClient extends NTLMSoapClient {
    protected $user = 'deine@mail.adresse';    // evtl. 'Domäne\\User' 
    protected $password = 'kennwort';
}


class NTLMStream {
    private $path;
    private $mode;
    private $options;
    private $opened_path;
    private $buffer;
    private $pos;

    public function stream_open($path, $mode, $options, $opened_path) {
        echo "[NTLMStream::stream_open] $path , mode=$mode n";
        $this->path = $path;
        $this->mode = $mode;
        $this->options = $options;
        $this->opened_path = $opened_path;
        $this->createBuffer($path);
        return true;
    }

    public function stream_close() {
        echo "[NTLMStream::stream_close] n";
        curl_close($this->ch);
    }

    public function stream_read($count) {
        echo "[NTLMStream::stream_read] $count n";
        if(strlen($this->buffer) == 0) {
            return false;
        }
        $read = substr($this->buffer,$this->pos, $count);
        $this->pos += $count;
        return $read;
    }

    public function stream_write($data) {
        echo "[NTLMStream::stream_write] n";
        if(strlen($this->buffer) == 0) {
            return false;
        }
        return true;
    }

    public function stream_eof() {
        echo "[NTLMStream::stream_eof] ";
        if($this->pos > strlen($this->buffer)) {
            echo "true n";
            return true;
        }
        echo "false n";
        return false;
    }

    /* return the position of the current read pointer */
    public function stream_tell() {
        echo "[NTLMStream::stream_tell] n";
        return $this->pos;
    }

    public function stream_flush() {
        echo "[NTLMStream::stream_flush] n";
        $this->buffer = null;
        $this->pos = null;
    }

    public function stream_stat() {
        echo "[NTLMStream::stream_stat] n";
        $this->createBuffer($this->path);
        $stat = array(
            'size' => strlen($this->buffer),
        );
        return $stat;
    }

    public function url_stat($path, $flags) {
        echo "[NTLMStream::url_stat] n";
        $this->createBuffer($path);
        $stat = array(
            'size' => strlen($this->buffer),
        );
        return $stat;
    }

    /* Create the buffer by requesting the url through cURL */
    private function createBuffer($path) {
        if($this->buffer) {
            return;
        }
        echo "[NTLMStream::createBuffer] create buffer from : $pathn";
        $this->ch = curl_init($path);
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($this->ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
        curl_setopt($this->ch, CURLOPT_USERPWD, $this->user.':'.$this->password);
        echo $this->buffer = curl_exec($this->ch);
        echo "[NTLMStream::createBuffer] buffer size : ".strlen($this->buffer)."bytesn";
        $this->pos = 0;
    }
}


class ExchangeNTLMStream extends NTLMStream {
    protected $user = 'deine@mail.adresse';    // evtl. 'Domäne\\User' 
    protected $password = 'kennwort';
}


//verändert: erst wenn https registriert ist, unregistrieren
$existed = in_array("https", stream_get_wrappers());
if ($existed) {
    stream_wrapper_unregister("https");

    stream_wrapper_register('https', 'ExchangeNTLMStream') or die("Failed to register protocol");
    $wsdl = "services.wsdl";
    $client = new ExchangeNTLMSoapClient($wsdl);

    /* Do something with the web service connection */
    stream_wrapper_restore('https');
    }
    else {
        stream_wrapper_register('https', 'ExchangeNTLMStream') or die("Failed to register protocol");
        $wsdl = "services.wsdl";
        $client = new ExchangeNTLMSoapClient($wsdl);
}



print_r($client->__getFunctions());

?>

Es ist mir schon gelungen einen Termineintrag zu erstellen.

$CreateItem->SendMeetingInvitations = "SendToNone";
$CreateItem->SavedItemFolderId->DistinguishedFolderId->Id = "calendar";
$CreateItem->Items->CalendarItem = array();
for($i = 0; $i < 1; $i++) {
    $CreateItem->Items->CalendarItem[$i]->Subject = "Hello from PHP";
    $CreateItem->Items->CalendarItem[$i]->Start = "2010-01-01T16:00:00Z"; # ISO date format. Z denotes UTC time
    $CreateItem->Items->CalendarItem[$i]->End = "2010-01-01T17:00:00Z";
    $CreateItem->Items->CalendarItem[$i]->IsAllDayEvent = false;
    $CreateItem->Items->CalendarItem[$i]->LegacyFreeBusyStatus = "Busy";
    $CreateItem->Items->CalendarItem[$i]->Location = "Bahamas";
    $CreateItem->Items->CalendarItem[$i]->Categories->String = "MyCategory";
}
$result = $client->CreateItem($CreateItem);
print_r($result);

Leider klappt es nicht eine Suche zu starten… (Quellcode: )

    $FindItem->Traversal = "Shallow";
    $FindItem->ItemShape->BaseShape = "AllProperties";
    $FindItem->ParentFolderIds->DistinguishedFolderId->Id = "calendar";
    $FindItem->CalendarView->StartDate = "2008-12-01T00:00:00Z";
    $FindItem->CalendarView->EndDate = "2008-12-31T00:00:00Z";
    $result = $client->FindItem($FindItem);
    $calendaritems = $result->ResponseMessages->FindItemResponseMessage->RootFolder->Items->CalendarItem;
    foreach($calendaritems as $item) {
        echo $item->Subject."n";
    }

Output:

<br />
<b>Fatal error</b>:  Uncaught SoapFault exception: [soap11:Client] The request failed schema validation:
The element 'FindItem' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages' has
incomplete content. List of possible elements expected: 'GroupBy, DistinguishedGroupBy, Restriction, SortOrder,
ParentFolderIds' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages'. in 
C:\Program Files\IP-SYMCON\scripts\.currentscript:192
Stack trace:
#0 [internal function]: SoapClient->__call('FindItem', Array)
#1 C:\Program Files\IP-SYMCON\scripts\.currentscript(192): ExchangeNTLMSoapClient->FindItem(Object(stdClass))
#2 {main}
  thrown in <b>C:\Program Files\IP-SYMCON\scripts\.currentscript</b> on line <b>192</b><br />

oder

    $FindFolder->Traversal = "Shallow";
    $FindFolder->FolderShape->BaseShape = "Default";
    $FindFolder->ParentFolderIds->DistinguishedFolderId->Id = "root";
    $result = $client->FindFolder($FindFolder);
    $folders = $result->ResponseMessages->FindFolderResponseMessage->RootFolder->Folders->Folder;
    foreach($folders as $folder) {
        echo $folder->DisplayName."n";
    }

Output:

<br />
<b>Fatal error</b>:  Uncaught SoapFault exception: [soap11:Client] The request failed schema validation:
The element 'FindFolder' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages'
has incomplete content. List of possible elements expected: 'IndexedPageFolderView, FractionalPageFolderView,
Restriction, ParentFolderIds' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages'.
in C:\Program Files\IP-SYMCON\scripts\.currentscript:179
Stack trace:
#0 [internal function]: SoapClient->__call('FindFolder', Array)
#1 C:\Program Files\IP-SYMCON\scripts\.currentscript(179): ExchangeNTLMSoapClient->FindFolder(Object(stdClass))
#2 {main}
  thrown in <b>C:\Program Files\IP-SYMCON\scripts\.currentscript</b> on line <b>179</b><br />

Wer von euch kann mir helfen dieses Problem zu lösen?

danke
oortmanp

weiß denn kein Web/SOAP Designer wie man dies lösen kann?

Ich bezweifle, dass dir jemand bei dem Problem helfen kann.

Es gibt hier kaum Exchange Nutzer, und noch weniger die SOAP können und noch weniger die beides im Zusammenhang nutzen, um dir bei bei deinem sehr speziellen Problem helfen zu können.

Ich würde lieber in einem Exchange Forum fragen - Dein PHP Skript geht ja auch unter dem normalen Apache und ist nicht an IPS gebunden.

paresy

so aus dem Bauch raus würde ich sagen, die Schemabeschreibung passt nicht zu dem, was der Server wirklich anbietet. Kann es sein, das das Beispiel für eine ältere Version von Exchange gemacht wurde?

The request failed schema validation:
The element 'FindFolder' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages'
has incomplete content. List of possible elements expected: 'IndexedPageFolderView, FractionalPageFolderView,
Restriction, ParentFolderIds' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages'.

Du solltest diesem Fehler mal nachgehen.

Tommi

EWS gibt es erst seit der Version 2007. Vielleicht liegt es ja an der php_soap.dll Version. Hier wurde schon einiges drüber berichtet in dem Forum wo ich den Beitrag her habe. Werde mich da mal schlau machen und evt (separat) ne neue PHP Version installieren.

Falls diese theoretische Lösung evt. was bringen würde, wäre das Problem meines Erachtens für IPS ja (noch) nicht gelöst. Oder könnte man auch die PHP Version in IPS updaten?

gruss
oortmanp

Du kannst das PHP nicht austauschen, aber Du könntest versuchen, eine neuere SOAP-Extension gegen die php 5.1.6 zu linken.
Ansonsten bleibt nur der Weg über einen externen Server/ externes Programm oder die wacklige PHP COM-Bridge, mit der man externe Komponenten ansprechen kann.

Tommi

Die Möglichkeiten werde ich dann mal (die Reihe nach) versuchen.

Habe nämlich soeben sowohl die version 5.2.10 und die 5.1.6 für windows runtergeladen und beide mal mit dem EWS script ausprobiert.
Ergebnis:
5.2.10 alles ok
5.1.6 die gepostete SoapFault exeption

werde dann berichten wie de Ergebnisse sind

gruß
oortmanp

Hallo oortmanp,

als erstes Danke für deine Anleitung.

Mit Freude kann ich dir mitteilen das der Zugriff mit deiner Anleitung bei mir funktoniert, muß aber auch sagen das ich die 2.2ß nutze und dort PHP 5.3.1 an Board ist.

Nun muss ich das Ganze mal ausbauen um die zurückgeliefert Werte in IPS auswerten zu können.

Hi wgreipl

das sind gute Nachrichten! Ich bin selber noch nicht weiter gekommen mit ne PHP-bridge oder es ueber den IIS server laufen zu lassen. Aber die Version 2.2 ist dann vielversprechend!

Danke fuer die Info

Gruss
oortmanp

Hallo,

kann auch bestätigen, dass es mit Exchange 2010 läuft.

Gruss
Michael

Hallo Michael,

danke für den Hinweis, dann kann ich mir sicher sein das die Klasse auch in kommenden Versionen von Exchange fuktioniert. Gibt ein wenig Planungssicherheit.

Hallo Exchange-Interessierte,

hier nun mein komplettes Skript zur Anzeige in Webfront inkl. Auswahl wieviele Tage im voraus Termine angezeigt werden.

Um das Skript lauffähig zu bekommen bedarf es nur zwei zusätzlicher Variablen.

[ul]
[li]Stringvariable mit Profil ~Textbox zur eigentlichen Anzeige der Termine[/li][li]Integervariable für die Anzahl der Tage wie weit die Termine angezeigt werden.[/li][/ul]
Habe das Skript eigentlich sauber kommentiert aber keine Funktionen zum automatischen Anlegen der Variablen bzw. des nötigen Timers eingebaut. Mit diesen Features spiele ich mich zu einem späteren Zeitpunkt.

Hier nun das Skript:

<?
// Debug-Modus ein/aus
$debug = false;
 
// Pfad für Sprach- bzw. Erinnerungston
$path = IPS_GetKernelDir().'media/';
 
// Vorlauf der Kalenderansicht (heute plus x-Tage)
// Hilfs-Integervariable mit Profil anlegen - Assoziation 2, 7, 14 und 31 Tage
if($IPS_SENDER == "WebFront")
{
   SetValue($IPS_VARIABLE, $IPS_VALUE);
 $vorlauf = $IPS_VALUE;
}
if(isset($IPS_VALUE)) {
 // NIX
} else {
 $vorlauf = 2;
 SetValue(42559 /*[Terminverwaltung\Vorlauf]*/, $vorlauf);
}
 
// Datum zusammensetzen der Startzeit für Abfrage Exchange
// alle Termine ab heute/jetzt
$s_jahr = date('Y');
$s_monat = date('m');
$s_tag   = date('d');
$s_start = $s_jahr."-".$s_monat."-".$s_tag."T00:00:01Z";
if($debug) { echo $s_start."
"; }
 
// Datum zusammensetzen der Endzeit für Abfrage Exchange
$s_EndDatum = time()+(60*60*24*$vorlauf);
$s_EndTag = date('j', $s_EndDatum);
$s_EndMonat = date('m', $s_EndDatum);
$s_EndJahr = date('Y', $s_EndDatum);
$s_ende = $s_EndJahr."-".$s_EndMonat."-".$s_EndTag."T23:59:59Z";
if($debug) { echo $s_ende."
"; }
// Klasse für den entsprechenden Benutzer laden
include "class_ex_werner.ips.php";
 
//SOAP-Anfrage an Exchange starten
$FindItem->Traversal = "Shallow";
$FindItem->ItemShape->BaseShape = "AllProperties";
$FindItem->ParentFolderIds->DistinguishedFolderId->Id = "calendar";
$FindItem->CalendarView->StartDate  = $s_start;
$FindItem->CalendarView->EndDate  = $s_ende;
$result = $client->FindItem($FindItem);
$calendaritems = $result->ResponseMessages->FindItemResponseMessage->RootFolder->Items->CalendarItem;
if($debug) { print_r($calendaritems); }
 
$x = 0;
foreach($calendaritems as $item) {
 // Startzeit des Termines aus Exchange zerlegen für Anzeige in Datumsform (Unix-Timestamp)
 $stunde  = substr ( $item->Start, 11, 2 );
 $minute  = substr ( $item->Start, 14, 2 );
 $sekunde = substr ( $item->Start, 17, 2 );
 $tag     = substr ( $item->Start, 8, 2 );
 $monat   = substr ( $item->Start, 5, 2 );
 $jahr    = substr ( $item->Start, 0, 4 );
 
 // String für Anzeigedatum und Uhrzeit generieren und Zeitzone hinzufügen
 $unix = mktime ( $stunde+date('I')+1, $minute, $sekunde, $monat, $tag, $jahr );
 if(date('d.m.Y, H:i', $unix-(($item->ReminderMinutesBeforeStart)*60)) == date('d.m.Y, H:i', time())) {
  WFC_SendNotification(43269 /*[WebFront Configurator]*/, "Terminwarnung", utf8_decode($item->Subject), "Glocke", 0);
      WAC_PlayFile(30880 /*[Erdgeschoß\Küche / Esszimmer\Terminwarnung\Sprachausgabe Küche]*/, $path."bell.wav");
      // In der kommenden Version wird der Termin vorgelesen
 }
 
 if($debug) { echo date ( 'd.m.Y, H:i', $unix) . ", " . utf8_decode($item->Subject)."<br>"; }
 if($debug) { echo $unix . "-". utf8_decode($item->Location) . "<br><br>"; }
 
 // Auswertung des Feldes ORT zur Steuerung von verschiedenen Aufgaben, z.B. FHT_Bad
 /*if (utf8_decode($item->Location) == "FHT_Bad") {
    echo "Heizung Bad";
 }*/
 
 // Array für Anzeige in Stringvariable in Webfront erzeugen
 $ausgabe[$x] = date ( 'd.m.Y, H:i', $unix) . " Uhr - " . utf8_decode($item->Subject);
 $x++;
}
if($debug) { print_r($ausgabe); }
 
// Array für Webfront aufbereiten und in String-Variable schreiben
// die im Webfront angezeigt wird. Profil ~Textbox
$ausgabe_wf = implode("
", $ausgabe);
SetValueString(30216 /*[Terminverwaltung\Termine]*/, $ausgabe_wf);
?>

Da das Skript in Webfront auch mit Hilfe von „WFC_SendNotification“ (nur V2.2) auf Termine hinweist muss im untenstehenden Teil die ID des Webfront-Konfigurators und einer evtl. Mediaplayerinstanz geändert werden. Wird dies nicht benötigt einfach den kompletten Part auskommentieren. Die Erinnerung erfolgt zum Zeitpunkt wie in Outlook unter Erinnerung (Reminder) eingetragen, also wenn Termin um 07:00h unter Erinnerung auf 15 Minuten dann weißt das Skript um 06:45 auf den Termin hin. Ist die Erinnerung ausgeschaltet weißt das Skript auch nicht auf den Termin hin sondern zeigt diesen nur in der Textbox an.

// String für Anzeigedatum und Uhrzeit generieren und Zeitzone hinzufügen
if(date('d.m.Y, H:i', $unix-(($item->ReminderMinutesBeforeStart)*60)) == date('d.m.Y, H:i', time())) {
      WFC_SendNotification(43269 /*[WebFront Configurator]*/, "Terminwarnung", utf8_decode($item->Subject), "Glocke", 0);
      WAC_PlayFile(30880 /*[Erdgeschoß\Küche / Esszimmer\Terminwarnung\Sprachausgabe Küche]*/, $path."bell.wav");
}

Ein Skript zur Eingabe von Terminen ist derzeit eigentlich nicht vorgesehen da dies ja in Outlook, OWA und iPhone geschieht und die komplette Familie mit einem dieser Clients ausgestattet ist, aber wer weiß schon was die Zukunft mit sich bringt.

Da die Termine in einer Stringvariable vorliegen sollte das Skript auch im Dashboard lauffähig sein. :smiley:

Für alle die es brauchen können, viel Spaß damit.

Hallo Werner,

scheine mich etwas ungeschickt anzustellen.
Bei mir klappt es leider nicht.

Was ich getan habe:
Datei vom Exchange-Server runtergeladen, service angepasst natürlich auch die Server-Adresse die PHP-Ext. habe ich mir passend zu der Beta 2.2 besorgt.

Wenn ich jetzt dein letzte Skript ausführe, natürlich mit den Anpassungen der Mail-Adresse und PW, dann versteht er folgendes nicht:

include „class_ex_werner.ips.php“;

Ist ja klar, die habe ich ja auch nicht, also kann ich sie auch nicht einbinden :slight_smile:

Was muss ich hier noch anlegen? Bzw. Was soll da eingebunden werden?

Zudem müsste doch irgendwo mein Benutzername eingegeben werden oder?
Die Dateien vom Exchange-Server, bekomme ich auch nicht mit Mail-Adresse und PW sonder nur mit Benutzername z. B. „e1111111“ und PW.

Mein Exchange-Server liegt bei 1und1, gibt das vielleicht Probleme?

Könnte die Funktion gut gebrauchen, würde gerne meine nächsten X Termin im Dashboard anzeigen lassen…

Für Hilfe bin ich sehr dankbar!

Viele Grüße

ASICS

Hallo,

die fehlende include

include "class_ex_werner.ips.php";

ist die aus dem ersten Thread. Hier nochmal der Quelltext.

<?
/*
*******************************
 IP-SYMCON Event Scripting
*******************************
File     : class_ex_?????.ips.php
Trigger  : 
Interval : 
*/
 
class NTLMSoapClient extends SoapClient {
    function __doRequest($request, $location, $action, $version) {
        $headers = array(
            'Method: POST',
            'Connection: Keep-Alive',
            'User-Agent: PHP-SOAP-CURL',
            'Content-Type: text/xml; charset=utf-8',
            'SOAPAction: "'.$action.'"',
        );
        $this->__last_request_headers = $headers;
        $ch = curl_init($location);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, true );
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
        curl_setopt($ch, CURLOPT_USERPWD, $this->user.':'.$this->password);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
 
        $response = curl_exec($ch);
        return $response;
    }
    function __getLastRequestHeaders() {
        return implode("n", $this->__last_request_headers)."n";
    }
}
 
 
 
class ExchangeNTLMSoapClient extends NTLMSoapClient {
    protected $user = 'deine@mail.adresse';
    protected $password = 'kennwort';
}
 
 
class NTLMStream {
    private $path;
    private $mode;
    private $options;
    private $opened_path;
    private $buffer;
    private $pos;
 
    public function stream_open($path, $mode, $options, $opened_path) {
        echo "[NTLMStream::stream_open] $path , mode=$mode n";
        $this->path = $path;
        $this->mode = $mode;
        $this->options = $options;
        $this->opened_path = $opened_path;
        $this->createBuffer($path);
        return true;
    }
 
    public function stream_close() {
        echo "[NTLMStream::stream_close] n";
        curl_close($this->ch);
    }
 
    public function stream_read($count) {
        echo "[NTLMStream::stream_read] $count n";
        if(strlen($this->buffer) == 0) {
            return false;
        }
        $read = substr($this->buffer,$this->pos, $count);
        $this->pos += $count;
        return $read;
    }
 
    public function stream_write($data) {
        echo "[NTLMStream::stream_write] n";
        if(strlen($this->buffer) == 0) {
            return false;
        }
        return true;
    }
 
    public function stream_eof() {
        echo "[NTLMStream::stream_eof] ";
        if($this->pos > strlen($this->buffer)) {
            echo "true n";
            return true;
        }
        echo "false n";
        return false;
    }
 
    /* return the position of the current read pointer */
    public function stream_tell() {
        echo "[NTLMStream::stream_tell] n";
        return $this->pos;
    }
 
    public function stream_flush() {
        echo "[NTLMStream::stream_flush] n";
        $this->buffer = null;
        $this->pos = null;
    }
 
    public function stream_stat() {
        echo "[NTLMStream::stream_stat] n";
        $this->createBuffer($this->path);
        $stat = array(
            'size' => strlen($this->buffer),
        );
        return $stat;
    }
 
    public function url_stat($path, $flags) {
        echo "[NTLMStream::url_stat] n";
        $this->createBuffer($path);
        $stat = array(
            'size' => strlen($this->buffer),
        );
        return $stat;
    }
 
    /* Create the buffer by requesting the url through cURL */
    private function createBuffer($path) {
        if($this->buffer) {
            return;
        }
        echo "[NTLMStream::createBuffer] create buffer from : $pathn";
        $this->ch = curl_init($path);
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($this->ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
        curl_setopt($this->ch, CURLOPT_USERPWD, $this->user.':'.$this->password);
        echo $this->buffer = curl_exec($this->ch);
        echo "[NTLMStream::createBuffer] buffer size : ".strlen($this->buffer)."bytesn";
        $this->pos = 0;
    }
}
 
 
class ExchangeNTLMStream extends NTLMStream {
    protected $user = 'deine@mail.adresse';
    protected $password = 'kennwort';
}
 
 
//verändert: erst wenn https registriert ist, unregistrieren
$existed = in_array("https", stream_get_wrappers());
if ($existed) {
    stream_wrapper_unregister("https");
 
    stream_wrapper_register('https', 'ExchangeNTLMStream') or die("Failed to register protocol");
    $wsdl = "services.wsdl";
    $client = new ExchangeNTLMSoapClient($wsdl);
 
    /* Do something with the web service connection */
    stream_wrapper_restore('https');
    }
    else {
        stream_wrapper_register('https', 'ExchangeNTLMStream') or die("Failed to register protocol");
        $wsdl = "services.wsdl";
        $client = new ExchangeNTLMSoapClient($wsdl);
}
 
 
 
print_r($client->__getFunctions());
 
?> 

Habe den Dateinamen nur mit meinem Vorname versehen da ich mehrere Postfächer im Webfront anzeigen lasse, je Postfach eine eigene include da darin die Zugangsdaten für den Exchange sind.

Update: Sollte sich der Exchangeserver mit dem Active Directory synchronisieren entsprechen Anmeldedaten dem SamAccountName + Passwort.

Ich habe irgendwie probleme kalenderItems zu bekommen. Scheint so als würde $calendaritems = $result->ResponseMessages->FindItemResponseMessage->RootFolder->Items->CalendarItem; nicht existieren.

Einer schon mal Erfahrungen mit gemacht?

Hallo,

ein paar Fragen diesbezüglich

[ol]
[li]Welche Version des Exchange nutzt Du?[/li][li]Hast Du in der Class deine Accountdaten 2x eingetragen.[/li][/ol]Könntest Du mir vielleicht deinen Aufruf aus IPS zeigen, also das Skript das Du benutzen möchtest.

$FindItem->Traversal = "Shallow";
$FindItem->ItemShape->BaseShape = "AllProperties";
$FindItem->ParentFolderIds->DistinguishedFolderId->Id = "calendar";
$FindItem->CalendarView->StartDate = "2010-06-01T00:00:00Z";
$FindItem->CalendarView->EndDate = "2010-06-30T00:00:00Z";
$result = $client->FindItem($FindItem);
$calendaritems = $result->ResponseMessages->FindItemResponseMessage->RootFolder->Items->CalendarItems;
foreach ($calendaritems as $item)
{
    echo $item->Subject . "n";
}

das ist mein Aufruf. Die Exchangeversion weiß ich leider nicht und habe im Moment auch keine Möglichkeit nach zu sehen, da aber alle anderen Aufrufe (Ordnerstruktur, Kalendereintrag anlegen) funktioniert denke ich daran wird es nicht liegen.

Ja meine Accountdaten sind 2x eingetragen, wobei ich da gerade dran bin und es variable mache.

Update:

Hier zwei Funktionen die die Anmeldedaten aus einem Cookie holen (für diejenigen die noch nicht viel mit PHP gearbeitet haben und natürlich auch alle anderen):

class ExchangeNTLMStream extends NTLMStream
{
    protected $user = null;
    protected $password = null;

    function __construct()
    {
        if(isset($_COOKIE['CookieName']))
        {
            $Cookie = $_COOKIE['CookieName'];
            $this->user = $Cookie[0];
            $this->password = $Cookie[1];
        }
    }
}
class ExchangeNTLMSoapClient extends NTLMSoapClient
{
    protected $user = null;
    protected $password = null;

    function __construct($wsdl)
    {
         if(isset($_COOKIE['CookieName']))
        {
            $Cookie = $_COOKIE['CookieName'];
            $this->user = $Cookie[0];
            $this->password = $Cookie[1];
        }
        parent::__construct($wsdl);
    }
}

Problem 1 Post weiter oben besteht leider immer noch :frowning:

Langsam sehe ich zwar das das mit IPS nichts zu tun hat :smiley: aber egal.

Der Aufruf sieht ja OK aus, aber vielleicht hast Du ja das gleiche Problem wie ich, und zwar wenn im ausgewählten Zeitraum nur 1 Termin vorhanden ist bricht mir die Routine mit einem Fehler ab, habe diesen aber auch noch nicht festmachen können.

Problem behoben.

Es heisst CalendarItem nicht CalendarItems.

Typendeklaration von MS: hier
Weitere Informationen: hier