Обновление клиента (apps, 3rdparty, install)

This commit is contained in:
root
2026-03-16 08:42:57 +00:00
parent b8905de237
commit f390426546
3354 changed files with 505213 additions and 3 deletions
+17
View File
@@ -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
{
}
+178
View File
@@ -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/',
];
}
}
+17
View File
@@ -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
View File
@@ -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
View File
@@ -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,
],
];
}
}
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,
],
];
}
}