Обновление клиента (apps, 3rdparty, install)
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sabre\CalDAV\Schedule;
|
||||
|
||||
/**
|
||||
* Implement this interface to have a node be recognized as a CalDAV scheduling
|
||||
* inbox.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
interface IInbox extends \Sabre\CalDAV\ICalendarObjectContainer, \Sabre\DAVACL\IACL
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sabre\CalDAV\Schedule;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\VObject\ITip;
|
||||
|
||||
/**
|
||||
* iMIP handler.
|
||||
*
|
||||
* This class is responsible for sending out iMIP messages. iMIP is the
|
||||
* email-based transport for iTIP. iTIP deals with scheduling operations for
|
||||
* iCalendar objects.
|
||||
*
|
||||
* If you want to customize the email that gets sent out, you can do so by
|
||||
* extending this class and overriding the sendMessage method.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class IMipPlugin extends DAV\ServerPlugin
|
||||
{
|
||||
/**
|
||||
* Email address used in From: header.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $senderEmail;
|
||||
|
||||
/**
|
||||
* Creates the email handler.
|
||||
*
|
||||
* @param string $senderEmail. The 'senderEmail' is the email that shows up
|
||||
* in the 'From:' address. This should
|
||||
* generally be some kind of no-reply email
|
||||
* address you own.
|
||||
*/
|
||||
public function __construct($senderEmail)
|
||||
{
|
||||
$this->senderEmail = $senderEmail;
|
||||
}
|
||||
|
||||
/*
|
||||
* This initializes the plugin.
|
||||
*
|
||||
* This function is called by Sabre\DAV\Server, after
|
||||
* addPlugin is called.
|
||||
*
|
||||
* This method should set up the required event subscriptions.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(DAV\Server $server)
|
||||
{
|
||||
$server->on('schedule', [$this, 'schedule'], 120);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a plugin name.
|
||||
*
|
||||
* Using this name other plugins will be able to access other plugins
|
||||
* using \Sabre\DAV\Server::getPlugin
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPluginName()
|
||||
{
|
||||
return 'imip';
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler for the 'schedule' event.
|
||||
*/
|
||||
public function schedule(ITip\Message $iTipMessage)
|
||||
{
|
||||
// Not sending any emails if the system considers the update
|
||||
// insignificant.
|
||||
if (!$iTipMessage->significantChange) {
|
||||
if (!$iTipMessage->scheduleStatus) {
|
||||
$iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$summary = $iTipMessage->message->VEVENT->SUMMARY;
|
||||
|
||||
if ('mailto' !== parse_url($iTipMessage->sender, PHP_URL_SCHEME)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ('mailto' !== parse_url($iTipMessage->recipient, PHP_URL_SCHEME)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sender = substr($iTipMessage->sender, 7);
|
||||
$recipient = substr($iTipMessage->recipient, 7);
|
||||
|
||||
if ($iTipMessage->senderName) {
|
||||
$sender = $iTipMessage->senderName.' <'.$sender.'>';
|
||||
}
|
||||
if ($iTipMessage->recipientName && $iTipMessage->recipientName != $recipient) {
|
||||
$recipient = $iTipMessage->recipientName.' <'.$recipient.'>';
|
||||
}
|
||||
|
||||
$subject = 'SabreDAV iTIP message';
|
||||
switch (strtoupper($iTipMessage->method)) {
|
||||
case 'REPLY':
|
||||
$subject = 'Re: '.$summary;
|
||||
break;
|
||||
case 'REQUEST':
|
||||
$subject = 'Invitation: '.$summary;
|
||||
break;
|
||||
case 'CANCEL':
|
||||
$subject = 'Cancelled: '.$summary;
|
||||
break;
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Reply-To: '.$sender,
|
||||
'From: '.$iTipMessage->senderName.' <'.$this->senderEmail.'>',
|
||||
'MIME-Version: 1.0',
|
||||
'Content-Type: text/calendar; charset=UTF-8; method='.$iTipMessage->method,
|
||||
];
|
||||
if (DAV\Server::$exposeVersion) {
|
||||
$headers[] = 'X-Sabre-Version: '.DAV\Version::VERSION;
|
||||
}
|
||||
$this->mail(
|
||||
$recipient,
|
||||
$subject,
|
||||
$iTipMessage->message->serialize(),
|
||||
$headers
|
||||
);
|
||||
$iTipMessage->scheduleStatus = '1.1; Scheduling message is sent via iMip';
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
// This is deemed untestable in a reasonable manner
|
||||
|
||||
/**
|
||||
* This function is responsible for sending the actual email.
|
||||
*
|
||||
* @param string $to Recipient email address
|
||||
* @param string $subject Subject of the email
|
||||
* @param string $body iCalendar body
|
||||
* @param array $headers List of headers
|
||||
*/
|
||||
protected function mail($to, $subject, $body, array $headers)
|
||||
{
|
||||
mail($to, $subject, $body, implode("\r\n", $headers));
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
/**
|
||||
* Returns a bunch of meta-data about the plugin.
|
||||
*
|
||||
* Providing this information is optional, and is mainly displayed by the
|
||||
* Browser plugin.
|
||||
*
|
||||
* The description key in the returned array may contain html and will not
|
||||
* be sanitized.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPluginInfo()
|
||||
{
|
||||
return [
|
||||
'name' => $this->getPluginName(),
|
||||
'description' => 'Email delivery (rfc6047) for CalDAV scheduling',
|
||||
'link' => 'http://sabre.io/dav/scheduling/',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sabre\CalDAV\Schedule;
|
||||
|
||||
/**
|
||||
* Implement this interface to have a node be recognized as a CalDAV scheduling
|
||||
* outbox.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
interface IOutbox extends \Sabre\DAV\ICollection, \Sabre\DAVACL\IACL
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sabre\CalDAV\Schedule;
|
||||
|
||||
/**
|
||||
* The SchedulingObject represents a scheduling object in the Inbox collection.
|
||||
*
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
*/
|
||||
interface ISchedulingObject extends \Sabre\CalDAV\ICalendarObject
|
||||
{
|
||||
}
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sabre\CalDAV\Schedule;
|
||||
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\CalDAV\Backend;
|
||||
use Sabre\DAV;
|
||||
use Sabre\DAVACL;
|
||||
use Sabre\VObject;
|
||||
|
||||
/**
|
||||
* The CalDAV scheduling inbox.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class Inbox extends DAV\Collection implements IInbox
|
||||
{
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* CalDAV backend.
|
||||
*
|
||||
* @var Backend\BackendInterface
|
||||
*/
|
||||
protected $caldavBackend;
|
||||
|
||||
/**
|
||||
* The principal Uri.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $principalUri;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $principalUri
|
||||
*/
|
||||
public function __construct(Backend\SchedulingSupport $caldavBackend, $principalUri)
|
||||
{
|
||||
$this->caldavBackend = $caldavBackend;
|
||||
$this->principalUri = $principalUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the node.
|
||||
*
|
||||
* This is used to generate the url.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'inbox';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with all the child nodes.
|
||||
*
|
||||
* @return \Sabre\DAV\INode[]
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
$objs = $this->caldavBackend->getSchedulingObjects($this->principalUri);
|
||||
$children = [];
|
||||
foreach ($objs as $obj) {
|
||||
//$obj['acl'] = $this->getACL();
|
||||
$obj['principaluri'] = $this->principalUri;
|
||||
$children[] = new SchedulingObject($this->caldavBackend, $obj);
|
||||
}
|
||||
|
||||
return $children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file in the directory.
|
||||
*
|
||||
* Data will either be supplied as a stream resource, or in certain cases
|
||||
* as a string. Keep in mind that you may have to support either.
|
||||
*
|
||||
* After successful creation of the file, you may choose to return the ETag
|
||||
* of the new file here.
|
||||
*
|
||||
* The returned ETag must be surrounded by double-quotes (The quotes should
|
||||
* be part of the actual string).
|
||||
*
|
||||
* If you cannot accurately determine the ETag, you should not return it.
|
||||
* If you don't store the file exactly as-is (you're transforming it
|
||||
* somehow) you should also not return an ETag.
|
||||
*
|
||||
* This means that if a subsequent GET to this new file does not exactly
|
||||
* return the same contents of what was submitted here, you are strongly
|
||||
* recommended to omit the ETag.
|
||||
*
|
||||
* @param string $name Name of the file
|
||||
* @param resource|string $data Initial payload
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function createFile($name, $data = null)
|
||||
{
|
||||
$this->caldavBackend->createSchedulingObject($this->principalUri, $name, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal.
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner()
|
||||
{
|
||||
return $this->principalUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
* Each ACE has the following properties:
|
||||
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
|
||||
* currently the only supported privileges
|
||||
* * 'principal', a url to the principal who owns the node
|
||||
* * 'protected' (optional), indicating that this ACE is not allowed to
|
||||
* be updated.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getACL()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => '{DAV:}authenticated',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write-properties',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}unbind',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}unbind',
|
||||
'principal' => $this->getOwner().'/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{'.CalDAV\Plugin::NS_CALDAV.'}schedule-deliver',
|
||||
'principal' => '{DAV:}authenticated',
|
||||
'protected' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a calendar-query on the contents of this calendar.
|
||||
*
|
||||
* The calendar-query is defined in RFC4791 : CalDAV. Using the
|
||||
* calendar-query it is possible for a client to request a specific set of
|
||||
* object, based on contents of iCalendar properties, date-ranges and
|
||||
* iCalendar component types (VTODO, VEVENT).
|
||||
*
|
||||
* This method should just return a list of (relative) urls that match this
|
||||
* query.
|
||||
*
|
||||
* The list of filters are specified as an array. The exact array is
|
||||
* documented by \Sabre\CalDAV\CalendarQueryParser.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function calendarQuery(array $filters)
|
||||
{
|
||||
$result = [];
|
||||
$validator = new CalDAV\CalendarQueryValidator();
|
||||
|
||||
$objects = $this->caldavBackend->getSchedulingObjects($this->principalUri);
|
||||
foreach ($objects as $object) {
|
||||
$vObject = VObject\Reader::read($object['calendardata']);
|
||||
if ($validator->validate($vObject, $filters)) {
|
||||
$result[] = $object['uri'];
|
||||
}
|
||||
|
||||
// Destroy circular references to PHP will GC the object.
|
||||
$vObject->destroy();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sabre\CalDAV\Schedule;
|
||||
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\DAV;
|
||||
use Sabre\DAVACL;
|
||||
|
||||
/**
|
||||
* The CalDAV scheduling outbox.
|
||||
*
|
||||
* The outbox is mainly used as an endpoint in the tree for a client to do
|
||||
* free-busy requests. This functionality is completely handled by the
|
||||
* Scheduling plugin, so this object is actually mostly static.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class Outbox extends DAV\Collection implements IOutbox
|
||||
{
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* The principal Uri.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $principalUri;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $principalUri
|
||||
*/
|
||||
public function __construct($principalUri)
|
||||
{
|
||||
$this->principalUri = $principalUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the node.
|
||||
*
|
||||
* This is used to generate the url.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'outbox';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with all the child nodes.
|
||||
*
|
||||
* @return \Sabre\DAV\INode[]
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal.
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner()
|
||||
{
|
||||
return $this->principalUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
* Each ACE has the following properties:
|
||||
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
|
||||
* currently the only supported privileges
|
||||
* * 'principal', a url to the principal who owns the node
|
||||
* * 'protected' (optional), indicating that this ACE is not allowed to
|
||||
* be updated.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getACL()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'privilege' => '{'.CalDAV\Plugin::NS_CALDAV.'}schedule-send',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{'.CalDAV\Plugin::NS_CALDAV.'}schedule-send',
|
||||
'principal' => $this->getOwner().'/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner().'/calendar-proxy-read',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner().'/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
+1006
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sabre\CalDAV\Schedule;
|
||||
|
||||
use Sabre\CalDAV\Backend;
|
||||
use Sabre\DAV\Exception\MethodNotAllowed;
|
||||
|
||||
/**
|
||||
* The SchedulingObject represents a scheduling object in the Inbox collection.
|
||||
*
|
||||
* @author Brett (https://github.com/bretten)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
*/
|
||||
class SchedulingObject extends \Sabre\CalDAV\CalendarObject implements ISchedulingObject
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* The following properties may be passed within $objectData:
|
||||
*
|
||||
* * uri - A unique uri. Only the 'basename' must be passed.
|
||||
* * principaluri - the principal that owns the object.
|
||||
* * calendardata (optional) - The iCalendar data
|
||||
* * etag - (optional) The etag for this object, MUST be encloded with
|
||||
* double-quotes.
|
||||
* * size - (optional) The size of the data in bytes.
|
||||
* * lastmodified - (optional) format as a unix timestamp.
|
||||
* * acl - (optional) Use this to override the default ACL for the node.
|
||||
*/
|
||||
public function __construct(Backend\SchedulingSupport $caldavBackend, array $objectData)
|
||||
{
|
||||
parent::__construct($caldavBackend, [], $objectData);
|
||||
|
||||
if (!isset($objectData['uri'])) {
|
||||
throw new \InvalidArgumentException('The objectData argument must contain an \'uri\' property');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ICalendar-formatted object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
// Pre-populating the 'calendardata' is optional, if we don't have it
|
||||
// already we fetch it from the backend.
|
||||
if (!isset($this->objectData['calendardata'])) {
|
||||
$this->objectData = $this->caldavBackend->getSchedulingObject($this->objectData['principaluri'], $this->objectData['uri']);
|
||||
}
|
||||
|
||||
return $this->objectData['calendardata'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ICalendar-formatted object.
|
||||
*
|
||||
* @param string|resource $calendarData
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function put($calendarData)
|
||||
{
|
||||
throw new MethodNotAllowed('Updating scheduling objects is not supported');
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the scheduling message.
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$this->caldavBackend->deleteSchedulingObject($this->objectData['principaluri'], $this->objectData['uri']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal.
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner()
|
||||
{
|
||||
return $this->objectData['principaluri'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
* Each ACE has the following properties:
|
||||
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
|
||||
* currently the only supported privileges
|
||||
* * 'principal', a url to the principal who owns the node
|
||||
* * 'protected' (optional), indicating that this ACE is not allowed to
|
||||
* be updated.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getACL()
|
||||
{
|
||||
// An alternative acl may be specified in the object data.
|
||||
//
|
||||
|
||||
if (isset($this->objectData['acl'])) {
|
||||
return $this->objectData['acl'];
|
||||
}
|
||||
|
||||
// The default ACL
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => '{DAV:}owner',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => $this->objectData['principaluri'].'/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->objectData['principaluri'].'/calendar-proxy-read',
|
||||
'protected' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user