%PDF- %PDF-
| Direktori : /www/varak.net/mail2.varak.net_old/libraries/afterlogic/common/dav/ |
| Current File : /www/varak.net/mail2.varak.net_old/libraries/afterlogic/common/dav/client.php |
<?php
/*
* Copyright 2004-2014, AfterLogic Corp.
* Licensed under AGPLv3 license or AfterLogic license
* if commercial version of the product was purchased.
* See the LICENSE file for a full license statement.
*/
if(!defined('DAV_ROOT')) define('DAV_ROOT', 'dav/server.php/');
if(!defined('DAV_EMAIL_DEV')) define('DAV_EMAIL_DEV', '@');
class CDAVClient
{
const PROP_RESOURCETYPE = '{DAV:}resourcetype';
const PROP_DISPLAYNAME = '{DAV:}displayname';
const PROP_CALENDAR_DESCRIPTION = '{urn:ietf:params:xml:ns:caldav}calendar-description';
const PROP_CALENDAR_ORDER = '{http://apple.com/ns/ical/}calendar-order';
const PROP_CALENDAR_COLOR = '{http://apple.com/ns/ical/}calendar-color';
const PROP_CALENDAR_DATA = '{urn:ietf:params:xml:ns:caldav}calendar-data';
const PROP_ADDRESSBOOK_DATA = '{urn:ietf:params:xml:ns:carddav}address-data';
const PROP_OWNER = '{DAV:}owner';
const PROP_CTAG = '{http://calendarserver.org/ns/}getctag';
const PROP_ETAG = '{DAV:}getetag';
const PROP_CURRENT_USER_PRINCIPAL = '{DAV:}current-user-principal';
const PROP_CALENDAR_HOME_SET = '{urn:ietf:params:xml:ns:caldav}calendar-home-set';
const PROP_ADDRESSBOOK_HOME_SET = '{urn:ietf:params:xml:ns:carddav}addressbook-home-set';
const PROP_GROUP_MEMBERSHIP = '{DAV:}group-membership';
const PROP_GROUP_MEMBER_SET = '{DAV:}group-member-set';
/**
* @var string
*/
public $baseUrl;
/**
* @var string
*/
protected $user;
/**
* @var bool
*/
protected $connected;
/**
* @var string
*/
protected $protocol = 'http';
/**
* @var string
*/
protected $port = 80;
/**
* @var string
*/
protected $server;
/**
* @var bool
*/
public $isCustomServer = false;
/**
* @var \afterlogic\DAV\Client
*/
public $client;
/**
* @param string $baseUrl
* @param string $user
* @param string $pass
*/
public function __construct($baseUrl, $user, $pass)
{
$this->client = new \afterlogic\DAV\Client(
array(
'baseUri' => $baseUrl,
'userName' => $user,
'password' => $pass
)
);
$this->user = $user;
$aUrlParts = parse_url($baseUrl);
if (isset($aUrlParts['port']))
{
$this->port = $aUrlParts['port'];
}
$matches = array();
if (preg_match('#^(https?)://([a-z0-9.-]+)(:([0-9]+))?(/.*)$#', $baseUrl, $matches))
{
$this->protocol = $matches[1];
$this->server = $matches[2];
$this->baseUrl = $matches[5];
}
$this->connected = false;
}
/**
* @return bool
*/
public function Connect()
{
if ($this->connected === false)
{
$this->connected = $this->TestConnection();
}
return $this->connected;
}
/**
* @return bool
*/
public function TestConnection()
{
$res = $this->client->options_ex();
$this->isCustomServer = $res['custom-server'];
return true;
}
/**
* @return string
*/
public function GetBaseUrl()
{
return $this->baseUrl;
}
/**
* @return string
*/
public function GetRootUrl($url)
{
$urlParts = parse_url($url);
$path = '/';
if (isset($urlParts['path']))
{
$path = $urlParts['path'];
}
return $path;
}
/**
* @return string
*/
public function GetUser()
{
return $this->user;
}
/**
* @return string
*/
public function GetServer()
{
return $this->server;
}
/**
* @return string
*/
public function GetServerUrl()
{
$sPort = '';
if ((int)$this->port != 80)
{
$sPort = ':' . $this->port;
}
return $this->protocol . '://' . $_SERVER['SERVER_NAME'] . $sPort;
}
/**
* @param string $sUrl
* @param string $sData
*
* @return string
*/
function CreateItem($sUrl, $sData)
{
return $this->client->request(
'PUT',
$sUrl,
$sData,
array(
'If-None-Match' => '*'
)
);
}
/**
* @param string $sUrl
* @param string $sData
*
* @return string
*/
function UpdateItem($sUrl, $sData, $sEtag = '*')
{
return $this->client->request(
'PUT',
$sUrl,
$sData,
array(
// 'If-Match' => '"'.$sEtag.'"'
)
);
}
/**
* @param string $url
* @param string $icalData
*
* @return string
*/
function MoveItem($url, $newUrl)
{
return $this->client->request(
'MOVE',
$url,
'',
array(
'destination' => $newUrl
)
);
}
/**
* @param string $sSystemName
* @param string $sDisplayName
* @param string $sDescription
* @param int $iOrder
* @param string $sColor
* @param string $sCalendarHome
*
* @return string
*/
function CreateCalendar($sSystemName, $sDisplayName, $sDescription, $iOrder, $sColor,
$sCalendarHome)
{
$xml =
'<?xml version="1.0" encoding="UTF-8" ?>
<c:mkcalendar xmlns:c="'.\Sabre\CalDAV\Plugin::NS_CALDAV.'" xmlns:d="DAV:" xmlns:ic="http://apple.com/ns/ical/">
<d:set>
<d:prop>
<d:displayname>'.$sDisplayName.'</d:displayname>
<c:calendar-description>'.$sDescription.'</c:calendar-description>
<ic:calendar-order>'.$iOrder.'</ic:calendar-order>
<ic:calendar-color>'.$sColor.'</ic:calendar-color>
</d:prop>
</d:set>
</c:mkcalendar>';
return $this->client->request(
'MKCALENDAR',
$sCalendarHome.$sSystemName,
$xml,
array(
'Content-Type' => 'application/xml',
'Depth' => '1'
)
);
}
/**
* @param string $sCalendarId
* @param string $sDisplayName
* @param string $sDescription
* @param int $iOrder
* @param string $sColor
*
* @return array
*/
function UpdateCalendar($sCalendarId, $sDisplayName, $sDescription, $iOrder, $sColor)
{
return $this->client->propPatch(
$sCalendarId,
array(
self::PROP_DISPLAYNAME => $sDisplayName,
self::PROP_CALENDAR_DESCRIPTION => $sDescription,
self::PROP_CALENDAR_ORDER => $iOrder,
self::PROP_CALENDAR_COLOR => $sColor
)
);
}
/**
* @param string $sCalendarId
* @param string $sColor
*
* @return array
*/
function UpdateCalendarColor($sCalendarId, $sColor)
{
return $this->client->propPatch(
$sCalendarId,
array(
self::PROP_CALENDAR_COLOR => $sColor
)
);
}
/**
* @param string $url
*/
function DeleteItem($url)
{
return $this->client->request('DELETE', $url);
}
/**
* @param string $filter
* @param string $url
*
* @return array
*/
function QueryCal($filter, $url = '')
{
$xml =
'<?xml version="1.0" encoding="utf-8" ?>
<c:calendar-query xmlns:d="DAV:" xmlns:c="'.\Sabre\CalDAV\Plugin::NS_CALDAV.'">
<d:prop>
<d:getetag/>
<c:calendar-data/>
</d:prop>
'.$filter.'
</c:calendar-query>';
$res = array();
try
{
$res = $this->client->request(
'REPORT',
$url,
$xml,
array(
'Content-Type' => 'application/xml',
'Depth' => '1'
)
);
}
catch(\Sabre\DAV\Exception $ex)
{
return false;
}
$aStatus = $this->client->parseMultiStatus($res['body']);
$report = array();
foreach($aStatus as $key => $props)
{
$response = array();
if (count($props) > 0)
{
$response['url'] = $url;
$response['href'] = basename($key);
$response['etag'] = isset($props[200]) ? preg_replace('/^"?([^"]+)"?/', '$1', $props[200][self::PROP_ETAG]) : '';
$response['data'] = isset($props[200]) ? $props[200][self::PROP_CALENDAR_DATA] : '';
$report[] = $response;
}
}
return $report;
}
/**
* @param string $filter
* @param string $url
*
* @return array
*/
function QueryCard($filter, $url = '')
{
$xml =
'<?xml version="1.0" encoding="utf-8" ?>
<c:addressbook-query xmlns:d="DAV:" xmlns:c="'.\Sabre\CardDAV\Plugin::NS_CARDDAV.'">
<d:prop>
<d:getetag/>
<c:address-data>
<c:allprop />
</c:address-data>
</d:prop>
'.$filter.'
</c:addressbook-query>';
$res = array();
try
{
$res = $this->client->request(
'REPORT',
$url,
$xml,
array(
'Content-Type' => 'application/xml',
'Depth' => '1'
)
);
}
catch(\Sabre\DAV\Exception $ex)
{
return false;
}
$aStatus = $this->client->parseMultiStatus($res['body']);
$report = array();
foreach($aStatus as $key => $props)
{
$response = array();
$response['href'] = basename($key);
$response['etag'] = isset($props[200]) ? preg_replace('/^"?([^"]+)"?/', '$1', $props[200][self::PROP_ETAG]) : '';
$response['data'] = isset($props[200]) ? $props[200][self::PROP_ADDRESSBOOK_DATA] : '';
$report[] = $response;
}
return $report;
}
function GetVcards($url = '', $sSearch = '', $sGroupId = '')
{
$sFilter = '';
$sGroupFilter = '';
$sSearchFilter = '';
if (!empty($sGroupId))
{
$sGroupFilter =
' <c:prop-filter name="CATEGORIES">
<c:text-match icollation="i;octet" match-type="contains">'.$sGroupId.'</c:text-match>
</c:prop-filter>';
}
if (!empty($sSearch))
{
$sSearchFilter =
' <c:prop-filter name="FN">
<c:text-match icollation="i;octet" match-type="contains">'.$sSearch.'</c:text-match>
</c:prop-filter>
<c:prop-filter name="N">
<c:text-match icollation="i;octet" match-type="contains">'.$sSearch.'</c:text-match>
</c:prop-filter>
<c:prop-filter name="EMAIL">
<c:text-match icollation="i;octet" match-type="contains">'.$sSearch.'</c:text-match>
</c:prop-filter>
<c:prop-filter name="NICKNAME">
<c:text-match icollation="i;octet" match-type="contains">'.$sSearch.'</c:text-match>
</c:prop-filter>';
}
if (!empty($sSearch) || !empty($sGroupId))
{
$sFilter =
' <c:filter>
' . $sSearchFilter
. $sGroupFilter . '
</c:filter>';
}
return $this->QueryCard($sFilter, $url);
}
/**
* @param timestamp $start
* @param timestamp $end
*
* @return string
*/
function GetTimeRange($start = null, $end = null)
{
$timeRange = '';
$startRange = '';
$endRange = '';
if (isset($start) || isset($end))
{
if (isset($start))
{
$startRange = 'start="'.$start.'"';
}
if (isset($end))
{
$endRange = 'end="'.$end.'"';
}
$timeRange = sprintf('<c:time-range %s %s/>', $startRange, $endRange);
}
return $timeRange;
}
/**
* @param string $url
* @param timestamp $start
* @param timestamp $finish
*
* @return array
*/
function GetEvents($url = '', $start = null, $finish = null)
{
$timeRange = $this->GetTimeRange($start, $finish);
$url = rtrim($url, '/') . '/';
$filter =
'<c:filter>
<c:comp-filter name="VCALENDAR">
<c:comp-filter name="VEVENT">
'.$timeRange.'
</c:comp-filter>
</c:comp-filter>
</c:filter>';
return $this->QueryCal($filter, $url);
}
/**
* @param string $sCalendarUrl
* @param string $sUid
*
* @return array
*/
function GetEventByUid($sCalendarUrl, $sUid)
{
$filter =
' <c:filter>
<c:comp-filter name="VCALENDAR">
<c:comp-filter name="VEVENT">
<c:prop-filter name="UID">
<c:text-match icollation="i;octet">'.$sUid.'</c:text-match>
</c:prop-filter>
</c:comp-filter>
</c:comp-filter>
</c:filter>';
$result = $this->QueryCal($filter, $sCalendarUrl);
if ($result !== false)
{
return current($result);
}
else
{
return false;
}
}
/**
* @param string $url
*
* @return string
*/
function GetItem($url = '')
{
$res = $this->clietn->request('GET', $url);
if ($res !== false)
{
return $res['body'];
}
return $res;
}
/**
* @param string $url
* @param timestamp $start
* @param timestamp $finish
*
* @return array
*/
function GetAlarms($url = '', $start = null, $finish = null)
{
$timeRange = $this->GetTimeRange($start, $finish);
$url = rtrim($url, '/') . '/';
$filter =
'<c:filter>
<c:comp-filter name="VCALENDAR">
<c:comp-filter name="VEVENT">
<c:comp-filter name="VALARM">
'.$timeRange.'
</c:comp-filter>
</c:comp-filter>
</c:comp-filter>
</c:filter>';
// $recurrenceSet = '<c:limit-recurrence-set start="'.$start.'" end="'.$finish.'"/>';
return $this->QueryCal($filter, $url);
}
/**
* @param timestamp $start
* @param timestamp $finish
* @param boolean $completed
* @param boolean $cancelled
* @param string $url
*
* @return array
*/
function GetTodos($start, $finish, $completed = false, $cancelled = false, $url = '')
{
$timeRange = $this->GetTimeRange($start, $finish);
// Warning! May contain traces of double negatives...
$negateCancelled = ($cancelled === true ? 'no' : 'yes');
$negateCompleted = ($cancelled === true ? 'no' : 'yes');
$filter =
'<c:filter>
<c:comp-filter name="VCALENDAR">
<c:comp-filter name="VTODO">
<c:prop-filter name="STATUS">
<c:text-match negate-condition="'.$negateCompleted.'">COMPLETED</c:text-match>
</c:prop-filter>
<c:prop-filter name="STATUS">
<C:text-match negate-condition="'.$negateCancelled.'">CANCELLED</c:text-match>
</c:prop-filter>
' . $timeRange . '
</c:comp-filter>
</c:comp-filter>
</c:filter>';
return $this->QueryCal($filter, $url);
}
/**
* @param string url
*
* @return array
*/
function GetCalendar($url = '')
{
$filter =
'<c:filter>
<c:comp-filter name="VCALENDAR"></c:comp-filter>
</c:filter>';
return $this->QueryCal($filter, $url);
}
function GetCurrentPrincipal()
{
$res = $this->client->propFind('', array(self::PROP_CURRENT_USER_PRINCIPAL));
return $res[self::PROP_CURRENT_USER_PRINCIPAL];
}
/**
* @param string $principal
*/
function GetPrincipalMembers($principal = '')
{
$res = array();
try
{
$res = $this->client->propFind(
$principal,
array(
self::PROP_GROUP_MEMBERSHIP
),
1
);
}
catch(Exception $ex)
{
return array();
}
return $res[self::PROP_GROUP_MEMBERSHIP];
}
/**
* @param $principalUrl string
*/
function GetCalendarHomeSet($principalUrl = '')
{
$props = $this->client->propFind(
$principalUrl,
array(
self::PROP_CALENDAR_HOME_SET
)
);
return $props[self::PROP_CALENDAR_HOME_SET];
}
/**
* @param $principalUrl string
*/
function GetAddressBookHomeSet($principalUrl = '')
{
$props = $this->client->propFind(
$principalUrl,
array(
self::PROP_ADDRESSBOOK_HOME_SET
)
);
return $props[self::PROP_ADDRESSBOOK_HOME_SET];
}
function GetAddressBooks($url = '')
{
$aProps = $this->client->propFind(
$url,
array(
self::PROP_RESOURCETYPE,
self::PROP_DISPLAYNAME
),
1
);
return $aProps;
}
function GetCalendars($url = '')
{
$calendars = array();
$aProps = $this->client->propFind(
$url,
array(
self::PROP_RESOURCETYPE,
self::PROP_DISPLAYNAME,
self::PROP_OWNER,
self::PROP_CTAG,
self::PROP_CALENDAR_DESCRIPTION,
self::PROP_CALENDAR_COLOR,
self::PROP_CALENDAR_ORDER
),
1
);
foreach($aProps as $key=>$props)
{
if ($props['{DAV:}resourcetype']->is('{'.\Sabre\CalDAV\Plugin::NS_CALDAV.'}calendar'))
{
$calendar = new CCalendar($key);
$calendar->CTag = $props[self::PROP_CTAG];
$calendar->DisplayName = $props[self::PROP_DISPLAYNAME];
$calendar->Principals[] = isset($props[self::PROP_OWNER])?$props[self::PROP_OWNER]:'';
$calendar->Description = isset($props[self::PROP_CALENDAR_DESCRIPTION])?$props[self::PROP_CALENDAR_DESCRIPTION]:'';
$calendar->Color = isset($props[self::PROP_CALENDAR_COLOR])?$props[self::PROP_CALENDAR_COLOR]:'';
if (strlen($calendar->Color) > 7)
{
$calendar->Color = substr($calendar->Color, 0, 7);
}
if (isset($props[self::PROP_CALENDAR_ORDER]))
{
$calendar->Order = $props[self::PROP_CALENDAR_ORDER];
}
$calendars[$calendar->Id] = $calendar;
}
}
return $calendars;
}
function GetVcardByUid($uid, $url = '')
{
$filter = "";
if ($uid)
{
$filter =
'<c:filter>
<c:prop-filter name="UID">
<c:text-match collation="i;unicode-casemap" match-type="equals">'.$uid.'</c:text-match>
</c:prop-filter>
</c:filter>';
}
return $this->QueryCard($filter, $url);
}
function GetProxies($sProxy)
{
$res = array();
try
{
$res = $this->client->propFind(
$sProxy,
array(
self::PROP_GROUP_MEMBER_SET
),
1
);
}
catch(Exception $ex)
{
return array();
}
return $res[self::PROP_GROUP_MEMBER_SET];
}
function AddProxy($proxy, $to)
{
$sProxyStr = '';
$aCurrentProxies = array();
$duplicate = false;
$aCurrentProxies = $this->GetProxies($proxy);
if($aCurrentProxies)
{
foreach($aCurrentProxies as $sCurrentProxy => $val)
{
$sCurrentProxy = ltrim($sCurrentProxy, DAV_ROOT);
if($sCurrentProxy == $proxy)
{
$duplicate = true;
}
$sProxyStr .= '<d:href>' . $sCurrentProxy . '</d:href>';
}
}
if($duplicate)
{
return false;
}
$sProxyStr .= '<d:href>' . \afterlogic\DAV\Constants::PRINCIPALS_PREFIX . '/' . $to . '</d:href>';
return $this->client->propPatch($proxy, array('group-member-set'=>$sProxyStr));
}
function DeleteProxy($proxy, $to)
{
$aCurrentProxies = $this->GetProxies($proxy);
$sProxyStr = "";
if($aCurrentProxies)
{
foreach($aCurrentProxies as $sCurrentProxy => $val)
{
$sCurrentProxy = ltrim($sCurrentProxy, DAV_ROOT);
$sProxyStr .= '<d:href>' . $sCurrentProxy . '</d:href>';
}
}
$sProxyStr = str_replace('<d:href>' . \afterlogic\DAV\Constants::PRINCIPALS_PREFIX . '/' . $to . '</d:href>', '', $sProxyStr);
return $this->client->propPatch(
$proxy,
array(
'group-member-set'=>$sProxyStr
)
);
}
/**
* Returns a list of calendar homes for principals the current
* user has access to through the calendar-proxy functionality.
*
* @return array
*/
public function GetCalendarProxiedFor($principalUrl)
{
$body =
'<?xml version="1.0"?>
<d:expand-property xmlns:d="DAV:">
<d:property name="calendar-proxy-read-for" namespace="'.\Sabre\CalDAV\Plugin::NS_CALENDARSERVER.'">
<d:property name="calendar-home-set" namespace="'.\Sabre\CalDAV\Plugin::NS_CALDAV.'" />
</d:property>
<d:property name="calendar-proxy-write-for" namespace="'.\Sabre\CalDAV\Plugin::NS_CALENDARSERVER.'">
<d:property name="calendar-home-set" namespace="'.\Sabre\CalDAV\Plugin::NS_CALDAV.'" />
</d:property>
</d:expand-property>';
$res = $this->client->request(
'REPORT',
$principalUrl,
$body,
array(
'Content-Type' => 'application/xml',
'Depth' => '1'
)
);
if(isset($res['body']))
{
$data = new DOMDocument();
$data->loadXML($res['body'], LIBXML_NOERROR | LIBXML_NOWARNING | LIBXML_NSCLEAN);
$xp = new DOMXPath($data);
$xp->registerNamespace('c', \Sabre\CalDAV\Plugin::NS_CALDAV);
$xp->registerNamespace('cs', \Sabre\CalDAV\Plugin::NS_CALENDARSERVER);
$xp->registerNamespace('d', 'urn:dav');
$values = array();
$result = $xp->query("/d:multistatus/d:response/d:propstat/d:prop/cs:calendar-proxy-read-for/d:response/d:propstat/d:prop/c:calendar-home-set/d:href");
foreach($result as $elem)
{
$values[] = array(
'href' => $elem->nodeValue,
'mode' => 'read'
);
}
$result = $xp->query("/d:multistatus/d:response/d:propstat/d:prop/cs:calendar-proxy-write-for/d:response/d:propstat/d:prop/c:calendar-home-set/d:href");
foreach($result as $elem)
{
$values[] = array(
'href' => $elem->nodeValue,
'mode' => 'write'
);
}
return $values;
}
return array();
}
}