initial sabre upgrade (needs lots of work - to wit: authentication, redo the browser interface, and rework event export/import)
This commit is contained in:
		| @@ -60,8 +60,16 @@ class Dav extends \Zotlabs\Web\Controller { | ||||
| 		if ($which) | ||||
| 			profile_load($a, $which, $profile); | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 		$auth = new \Zotlabs\Storage\BasicAuth(); | ||||
|  | ||||
| 		$authBackend = new \Sabre\DAV\Auth\Backend\BasicCallBack(function($userName,$password) { | ||||
| 			if(account_verify_password($userName,$password)) | ||||
| 				return true; | ||||
| 			return false; | ||||
| 		}); | ||||
|  | ||||
| 		$ob_hash = get_observer_hash(); | ||||
| 	 | ||||
| 		if ($ob_hash) { | ||||
| @@ -92,6 +100,12 @@ class Dav extends \Zotlabs\Web\Controller { | ||||
| 	 | ||||
| 		// A SabreDAV server-object | ||||
| 		$server = new SDAV\Server($rootDirectory); | ||||
|  | ||||
|  | ||||
| 		$authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend); | ||||
| 		$server->addPlugin($authPlugin); | ||||
|  | ||||
|  | ||||
| 		// prevent overwriting changes each other with a lock backend | ||||
| 		$lockBackend = new SDAV\Locks\Backend\File('store/[data]/locks'); | ||||
| 		$lockPlugin = new SDAV\Locks\Plugin($lockBackend); | ||||
|   | ||||
| @@ -101,8 +101,8 @@ class Browser extends DAV\Browser\Plugin { | ||||
| 		$parentpath = array(); | ||||
| 		// only show parent if not leaving /cloud/; TODO how to improve this?  | ||||
| 		if ($path && $path != "cloud") { | ||||
| 			list($parentUri) = DAV\URLUtil::splitPath($path); | ||||
| 			$fullPath = DAV\URLUtil::encodePath($this->server->getBaseUri() . $parentUri); | ||||
| 			list($parentUri) = \Sabre\HTTP\URLUtil::splitPath($path); | ||||
| 			$fullPath = \Sabre\HTTP\URLUtil::encodePath($this->server->getBaseUri() . $parentUri); | ||||
|  | ||||
| 			$parentpath['icon'] = $this->enableAssets ? '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl('icons/parent' . $this->iconExtension) . '" width="24" alt="' . t('parent') . '"></a>' : ''; | ||||
| 			$parentpath['path'] = $fullPath; | ||||
| @@ -116,7 +116,7 @@ class Browser extends DAV\Browser\Plugin { | ||||
| 			// This is the current directory, we can skip it | ||||
| 			if (rtrim($file['href'],'/') == $path) continue; | ||||
|  | ||||
| 			list(, $name) = DAV\URLUtil::splitPath($file['href']); | ||||
| 			list(, $name) = \Sabre\HTTP\URLUtil::splitPath($file['href']); | ||||
|  | ||||
| 			if (isset($file[200]['{DAV:}resourcetype'])) { | ||||
| 				$type = $file[200]['{DAV:}resourcetype']->getValue(); | ||||
| @@ -166,7 +166,7 @@ class Browser extends DAV\Browser\Plugin { | ||||
| 			$size = isset($file[200]['{DAV:}getcontentlength']) ? (int)$file[200]['{DAV:}getcontentlength'] : ''; | ||||
| 			$lastmodified = ((isset($file[200]['{DAV:}getlastmodified'])) ? $file[200]['{DAV:}getlastmodified']->getTime()->format('Y-m-d H:i:s') : ''); | ||||
|  | ||||
| 			$fullPath = DAV\URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path ? $path . '/' : '') . $name, '/')); | ||||
| 			$fullPath = \Sabre\HTTP\URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path ? $path . '/' : '') . $name, '/')); | ||||
|  | ||||
|  | ||||
| 			$displayName = isset($file[200]['{DAV:}displayname']) ? $file[200]['{DAV:}displayname'] : $name; | ||||
| @@ -219,7 +219,7 @@ class Browser extends DAV\Browser\Plugin { | ||||
|  | ||||
| 		$output = ''; | ||||
| 		if ($this->enablePost) { | ||||
| 			$this->server->broadcastEvent('onHTMLActionsPanel', array($parent, &$output)); | ||||
| 			$this->server->emit('onHTMLActionsPanel', array($parent, &$output)); | ||||
| 		} | ||||
|  | ||||
| 		$html .= replace_macros(get_markup_template('cloud.tpl'), array( | ||||
|   | ||||
| @@ -539,16 +539,16 @@ function event_import_ical($ical, $uid) { | ||||
|  | ||||
| //	logger('dtstart: ' . var_export($dtstart,true)); | ||||
|  | ||||
|  | ||||
| 	switch($dtstart->timezone_type) { | ||||
| 		case VObject\Property\DateTime::UTC : | ||||
| 			$ev['adjust'] = 0; | ||||
| 			break; | ||||
| 		case VObject\Property\DateTime::LOCALTZ : | ||||
| 		default: | ||||
| 			$ev['adjust'] = 1; | ||||
| 			break; | ||||
| 	} | ||||
| // @FIXME - convert/upgrade to vobject [3|4] | ||||
| //	switch($dtstart->timezone_type) { | ||||
| //		case VObject\Property\DateTime::UTC : | ||||
| //			$ev['adjust'] = 0; | ||||
| //			break; | ||||
| //		case VObject\Property\DateTime::LOCALTZ : | ||||
| //		default: | ||||
| //			$ev['adjust'] = 1; | ||||
| //			break; | ||||
| //	} | ||||
|  | ||||
| 	$ev['start'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC', | ||||
| 		$dtstart->format(\DateTime::W3C)); | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/autoload.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/autoload.php
									
									
									
									
										vendored
									
									
								
							| @@ -4,4 +4,4 @@ | ||||
|  | ||||
| require_once __DIR__ . '/composer' . '/autoload_real.php'; | ||||
|  | ||||
| return ComposerAutoloaderInita478c0bdc9041edcc4f485e8fb39b90d::getLoader(); | ||||
| return ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785::getLoader(); | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/bin/generate_vcards
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								vendor/bin/generate_vcards
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | ||||
| ../sabre/vobject/bin/generate_vcards | ||||
							
								
								
									
										1
									
								
								vendor/bin/naturalselection
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								vendor/bin/naturalselection
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | ||||
| ../sabre/dav/bin/naturalselection | ||||
							
								
								
									
										1
									
								
								vendor/bin/sabredav
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								vendor/bin/sabredav
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | ||||
| ../sabre/dav/bin/sabredav | ||||
							
								
								
									
										1
									
								
								vendor/bin/vobject
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								vendor/bin/vobject
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | ||||
| ../sabre/vobject/bin/vobject | ||||
							
								
								
									
										42
									
								
								vendor/composer/ClassLoader.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								vendor/composer/ClassLoader.php
									
									
									
									
										vendored
									
									
								
							| @@ -13,9 +13,7 @@ | ||||
| namespace Composer\Autoload; | ||||
|  | ||||
| /** | ||||
|  * ClassLoader implements a PSR-0 class loader | ||||
|  * | ||||
|  * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md | ||||
|  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. | ||||
|  * | ||||
|  *     $loader = new \Composer\Autoload\ClassLoader(); | ||||
|  * | ||||
| @@ -39,6 +37,8 @@ namespace Composer\Autoload; | ||||
|  * | ||||
|  * @author Fabien Potencier <fabien@symfony.com> | ||||
|  * @author Jordi Boggiano <j.boggiano@seld.be> | ||||
|  * @see    http://www.php-fig.org/psr/psr-0/ | ||||
|  * @see    http://www.php-fig.org/psr/psr-4/ | ||||
|  */ | ||||
| class ClassLoader | ||||
| { | ||||
| @@ -54,11 +54,17 @@ class ClassLoader | ||||
|     private $useIncludePath = false; | ||||
|     private $classMap = array(); | ||||
|  | ||||
|     private $classMapAuthoritative = false; | ||||
|  | ||||
|     public function getPrefixes() | ||||
|     { | ||||
|         if (!empty($this->prefixesPsr0)) { | ||||
|             return call_user_func_array('array_merge', $this->prefixesPsr0); | ||||
|         } | ||||
|  | ||||
|         return array(); | ||||
|     } | ||||
|  | ||||
|     public function getPrefixesPsr4() | ||||
|     { | ||||
|         return $this->prefixDirsPsr4; | ||||
| @@ -141,8 +147,10 @@ class ClassLoader | ||||
|      * appending or prepending to the ones previously set for this namespace. | ||||
|      * | ||||
|      * @param string       $prefix  The prefix/namespace, with trailing '\\' | ||||
|      * @param array|string $paths   The PSR-0 base directories | ||||
|      * @param array|string $paths   The PSR-4 base directories | ||||
|      * @param bool         $prepend Whether to prepend the directories | ||||
|      * | ||||
|      * @throws \InvalidArgumentException | ||||
|      */ | ||||
|     public function addPsr4($prefix, $paths, $prepend = false) | ||||
|     { | ||||
| @@ -204,6 +212,8 @@ class ClassLoader | ||||
|      * | ||||
|      * @param string       $prefix The prefix/namespace, with trailing '\\' | ||||
|      * @param array|string $paths  The PSR-4 base directories | ||||
|      * | ||||
|      * @throws \InvalidArgumentException | ||||
|      */ | ||||
|     public function setPsr4($prefix, $paths) | ||||
|     { | ||||
| @@ -240,6 +250,27 @@ class ClassLoader | ||||
|         return $this->useIncludePath; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Turns off searching the prefix and fallback directories for classes | ||||
|      * that have not been registered with the class map. | ||||
|      * | ||||
|      * @param bool $classMapAuthoritative | ||||
|      */ | ||||
|     public function setClassMapAuthoritative($classMapAuthoritative) | ||||
|     { | ||||
|         $this->classMapAuthoritative = $classMapAuthoritative; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Should class lookup fail if not found in the current class map? | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isClassMapAuthoritative() | ||||
|     { | ||||
|         return $this->classMapAuthoritative; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Registers this instance as an autoloader. | ||||
|      * | ||||
| @@ -291,6 +322,9 @@ class ClassLoader | ||||
|         if (isset($this->classMap[$class])) { | ||||
|             return $this->classMap[$class]; | ||||
|         } | ||||
|         if ($this->classMapAuthoritative) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         $file = $this->findFileWithExtension($class, '.php'); | ||||
|  | ||||
|   | ||||
							
								
								
									
										21
									
								
								vendor/composer/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/composer/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
|  | ||||
| Copyright (c) 2016 Nils Adermann, Jordi Boggiano | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is furnished | ||||
| to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
|  | ||||
							
								
								
									
										16
									
								
								vendor/composer/autoload_files.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/composer/autoload_files.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
| // autoload_files.php @generated by Composer | ||||
|  | ||||
| $vendorDir = dirname(dirname(__FILE__)); | ||||
| $baseDir = dirname($vendorDir); | ||||
|  | ||||
| return array( | ||||
|     '383eaff206634a77a1be54e64e6459c7' => $vendorDir . '/sabre/uri/lib/functions.php', | ||||
|     '2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php', | ||||
|     'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php', | ||||
|     'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php', | ||||
|     '3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php', | ||||
|     '93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php', | ||||
|     'ebdb698ed4152ae445614b69b5e4bb6a' => $vendorDir . '/sabre/http/lib/functions.php', | ||||
| ); | ||||
							
								
								
									
										6
									
								
								vendor/composer/autoload_namespaces.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/composer/autoload_namespaces.php
									
									
									
									
										vendored
									
									
								
							| @@ -6,10 +6,4 @@ $vendorDir = dirname(dirname(__FILE__)); | ||||
| $baseDir = dirname($vendorDir); | ||||
|  | ||||
| return array( | ||||
|     'Sabre\\VObject' => array($vendorDir . '/sabre/vobject/lib'), | ||||
|     'Sabre\\HTTP' => array($vendorDir . '/sabre/dav/lib'), | ||||
|     'Sabre\\DAVACL' => array($vendorDir . '/sabre/dav/lib'), | ||||
|     'Sabre\\DAV' => array($vendorDir . '/sabre/dav/lib'), | ||||
|     'Sabre\\CardDAV' => array($vendorDir . '/sabre/dav/lib'), | ||||
|     'Sabre\\CalDAV' => array($vendorDir . '/sabre/dav/lib'), | ||||
| ); | ||||
|   | ||||
							
								
								
									
										9
									
								
								vendor/composer/autoload_psr4.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/composer/autoload_psr4.php
									
									
									
									
										vendored
									
									
								
							| @@ -6,4 +6,13 @@ $vendorDir = dirname(dirname(__FILE__)); | ||||
| $baseDir = dirname($vendorDir); | ||||
|  | ||||
| return array( | ||||
|     'Sabre\\Xml\\' => array($vendorDir . '/sabre/xml/lib'), | ||||
|     'Sabre\\VObject\\' => array($vendorDir . '/sabre/vobject/lib'), | ||||
|     'Sabre\\Uri\\' => array($vendorDir . '/sabre/uri/lib'), | ||||
|     'Sabre\\HTTP\\' => array($vendorDir . '/sabre/http/lib'), | ||||
|     'Sabre\\Event\\' => array($vendorDir . '/sabre/event/lib'), | ||||
|     'Sabre\\DAV\\' => array($vendorDir . '/sabre/dav/lib/DAV'), | ||||
|     'Sabre\\DAVACL\\' => array($vendorDir . '/sabre/dav/lib/DAVACL'), | ||||
|     'Sabre\\CardDAV\\' => array($vendorDir . '/sabre/dav/lib/CardDAV'), | ||||
|     'Sabre\\CalDAV\\' => array($vendorDir . '/sabre/dav/lib/CalDAV'), | ||||
| ); | ||||
|   | ||||
							
								
								
									
										28
									
								
								vendor/composer/autoload_real.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/composer/autoload_real.php
									
									
									
									
										vendored
									
									
								
							| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| // autoload_real.php @generated by Composer | ||||
|  | ||||
| class ComposerAutoloaderInita478c0bdc9041edcc4f485e8fb39b90d | ||||
| class ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785 | ||||
| { | ||||
|     private static $loader; | ||||
|  | ||||
| @@ -19,10 +19,16 @@ class ComposerAutoloaderInita478c0bdc9041edcc4f485e8fb39b90d | ||||
|             return self::$loader; | ||||
|         } | ||||
|  | ||||
|         spl_autoload_register(array('ComposerAutoloaderInita478c0bdc9041edcc4f485e8fb39b90d', 'loadClassLoader'), true, true); | ||||
|         spl_autoload_register(array('ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785', 'loadClassLoader'), true, true); | ||||
|         self::$loader = $loader = new \Composer\Autoload\ClassLoader(); | ||||
|         spl_autoload_unregister(array('ComposerAutoloaderInita478c0bdc9041edcc4f485e8fb39b90d', 'loadClassLoader')); | ||||
|         spl_autoload_unregister(array('ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785', 'loadClassLoader')); | ||||
|  | ||||
|         $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION'); | ||||
|         if ($useStaticLoader) { | ||||
|             require_once __DIR__ . '/autoload_static.php'; | ||||
|  | ||||
|             call_user_func(\Composer\Autoload\ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::getInitializer($loader)); | ||||
|         } else { | ||||
|             $map = require __DIR__ . '/autoload_namespaces.php'; | ||||
|             foreach ($map as $namespace => $path) { | ||||
|                 $loader->set($namespace, $path); | ||||
| @@ -37,14 +43,28 @@ class ComposerAutoloaderInita478c0bdc9041edcc4f485e8fb39b90d | ||||
|             if ($classMap) { | ||||
|                 $loader->addClassMap($classMap); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $loader->register(true); | ||||
|  | ||||
|         if ($useStaticLoader) { | ||||
|             $includeFiles = Composer\Autoload\ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$files; | ||||
|         } else { | ||||
|             $includeFiles = require __DIR__ . '/autoload_files.php'; | ||||
|         } | ||||
|         foreach ($includeFiles as $fileIdentifier => $file) { | ||||
|             composerRequire85a1cefa95be2f464cf7f947cbc4c785($fileIdentifier, $file); | ||||
|         } | ||||
|  | ||||
|         return $loader; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function composerRequirea478c0bdc9041edcc4f485e8fb39b90d($file) | ||||
| function composerRequire85a1cefa95be2f464cf7f947cbc4c785($fileIdentifier, $file) | ||||
| { | ||||
|     if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { | ||||
|         require $file; | ||||
|  | ||||
|         $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										81
									
								
								vendor/composer/autoload_static.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								vendor/composer/autoload_static.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| <?php | ||||
|  | ||||
| // autoload_static.php @generated by Composer | ||||
|  | ||||
| namespace Composer\Autoload; | ||||
|  | ||||
| class ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785 | ||||
| { | ||||
|     public static $files = array ( | ||||
|         '383eaff206634a77a1be54e64e6459c7' => __DIR__ . '/..' . '/sabre/uri/lib/functions.php', | ||||
|         '2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php', | ||||
|         'd81bab31d3feb45bfe2f283ea3c8fdf7' => __DIR__ . '/..' . '/sabre/event/lib/Loop/functions.php', | ||||
|         'a1cce3d26cc15c00fcd0b3354bd72c88' => __DIR__ . '/..' . '/sabre/event/lib/Promise/functions.php', | ||||
|         '3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php', | ||||
|         '93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php', | ||||
|         'ebdb698ed4152ae445614b69b5e4bb6a' => __DIR__ . '/..' . '/sabre/http/lib/functions.php', | ||||
|     ); | ||||
|  | ||||
|     public static $prefixLengthsPsr4 = array ( | ||||
|         'S' =>  | ||||
|         array ( | ||||
|             'Sabre\\Xml\\' => 10, | ||||
|             'Sabre\\VObject\\' => 14, | ||||
|             'Sabre\\Uri\\' => 10, | ||||
|             'Sabre\\HTTP\\' => 11, | ||||
|             'Sabre\\Event\\' => 12, | ||||
|             'Sabre\\DAV\\' => 10, | ||||
|             'Sabre\\DAVACL\\' => 13, | ||||
|             'Sabre\\CardDAV\\' => 14, | ||||
|             'Sabre\\CalDAV\\' => 13, | ||||
|         ), | ||||
|     ); | ||||
|  | ||||
|     public static $prefixDirsPsr4 = array ( | ||||
|         'Sabre\\Xml\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/xml/lib', | ||||
|         ), | ||||
|         'Sabre\\VObject\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/vobject/lib', | ||||
|         ), | ||||
|         'Sabre\\Uri\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/uri/lib', | ||||
|         ), | ||||
|         'Sabre\\HTTP\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/http/lib', | ||||
|         ), | ||||
|         'Sabre\\Event\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/event/lib', | ||||
|         ), | ||||
|         'Sabre\\DAV\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/dav/lib/DAV', | ||||
|         ), | ||||
|         'Sabre\\DAVACL\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/dav/lib/DAVACL', | ||||
|         ), | ||||
|         'Sabre\\CardDAV\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/dav/lib/CardDAV', | ||||
|         ), | ||||
|         'Sabre\\CalDAV\\' =>  | ||||
|         array ( | ||||
|             0 => __DIR__ . '/..' . '/sabre/dav/lib/CalDAV', | ||||
|         ), | ||||
|     ); | ||||
|  | ||||
|     public static function getInitializer(ClassLoader $loader) | ||||
|     { | ||||
|         return \Closure::bind(function () use ($loader) { | ||||
|             $loader->prefixLengthsPsr4 = ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$prefixLengthsPsr4; | ||||
|             $loader->prefixDirsPsr4 = ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$prefixDirsPsr4; | ||||
|  | ||||
|         }, null, ClassLoader::class); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										373
									
								
								vendor/composer/installed.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										373
									
								
								vendor/composer/installed.json
									
									
									
									
										vendored
									
									
								
							| @@ -1,32 +1,35 @@ | ||||
| [ | ||||
|     { | ||||
|         "name": "sabre/vobject", | ||||
|         "version": "2.1.4", | ||||
|         "version_normalized": "2.1.4.0", | ||||
|         "name": "sabre/uri", | ||||
|         "version": "1.1.0", | ||||
|         "version_normalized": "1.1.0.0", | ||||
|         "source": { | ||||
|             "type": "git", | ||||
|             "url": "https://github.com/fruux/sabre-vobject.git", | ||||
|             "reference": "199b6ec87104b05e3013dfd5b90eafbbe4cf97dc" | ||||
|             "url": "https://github.com/fruux/sabre-uri.git", | ||||
|             "reference": "9012116434d84ef6e5e37a89dfdbfbe2204a8704" | ||||
|         }, | ||||
|         "dist": { | ||||
|             "type": "zip", | ||||
|             "url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/199b6ec87104b05e3013dfd5b90eafbbe4cf97dc", | ||||
|             "reference": "199b6ec87104b05e3013dfd5b90eafbbe4cf97dc", | ||||
|             "url": "https://api.github.com/repos/fruux/sabre-uri/zipball/9012116434d84ef6e5e37a89dfdbfbe2204a8704", | ||||
|             "reference": "9012116434d84ef6e5e37a89dfdbfbe2204a8704", | ||||
|             "shasum": "" | ||||
|         }, | ||||
|         "require": { | ||||
|             "ext-mbstring": "*", | ||||
|             "php": ">=5.3.1" | ||||
|             "php": ">=5.4.7" | ||||
|         }, | ||||
|         "time": "2014-03-30 23:01:06", | ||||
|         "bin": [ | ||||
|             "bin/vobjectvalidate.php" | ||||
|         ], | ||||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "*", | ||||
|             "sabre/cs": "~0.0.1" | ||||
|         }, | ||||
|         "time": "2016-03-08 02:29:27", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|             "psr-0": { | ||||
|                 "Sabre\\VObject": "lib/" | ||||
|             "files": [ | ||||
|                 "lib/functions.php" | ||||
|             ], | ||||
|             "psr-4": { | ||||
|                 "Sabre\\Uri\\": "lib/" | ||||
|             } | ||||
|         }, | ||||
|         "notification-url": "https://packagist.org/downloads/", | ||||
| @@ -36,32 +39,310 @@ | ||||
|         "authors": [ | ||||
|             { | ||||
|                 "name": "Evert Pot", | ||||
|                 "email": "evert@rooftopsolutions.nl", | ||||
|                 "email": "me@evertpot.com", | ||||
|                 "homepage": "http://evertpot.com/", | ||||
|                 "role": "Developer" | ||||
|             } | ||||
|         ], | ||||
|         "description": "The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects", | ||||
|         "homepage": "https://github.com/fruux/sabre-vobject", | ||||
|         "description": "Functions for making sense out of URIs.", | ||||
|         "homepage": "http://sabre.io/uri/", | ||||
|         "keywords": [ | ||||
|             "VObject", | ||||
|             "rfc3986", | ||||
|             "uri", | ||||
|             "url" | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "name": "sabre/event", | ||||
|         "version": "3.0.0", | ||||
|         "version_normalized": "3.0.0.0", | ||||
|         "source": { | ||||
|             "type": "git", | ||||
|             "url": "https://github.com/fruux/sabre-event.git", | ||||
|             "reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534" | ||||
|         }, | ||||
|         "dist": { | ||||
|             "type": "zip", | ||||
|             "url": "https://api.github.com/repos/fruux/sabre-event/zipball/831d586f5a442dceacdcf5e9c4c36a4db99a3534", | ||||
|             "reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534", | ||||
|             "shasum": "" | ||||
|         }, | ||||
|         "require": { | ||||
|             "php": ">=5.5" | ||||
|         }, | ||||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "*", | ||||
|             "sabre/cs": "~0.0.4" | ||||
|         }, | ||||
|         "time": "2015-11-05 20:14:39", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|             "psr-4": { | ||||
|                 "Sabre\\Event\\": "lib/" | ||||
|             }, | ||||
|             "files": [ | ||||
|                 "lib/coroutine.php", | ||||
|                 "lib/Loop/functions.php", | ||||
|                 "lib/Promise/functions.php" | ||||
|             ] | ||||
|         }, | ||||
|         "notification-url": "https://packagist.org/downloads/", | ||||
|         "license": [ | ||||
|             "BSD-3-Clause" | ||||
|         ], | ||||
|         "authors": [ | ||||
|             { | ||||
|                 "name": "Evert Pot", | ||||
|                 "email": "me@evertpot.com", | ||||
|                 "homepage": "http://evertpot.com/", | ||||
|                 "role": "Developer" | ||||
|             } | ||||
|         ], | ||||
|         "description": "sabre/event is a library for lightweight event-based programming", | ||||
|         "homepage": "http://sabre.io/event/", | ||||
|         "keywords": [ | ||||
|             "EventEmitter", | ||||
|             "async", | ||||
|             "events", | ||||
|             "hooks", | ||||
|             "plugin", | ||||
|             "promise", | ||||
|             "signal" | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "name": "sabre/http", | ||||
|         "version": "4.2.1", | ||||
|         "version_normalized": "4.2.1.0", | ||||
|         "source": { | ||||
|             "type": "git", | ||||
|             "url": "https://github.com/fruux/sabre-http.git", | ||||
|             "reference": "2e93bc8321524c67be4ca5b8415daebd4c8bf85e" | ||||
|         }, | ||||
|         "dist": { | ||||
|             "type": "zip", | ||||
|             "url": "https://api.github.com/repos/fruux/sabre-http/zipball/2e93bc8321524c67be4ca5b8415daebd4c8bf85e", | ||||
|             "reference": "2e93bc8321524c67be4ca5b8415daebd4c8bf85e", | ||||
|             "shasum": "" | ||||
|         }, | ||||
|         "require": { | ||||
|             "ext-mbstring": "*", | ||||
|             "php": ">=5.4", | ||||
|             "sabre/event": ">=1.0.0,<4.0.0", | ||||
|             "sabre/uri": "~1.0" | ||||
|         }, | ||||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.3", | ||||
|             "sabre/cs": "~0.0.1" | ||||
|         }, | ||||
|         "suggest": { | ||||
|             "ext-curl": " to make http requests with the Client class" | ||||
|         }, | ||||
|         "time": "2016-01-06 23:00:08", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|             "files": [ | ||||
|                 "lib/functions.php" | ||||
|             ], | ||||
|             "psr-4": { | ||||
|                 "Sabre\\HTTP\\": "lib/" | ||||
|             } | ||||
|         }, | ||||
|         "notification-url": "https://packagist.org/downloads/", | ||||
|         "license": [ | ||||
|             "BSD-3-Clause" | ||||
|         ], | ||||
|         "authors": [ | ||||
|             { | ||||
|                 "name": "Evert Pot", | ||||
|                 "email": "me@evertpot.com", | ||||
|                 "homepage": "http://evertpot.com/", | ||||
|                 "role": "Developer" | ||||
|             } | ||||
|         ], | ||||
|         "description": "The sabre/http library provides utilities for dealing with http requests and responses. ", | ||||
|         "homepage": "https://github.com/fruux/sabre-http", | ||||
|         "keywords": [ | ||||
|             "http" | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "name": "sabre/xml", | ||||
|         "version": "1.4.1", | ||||
|         "version_normalized": "1.4.1.0", | ||||
|         "source": { | ||||
|             "type": "git", | ||||
|             "url": "https://github.com/fruux/sabre-xml.git", | ||||
|             "reference": "59998046db252634259a878baf1af18159f508f3" | ||||
|         }, | ||||
|         "dist": { | ||||
|             "type": "zip", | ||||
|             "url": "https://api.github.com/repos/fruux/sabre-xml/zipball/59998046db252634259a878baf1af18159f508f3", | ||||
|             "reference": "59998046db252634259a878baf1af18159f508f3", | ||||
|             "shasum": "" | ||||
|         }, | ||||
|         "require": { | ||||
|             "ext-dom": "*", | ||||
|             "ext-xmlreader": "*", | ||||
|             "ext-xmlwriter": "*", | ||||
|             "lib-libxml": ">=2.6.20", | ||||
|             "php": ">=5.4.1", | ||||
|             "sabre/uri": "~1.0" | ||||
|         }, | ||||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "*", | ||||
|             "sabre/cs": "~0.0.2" | ||||
|         }, | ||||
|         "time": "2016-03-12 22:23:16", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|             "psr-4": { | ||||
|                 "Sabre\\Xml\\": "lib/" | ||||
|             }, | ||||
|             "files": [ | ||||
|                 "lib/Deserializer/functions.php", | ||||
|                 "lib/Serializer/functions.php" | ||||
|             ] | ||||
|         }, | ||||
|         "notification-url": "https://packagist.org/downloads/", | ||||
|         "license": [ | ||||
|             "BSD-3-Clause" | ||||
|         ], | ||||
|         "authors": [ | ||||
|             { | ||||
|                 "name": "Evert Pot", | ||||
|                 "email": "me@evertpot.com", | ||||
|                 "homepage": "http://evertpot.com/", | ||||
|                 "role": "Developer" | ||||
|             }, | ||||
|             { | ||||
|                 "name": "Markus Staab", | ||||
|                 "email": "markus.staab@redaxo.de", | ||||
|                 "role": "Developer" | ||||
|             } | ||||
|         ], | ||||
|         "description": "sabre/xml is an XML library that you may not hate.", | ||||
|         "homepage": "https://sabre.io/xml/", | ||||
|         "keywords": [ | ||||
|             "XMLReader", | ||||
|             "XMLWriter", | ||||
|             "dom", | ||||
|             "xml" | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "name": "sabre/vobject", | ||||
|         "version": "4.1.0", | ||||
|         "version_normalized": "4.1.0.0", | ||||
|         "source": { | ||||
|             "type": "git", | ||||
|             "url": "https://github.com/fruux/sabre-vobject.git", | ||||
|             "reference": "8899c0e856b3178b17f4e9a4e85010209f32a2fa" | ||||
|         }, | ||||
|         "dist": { | ||||
|             "type": "zip", | ||||
|             "url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/8899c0e856b3178b17f4e9a4e85010209f32a2fa", | ||||
|             "reference": "8899c0e856b3178b17f4e9a4e85010209f32a2fa", | ||||
|             "shasum": "" | ||||
|         }, | ||||
|         "require": { | ||||
|             "ext-mbstring": "*", | ||||
|             "php": ">=5.5", | ||||
|             "sabre/xml": "~1.1" | ||||
|         }, | ||||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "*", | ||||
|             "sabre/cs": "~0.0.3" | ||||
|         }, | ||||
|         "suggest": { | ||||
|             "hoa/bench": "If you would like to run the benchmark scripts" | ||||
|         }, | ||||
|         "time": "2016-04-07 00:48:27", | ||||
|         "bin": [ | ||||
|             "bin/vobject", | ||||
|             "bin/generate_vcards" | ||||
|         ], | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|                 "dev-master": "4.0.x-dev" | ||||
|             } | ||||
|         }, | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|             "psr-4": { | ||||
|                 "Sabre\\VObject\\": "lib/" | ||||
|             } | ||||
|         }, | ||||
|         "notification-url": "https://packagist.org/downloads/", | ||||
|         "license": [ | ||||
|             "BSD-3-Clause" | ||||
|         ], | ||||
|         "authors": [ | ||||
|             { | ||||
|                 "name": "Evert Pot", | ||||
|                 "email": "me@evertpot.com", | ||||
|                 "homepage": "http://evertpot.com/", | ||||
|                 "role": "Developer" | ||||
|             }, | ||||
|             { | ||||
|                 "name": "Dominik Tobschall", | ||||
|                 "email": "dominik@fruux.com", | ||||
|                 "homepage": "http://tobschall.de/", | ||||
|                 "role": "Developer" | ||||
|             }, | ||||
|             { | ||||
|                 "name": "Ivan Enderlin", | ||||
|                 "email": "ivan.enderlin@hoa-project.net", | ||||
|                 "homepage": "http://mnt.io/", | ||||
|                 "role": "Developer" | ||||
|             } | ||||
|         ], | ||||
|         "description": "The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects", | ||||
|         "homepage": "http://sabre.io/vobject/", | ||||
|         "keywords": [ | ||||
|             "availability", | ||||
|             "freebusy", | ||||
|             "iCalendar", | ||||
|             "vCard" | ||||
|             "ics", | ||||
|             "jCal", | ||||
|             "jCard", | ||||
|             "recurrence", | ||||
|             "rfc2425", | ||||
|             "rfc2426", | ||||
|             "rfc2739", | ||||
|             "rfc4770", | ||||
|             "rfc5545", | ||||
|             "rfc5546", | ||||
|             "rfc6321", | ||||
|             "rfc6350", | ||||
|             "rfc6351", | ||||
|             "rfc6474", | ||||
|             "rfc6638", | ||||
|             "rfc6715", | ||||
|             "rfc6868", | ||||
|             "vCard", | ||||
|             "vcf", | ||||
|             "xCal", | ||||
|             "xCard" | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "name": "sabre/dav", | ||||
|         "version": "1.8.10", | ||||
|         "version_normalized": "1.8.10.0", | ||||
|         "version": "3.1.3", | ||||
|         "version_normalized": "3.1.3.0", | ||||
|         "source": { | ||||
|             "type": "git", | ||||
|             "url": "https://github.com/fruux/sabre-dav.git", | ||||
|             "reference": "0d064536ed3c7974e486b6ebb5b17ad7a974fe18" | ||||
|             "reference": "8a266c7b5e140da79529414b9cde2a2d058b536b" | ||||
|         }, | ||||
|         "dist": { | ||||
|             "type": "zip", | ||||
|             "url": "https://api.github.com/repos/fruux/sabre-dav/zipball/0d064536ed3c7974e486b6ebb5b17ad7a974fe18", | ||||
|             "reference": "0d064536ed3c7974e486b6ebb5b17ad7a974fe18", | ||||
|             "url": "https://api.github.com/repos/fruux/sabre-dav/zipball/8a266c7b5e140da79529414b9cde2a2d058b536b", | ||||
|             "reference": "8a266c7b5e140da79529414b9cde2a2d058b536b", | ||||
|             "shasum": "" | ||||
|         }, | ||||
|         "require": { | ||||
| @@ -69,39 +350,45 @@ | ||||
|             "ext-date": "*", | ||||
|             "ext-dom": "*", | ||||
|             "ext-iconv": "*", | ||||
|             "ext-libxml": "*", | ||||
|             "ext-mbstring": "*", | ||||
|             "ext-pcre": "*", | ||||
|             "ext-simplexml": "*", | ||||
|             "ext-spl": "*", | ||||
|             "php": ">=5.3.1", | ||||
|             "sabre/vobject": "~2.1.0" | ||||
|         }, | ||||
|         "provide": { | ||||
|             "evert/sabredav": "1.7.*" | ||||
|             "lib-libxml": ">=2.7.0", | ||||
|             "php": ">=5.5.0", | ||||
|             "sabre/event": ">=2.0.0, <4.0.0", | ||||
|             "sabre/http": "^4.2.1", | ||||
|             "sabre/uri": "~1.0", | ||||
|             "sabre/vobject": "~4.0", | ||||
|             "sabre/xml": "~1.0" | ||||
|         }, | ||||
|         "require-dev": { | ||||
|             "evert/phpdoc-md": "~0.0.7", | ||||
|             "phpunit/phpunit": "~4.0.0" | ||||
|             "evert/phpdoc-md": "~0.1.0", | ||||
|             "phpunit/phpunit": "> 4.8, <=6.0.0", | ||||
|             "sabre/cs": "~0.0.5" | ||||
|         }, | ||||
|         "suggest": { | ||||
|             "ext-apc": "*", | ||||
|             "ext-curl": "*", | ||||
|             "ext-pdo": "*" | ||||
|         }, | ||||
|         "time": "2014-05-16 00:14:02", | ||||
|         "time": "2016-04-07 01:02:57", | ||||
|         "bin": [ | ||||
|             "bin/sabredav" | ||||
|             "bin/sabredav", | ||||
|             "bin/naturalselection" | ||||
|         ], | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|                 "dev-master": "3.1.0-dev" | ||||
|             } | ||||
|         }, | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|             "psr-0": { | ||||
|                 "Sabre\\DAV": "lib/", | ||||
|                 "Sabre\\HTTP": "lib/", | ||||
|                 "Sabre\\DAVACL": "lib/", | ||||
|                 "Sabre\\CalDAV": "lib/", | ||||
|                 "Sabre\\CardDAV": "lib/" | ||||
|             "psr-4": { | ||||
|                 "Sabre\\DAV\\": "lib/DAV/", | ||||
|                 "Sabre\\DAVACL\\": "lib/DAVACL/", | ||||
|                 "Sabre\\CalDAV\\": "lib/CalDAV/", | ||||
|                 "Sabre\\CardDAV\\": "lib/CardDAV/" | ||||
|             } | ||||
|         }, | ||||
|         "notification-url": "https://packagist.org/downloads/", | ||||
| @@ -117,7 +404,7 @@ | ||||
|             } | ||||
|         ], | ||||
|         "description": "WebDAV Framework for PHP", | ||||
|         "homepage": "http://code.google.com/p/sabredav/", | ||||
|         "homepage": "http://sabre.io/", | ||||
|         "keywords": [ | ||||
|             "CalDAV", | ||||
|             "CardDAV", | ||||
|   | ||||
							
								
								
									
										47
									
								
								vendor/sabre/dav/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								vendor/sabre/dav/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,22 +1,43 @@ | ||||
| docs/api | ||||
| docs/wikidocs | ||||
| build.properties | ||||
| build | ||||
| public | ||||
| data | ||||
| fileserver.php | ||||
| fileserver2.php | ||||
| calendarserver.php | ||||
| groupwareserver.php | ||||
| package.xml | ||||
| tmpdata | ||||
| # Unit tests | ||||
| tests/temp | ||||
| tests/.sabredav | ||||
| tests/cov | ||||
|  | ||||
| # Custom settings for tests | ||||
| tests/config.user.php | ||||
|  | ||||
| # ViM | ||||
| *.swp | ||||
|  | ||||
| # Composer | ||||
| composer.lock | ||||
| vendor | ||||
|  | ||||
| # Composer binaries | ||||
| bin/phing | ||||
| bin/phpunit | ||||
| bin/vobjectvalidate.php | ||||
| bin/vobject | ||||
| bin/generate_vcards | ||||
| bin/phpdocmd | ||||
| bin/phpunit | ||||
| bin/php-cs-fixer | ||||
| bin/sabre-cs-fixer | ||||
|  | ||||
| # Assuming every .php file in the root is for testing | ||||
| /*.php | ||||
|  | ||||
| # Other testing stuff | ||||
| /tmpdata | ||||
| /data | ||||
| /public | ||||
|  | ||||
| # Build | ||||
| build | ||||
| build.properties | ||||
|  | ||||
| # Docs | ||||
| docs/api | ||||
| docs/wikidocs | ||||
|  | ||||
| # Mac | ||||
| .DS_Store | ||||
|   | ||||
							
								
								
									
										27
									
								
								vendor/sabre/dav/.travis.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/sabre/dav/.travis.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,28 +1,33 @@ | ||||
| language: php | ||||
| php: | ||||
|   - 5.3.3 | ||||
|   - 5.3 | ||||
|   - 5.4 | ||||
|   - 5.5 | ||||
|   - 5.6 | ||||
|   - 7 | ||||
|   - hhvm | ||||
|  | ||||
| matrix: | ||||
|   fast_finish: true | ||||
|   allow_failures: | ||||
|     - php: 5.6 | ||||
|       - php: hhvm | ||||
|  | ||||
| env: | ||||
|   matrix: | ||||
|     - LOWEST_DEPS="" TEST_DEPS="" | ||||
|     - LOWEST_DEPS="--prefer-lowest" TEST_DEPS="tests/Sabre/" | ||||
|  | ||||
| services: | ||||
|   - mysql | ||||
|  | ||||
| sudo: false | ||||
|  | ||||
| cache: vendor | ||||
|  | ||||
| before_script: | ||||
|   - mysql -e 'create database sabredav' | ||||
|   - composer self-update | ||||
|   - composer install --prefer-source | ||||
| #  - echo "zend.enable_gc=0" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` | ||||
|   #  - composer self-update | ||||
|   - composer update --prefer-source $LOWEST_DEPS | ||||
|  | ||||
| script: | ||||
|   - phpunit --configuration tests/phpunit.xml | ||||
|   - cp tests/composer.vobject3.json composer.json | ||||
|   - composer update --no-dev | ||||
|   - phpunit --configuration tests/phpunit.xml | ||||
|   - ./bin/phpunit --configuration tests/phpunit.xml $TEST_DEPS | ||||
|   - ./bin/sabre-cs-fixer fix lib/ --dry-run --diff | ||||
|  | ||||
|   | ||||
							
								
								
									
										2242
									
								
								vendor/sabre/dav/CHANGELOG.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2242
									
								
								vendor/sabre/dav/CHANGELOG.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										87
									
								
								vendor/sabre/dav/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								vendor/sabre/dav/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| Contributing to sabre projects | ||||
| ============================== | ||||
|  | ||||
| Want to contribute to sabre/dav? Here are some guidelines to ensure your patch | ||||
| gets accepted. | ||||
|  | ||||
|  | ||||
| Building a new feature? Contact us first | ||||
| ---------------------------------------- | ||||
|  | ||||
| We may not want to accept every feature that comes our way. Sometimes | ||||
| features are out of scope for our projects. | ||||
|  | ||||
| We don't want to waste your time, so by having a quick chat with us first, | ||||
| you may find out quickly if the feature makes sense to us, and we can give | ||||
| some tips on how to best build the feature. | ||||
|  | ||||
| If we don't accept the feature, it could be for a number of reasons. For | ||||
| instance, we've rejected features in the past because we felt uncomfortable | ||||
| assuming responsibility for maintaining the feature. | ||||
|  | ||||
| In those cases, it's often possible to keep the feature separate from the | ||||
| sabre projects. sabre/dav for instance has a plugin system, and there's no | ||||
| reason the feature can't live in a project you own. | ||||
|  | ||||
| In that case, definitely let us know about your plugin as well, so we can | ||||
| feature it on [sabre.io][4]. | ||||
|  | ||||
| We are often on [IRC][5], in the #sabredav channel on freenode. If there's | ||||
| no one there, post a message on the [mailing list][6]. | ||||
|  | ||||
|  | ||||
| Coding standards | ||||
| ---------------- | ||||
|  | ||||
| sabre projects follow: | ||||
|  | ||||
| 1. [PSR-1][1] | ||||
| 2. [PSR-4][2] | ||||
|  | ||||
| sabre projects don't follow [PSR-2][3]. | ||||
|  | ||||
| In addition to that, here's a list of basic rules: | ||||
|  | ||||
| 1. PHP 5.4 array syntax must be used every where. This means you use `[` and | ||||
|    `]` instead of `array(` and `)`. | ||||
| 2. Use PHP namespaces everywhere. | ||||
| 3. Use 4 spaces for indentation. | ||||
| 4. Try to keep your lines under 80 characters. This is not a hard rule, as | ||||
|    there are many places in the source where it felt more sensibile to not | ||||
|    do so. In particular, function declarations are never split over multiple | ||||
|    lines. | ||||
| 5. Opening braces (`{`) are _always_ on the same line as the `class`, `if`, | ||||
|    `function`, etc. they belong to. | ||||
| 6. `public` must be omitted from method declarations. It must also be omitted | ||||
|    for static properties. | ||||
| 7. All files should use unix-line endings (`\n`). | ||||
| 8. Files must omit the closing php tag (`?>`). | ||||
| 9. `true`, `false` and `null` are always lower-case. | ||||
| 10. Constants are always upper-case. | ||||
| 11. Any of the rules stated before may be broken where this is the pragmatic | ||||
|     thing to do. | ||||
|  | ||||
|  | ||||
| Unit test requirements | ||||
| ---------------------- | ||||
|  | ||||
| Any new feature or change requires unittests. We use [PHPUnit][7] for all our | ||||
| tests. | ||||
|  | ||||
| Adding unittests will greatly increase the likelyhood of us quickly accepting | ||||
| your pull request. If unittests are not included though for whatever reason, | ||||
| we'd still _love_ your pull request. | ||||
|  | ||||
| We may have to write the tests ourselves, which can increase the time it takes | ||||
| to accept the patch, but we'd still really like your contribution! | ||||
|  | ||||
| To run the testsuite jump into the directory `cd tests` and trigger `phpunit`. | ||||
| Make sure you did a `composer install` beforehand. | ||||
|  | ||||
| [1]: http://www.php-fig.org/psr/psr-1/ | ||||
| [2]: http://www.php-fig.org/psr/psr-4/ | ||||
| [3]: http://www.php-fig.org/psr/psr-2/ | ||||
| [4]: http://sabre.io/ | ||||
| [5]: irc://freenode.net/#sabredav | ||||
| [6]: http://groups.google.com/group/sabredav-discuss | ||||
| [7]: http://phpunit.de/ | ||||
							
								
								
									
										1164
									
								
								vendor/sabre/dav/ChangeLog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1164
									
								
								vendor/sabre/dav/ChangeLog
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2
									
								
								vendor/sabre/dav/LICENSE
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/sabre/dav/LICENSE
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
| Copyright (C) 2007-2016 fruux GmbH (https://fruux.com/). | ||||
|  | ||||
| All rights reserved. | ||||
|  | ||||
|   | ||||
							
								
								
									
										49
									
								
								vendor/sabre/dav/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										49
									
								
								vendor/sabre/dav/README.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,30 +1,29 @@ | ||||
| # What is SabreDAV | ||||
|  SabreDAV | ||||
| ====================================================== | ||||
|  | ||||
| SabreDAV allows you to easily add WebDAV support to a PHP application. SabreDAV is meant to cover the entire standard, and attempts to allow integration using an easy to understand API. | ||||
| Introduction | ||||
| ------------ | ||||
|  | ||||
| ### Feature list: | ||||
| SabreDAV is the most popular WebDAV framework for PHP. Use it to create WebDAV, CalDAV and CardDAV servers. | ||||
|  | ||||
| * Fully WebDAV compliant | ||||
| * Supports Windows XP, Windows Vista, Mac OS/X, DavFSv2, Cadaver, Netdrive, Open Office, and probably more. | ||||
| * Passing all Litmus tests. | ||||
| * Supporting class 1, 2 and 3 Webdav servers. | ||||
| * Locking support. | ||||
| * Custom property support. | ||||
| * CalDAV (tested with [Evolution](http://code.google.com/p/sabredav/wiki/Evolution), [iCal](http://code.google.com/p/sabredav/wiki/ICal), [iPhone](http://code.google.com/p/sabredav/wiki/IPhone) and [Lightning](http://code.google.com/p/sabredav/wiki/Lightning)). | ||||
| * CardDAV (tested with [OS/X addressbook](http://code.google.com/p/sabredav/wiki/OSXAddressbook), the [iOS addressbook](http://code.google.com/p/sabredav/wiki/iOSCardDAV) and [Evolution](http://code.google.com/p/sabredav/wiki/Evolution)). | ||||
| * Over 97% unittest code coverage. | ||||
| Full documentation can be found on the website: | ||||
|  | ||||
| ### Supported RFC's: | ||||
| http://sabre.io/ | ||||
|  | ||||
| * [RFC2617](http://www.ietf.org/rfc/rfc2617.txt): Basic/Digest auth. | ||||
| * [RFC2518](http://www.ietf.org/rfc/rfc2518.txt): First WebDAV spec. | ||||
| * [RFC3744](http://www.ietf.org/rfc/rfc3744.txt): ACL (some features missing). | ||||
| * [RFC4709](http://www.ietf.org/rfc/rfc4709.txt): [DavMount](http://code.google.com/p/sabredav/wiki/DavMount). | ||||
| * [RFC4791](http://www.ietf.org/rfc/rfc4791.txt): CalDAV. | ||||
| * [RFC4918](http://www.ietf.org/rfc/rfc4918.txt): WebDAV revision. | ||||
| * [RFC5397](http://www.ietf.org/rfc/rfc5689.txt): current-user-principal. | ||||
| * [RFC5689](http://www.ietf.org/rfc/rfc5689.txt): Extended MKCOL. | ||||
| * [RFC5789](http://tools.ietf.org/html/rfc5789): PATCH method for HTTP. | ||||
| * [RFC6352](http://www.ietf.org/rfc/rfc6352.txt): CardDAV | ||||
| * [draft-daboo-carddav-directory-gateway](http://tools.ietf.org/html/draft-daboo-carddav-directory-gateway): CardDAV directory gateway | ||||
| * CalDAV ctag, CalDAV-proxy. | ||||
| Build status | ||||
| ------------ | ||||
|  | ||||
| | branch       | status | minimum PHP version | | ||||
| | ------------ | ------ | ------------------- | | ||||
| | master       | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 | | ||||
| | 3.0          | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | | ||||
| | 2.1          | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | | ||||
| | 2.0          | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | | ||||
| | 1.8          | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | | ||||
| | 1.7          | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | | ||||
| | 1.6          | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | | ||||
|  | ||||
| Made at fruux | ||||
| ------------- | ||||
|  | ||||
| SabreDAV is being developed by [fruux](https://fruux.com/). Drop us a line for commercial services or enterprise support. | ||||
|   | ||||
							
								
								
									
										46
									
								
								vendor/sabre/dav/bin/build.php
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										46
									
								
								vendor/sabre/dav/bin/build.php
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -1,3 +1,4 @@ | ||||
| #!/usr/bin/env php | ||||
| <?php | ||||
|  | ||||
| $tasks = [ | ||||
| @@ -100,7 +101,7 @@ function composerupdate() { | ||||
|  | ||||
|     global $baseDir; | ||||
|     echo "  Updating composer packages to latest version\n\n"; | ||||
|     system('cd ' . $baseDir . '; composer update --dev'); | ||||
|     system('cd ' . $baseDir . '; composer update'); | ||||
| } | ||||
|  | ||||
| function test() { | ||||
| @@ -120,12 +121,51 @@ function test() { | ||||
| function buildzip() { | ||||
|  | ||||
|     global $baseDir, $version; | ||||
|     echo "  Asking composer to download sabre/dav $version\n\n"; | ||||
|     system("composer create-project --no-dev sabre/dav build/SabreDAV $version", $code); | ||||
|     echo "  Generating composer.json\n"; | ||||
|  | ||||
|     $input = json_decode(file_get_contents(__DIR__ . '/../composer.json'), true); | ||||
|     $newComposer = [ | ||||
|         "require" => $input['require'], | ||||
|         "config"  => [ | ||||
|             "bin-dir" => "./bin", | ||||
|         ], | ||||
|         "prefer-stable"     => true, | ||||
|         "minimum-stability" => "alpha", | ||||
|     ]; | ||||
|     unset( | ||||
|         $newComposer['require']['sabre/vobject'], | ||||
|         $newComposer['require']['sabre/http'], | ||||
|         $newComposer['require']['sabre/uri'], | ||||
|         $newComposer['require']['sabre/event'] | ||||
|     ); | ||||
|     $newComposer['require']['sabre/dav'] = $version; | ||||
|     mkdir('build/SabreDAV'); | ||||
|     file_put_contents('build/SabreDAV/composer.json', json_encode($newComposer, JSON_PRETTY_PRINT)); | ||||
|  | ||||
|     echo "  Downloading dependencies\n"; | ||||
|     system("cd build/SabreDAV; composer install -n", $code); | ||||
|     if ($code !== 0) { | ||||
|         echo "Composer reported error code $code\n"; | ||||
|         die(1); | ||||
|     } | ||||
|  | ||||
|     echo "  Removing pointless files\n"; | ||||
|     unlink('build/SabreDAV/composer.json'); | ||||
|     unlink('build/SabreDAV/composer.lock'); | ||||
|  | ||||
|     echo "  Moving important files to the root of the project\n"; | ||||
|  | ||||
|     $fileNames = [ | ||||
|         'CHANGELOG.md', | ||||
|         'LICENSE', | ||||
|         'README.md', | ||||
|         'examples', | ||||
|     ]; | ||||
|     foreach ($fileNames as $fileName) { | ||||
|         echo "    $fileName\n"; | ||||
|         rename('build/SabreDAV/vendor/sabre/dav/' . $fileName, 'build/SabreDAV/' . $fileName); | ||||
|     } | ||||
|  | ||||
|     // <zip destfile="build/SabreDAV-${sabredav.version}.zip" basedir="build/SabreDAV" prefix="SabreDAV/" /> | ||||
|  | ||||
|     echo "\n"; | ||||
|   | ||||
							
								
								
									
										22
									
								
								vendor/sabre/dav/bin/migrateto17.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/sabre/dav/bin/migrateto17.php
									
									
									
									
										vendored
									
									
								
							| @@ -35,10 +35,10 @@ HELLO; | ||||
|  | ||||
| // There's a bunch of places where the autoloader could be, so we'll try all of | ||||
| // them. | ||||
| $paths = array( | ||||
| $paths = [ | ||||
|     __DIR__ . '/../vendor/autoload.php', | ||||
|     __DIR__ . '/../../../autoload.php', | ||||
| ); | ||||
| ]; | ||||
|  | ||||
| foreach ($paths as $path) { | ||||
|     if (file_exists($path)) { | ||||
| @@ -67,13 +67,13 @@ if (!$row) { | ||||
|     exit(-1); | ||||
| } | ||||
|  | ||||
| $requiredFields = array( | ||||
| $requiredFields = [ | ||||
|     'id', | ||||
|     'calendardata', | ||||
|     'uri', | ||||
|     'calendarid', | ||||
|     'lastmodified', | ||||
| ); | ||||
| ]; | ||||
|  | ||||
| foreach ($requiredFields as $requiredField) { | ||||
|     if (!array_key_exists($requiredField, $row)) { | ||||
| @@ -83,13 +83,13 @@ foreach($requiredFields as $requiredField) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| $fields17 = array( | ||||
| $fields17 = [ | ||||
|     'etag', | ||||
|     'size', | ||||
|     'componenttype', | ||||
|     'firstoccurence', | ||||
|     'lastoccurence', | ||||
| ); | ||||
| ]; | ||||
|  | ||||
| $found = 0; | ||||
| foreach ($fields17 as $field) { | ||||
| @@ -161,14 +161,14 @@ while($row = $result->fetch()) { | ||||
|         echo "This record is ignored, you should inspect it to see if there's anything wrong.\n===\n"; | ||||
|         continue; | ||||
|     } | ||||
|     $stmt->execute(array( | ||||
|     $stmt->execute([ | ||||
|         $newData['etag'], | ||||
|         $newData['size'], | ||||
|         $newData['componentType'], | ||||
|         $newData['firstOccurence'], | ||||
|         $newData['lastOccurence'], | ||||
|         $row['id'], | ||||
|     )); | ||||
|     ]); | ||||
|     $done++; | ||||
|  | ||||
|     if ($done % 500 === 0) { | ||||
| @@ -256,7 +256,7 @@ function getDenormalizedData($calendarData) { | ||||
|                 $lastOccurence = $firstOccurence; | ||||
|             } | ||||
|         } else { | ||||
|             $it = new \Sabre\VObject\RecurrenceIterator($vObject, (string)$component->UID); | ||||
|             $it = new \Sabre\VObject\Recur\EventIterator($vObject, (string)$component->UID); | ||||
|             $maxDate = new DateTime(\Sabre\CalDAV\Backend\PDO::MAX_DATE); | ||||
|             if ($it->isInfinite()) { | ||||
|                 $lastOccurence = $maxDate->getTimeStamp(); | ||||
| @@ -273,12 +273,12 @@ function getDenormalizedData($calendarData) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return array( | ||||
|     return [ | ||||
|         'etag'           => md5($calendarData), | ||||
|         'size'           => strlen($calendarData), | ||||
|         'componentType'  => $componentType, | ||||
|         'firstOccurence' => $firstOccurence, | ||||
|         'lastOccurence'  => $lastOccurence, | ||||
|     ); | ||||
|     ]; | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										453
									
								
								vendor/sabre/dav/bin/migrateto20.php
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										453
									
								
								vendor/sabre/dav/bin/migrateto20.php
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,453 @@ | ||||
| #!/usr/bin/env php | ||||
| <?php | ||||
|  | ||||
| echo "SabreDAV migrate script for version 2.0\n"; | ||||
|  | ||||
| if ($argc < 2) { | ||||
|  | ||||
|     echo <<<HELLO | ||||
|  | ||||
| This script help you migrate from a pre-2.0 database to 2.0 and later | ||||
|  | ||||
| The 'calendars', 'addressbooks' and 'cards' tables will be upgraded, and new | ||||
| tables (calendarchanges, addressbookchanges, propertystorage) will be added. | ||||
|  | ||||
| If you don't use the default PDO CalDAV or CardDAV backend, it's pointless to | ||||
| run this script. | ||||
|  | ||||
| Keep in mind that ALTER TABLE commands will be executed. If you have a large | ||||
| dataset this may mean that this process takes a while. | ||||
|  | ||||
| Lastly: Make a back-up first. This script has been tested, but the amount of | ||||
| potential variants are extremely high, so it's impossible to deal with every | ||||
| possible situation. | ||||
|  | ||||
| In the worst case, you will lose all your data. This is not an overstatement. | ||||
|  | ||||
| Usage: | ||||
|  | ||||
| php {$argv[0]} [pdo-dsn] [username] [password] | ||||
|  | ||||
| For example: | ||||
|  | ||||
| php {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password | ||||
| php {$argv[0]} sqlite:data/sabredav.db | ||||
|  | ||||
| HELLO; | ||||
|  | ||||
|     exit(); | ||||
|  | ||||
| } | ||||
|  | ||||
| // There's a bunch of places where the autoloader could be, so we'll try all of | ||||
| // them. | ||||
| $paths = [ | ||||
|     __DIR__ . '/../vendor/autoload.php', | ||||
|     __DIR__ . '/../../../autoload.php', | ||||
| ]; | ||||
|  | ||||
| foreach ($paths as $path) { | ||||
|     if (file_exists($path)) { | ||||
|         include $path; | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| $dsn = $argv[1]; | ||||
| $user = isset($argv[2]) ? $argv[2] : null; | ||||
| $pass = isset($argv[3]) ? $argv[3] : null; | ||||
|  | ||||
| echo "Connecting to database: " . $dsn . "\n"; | ||||
|  | ||||
| $pdo = new PDO($dsn, $user, $pass); | ||||
| $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||||
| $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); | ||||
|  | ||||
| $driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME); | ||||
|  | ||||
| switch ($driver) { | ||||
|  | ||||
|     case 'mysql' : | ||||
|         echo "Detected MySQL.\n"; | ||||
|         break; | ||||
|     case 'sqlite' : | ||||
|         echo "Detected SQLite.\n"; | ||||
|         break; | ||||
|     default : | ||||
|         echo "Error: unsupported driver: " . $driver . "\n"; | ||||
|         die(-1); | ||||
| } | ||||
|  | ||||
| foreach (['calendar', 'addressbook'] as $itemType) { | ||||
|  | ||||
|     $tableName = $itemType . 's'; | ||||
|     $tableNameOld = $tableName . '_old'; | ||||
|     $changesTable = $itemType . 'changes'; | ||||
|  | ||||
|     echo "Upgrading '$tableName'\n"; | ||||
|  | ||||
|     // The only cross-db way to do this, is to just fetch a single record. | ||||
|     $row = $pdo->query("SELECT * FROM $tableName LIMIT 1")->fetch(); | ||||
|  | ||||
|     if (!$row) { | ||||
|  | ||||
|         echo "No records were found in the '$tableName' table.\n"; | ||||
|         echo "\n"; | ||||
|         echo "We're going to rename the old table to $tableNameOld (just in case).\n"; | ||||
|         echo "and re-create the new table.\n"; | ||||
|  | ||||
|         switch ($driver) { | ||||
|  | ||||
|             case 'mysql' : | ||||
|                 $pdo->exec("RENAME TABLE $tableName TO $tableNameOld"); | ||||
|                 switch ($itemType) { | ||||
|                     case 'calendar' : | ||||
|                         $pdo->exec(" | ||||
|             CREATE TABLE calendars ( | ||||
|                 id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|                 principaluri VARCHAR(100), | ||||
|                 displayname VARCHAR(100), | ||||
|                 uri VARCHAR(200), | ||||
|                 synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1', | ||||
|                 description TEXT, | ||||
|                 calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', | ||||
|                 calendarcolor VARCHAR(10), | ||||
|                 timezone TEXT, | ||||
|                 components VARCHAR(20), | ||||
|                 transparent TINYINT(1) NOT NULL DEFAULT '0', | ||||
|                 UNIQUE(principaluri, uri) | ||||
|             ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|                         "); | ||||
|                         break; | ||||
|                     case 'addressbook' : | ||||
|                         $pdo->exec(" | ||||
|             CREATE TABLE addressbooks ( | ||||
|                 id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|                 principaluri VARCHAR(255), | ||||
|                 displayname VARCHAR(255), | ||||
|                 uri VARCHAR(200), | ||||
|                 description TEXT, | ||||
|                 synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1', | ||||
|                 UNIQUE(principaluri, uri) | ||||
|             ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|                         "); | ||||
|                         break; | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|             case 'sqlite' : | ||||
|  | ||||
|                 $pdo->exec("ALTER TABLE $tableName RENAME TO $tableNameOld"); | ||||
|  | ||||
|                 switch ($itemType) { | ||||
|                     case 'calendar' : | ||||
|                         $pdo->exec(" | ||||
|             CREATE TABLE calendars ( | ||||
|                 id integer primary key asc, | ||||
|                 principaluri text, | ||||
|                 displayname text, | ||||
|                 uri text, | ||||
|                 synctoken integer, | ||||
|                 description text, | ||||
|                 calendarorder integer, | ||||
|                 calendarcolor text, | ||||
|                 timezone text, | ||||
|                 components text, | ||||
|                 transparent bool | ||||
|             ); | ||||
|                         "); | ||||
|                         break; | ||||
|                     case 'addressbook' : | ||||
|                         $pdo->exec(" | ||||
|             CREATE TABLE addressbooks ( | ||||
|                 id integer primary key asc, | ||||
|                 principaluri text, | ||||
|                 displayname text, | ||||
|                 uri text, | ||||
|                 description text, | ||||
|                 synctoken integer | ||||
|             ); | ||||
|                         "); | ||||
|  | ||||
|                         break; | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|         } | ||||
|         echo "Creation of 2.0 $tableName table is complete\n"; | ||||
|  | ||||
|     } else { | ||||
|  | ||||
|         // Checking if there's a synctoken field already. | ||||
|         if (array_key_exists('synctoken', $row)) { | ||||
|             echo "The 'synctoken' field already exists in the $tableName table.\n"; | ||||
|             echo "It's likely you already upgraded, so we're simply leaving\n"; | ||||
|             echo "the $tableName table alone\n"; | ||||
|         } else { | ||||
|  | ||||
|             echo "1.8 table schema detected\n"; | ||||
|             switch ($driver) { | ||||
|  | ||||
|                 case 'mysql' : | ||||
|                     $pdo->exec("ALTER TABLE $tableName ADD synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1'"); | ||||
|                     $pdo->exec("ALTER TABLE $tableName DROP ctag"); | ||||
|                     $pdo->exec("UPDATE $tableName SET synctoken = '1'"); | ||||
|                     break; | ||||
|                 case 'sqlite' : | ||||
|                     $pdo->exec("ALTER TABLE $tableName ADD synctoken integer"); | ||||
|                     $pdo->exec("UPDATE $tableName SET synctoken = '1'"); | ||||
|                     echo "Note: there's no easy way to remove fields in sqlite.\n"; | ||||
|                     echo "The ctag field is no longer used, but it's kept in place\n"; | ||||
|                     break; | ||||
|  | ||||
|             } | ||||
|  | ||||
|             echo "Upgraded '$tableName' to 2.0 schema.\n"; | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|         $pdo->query("SELECT * FROM $changesTable LIMIT 1"); | ||||
|  | ||||
|         echo "'$changesTable' already exists. Assuming that this part of the\n"; | ||||
|         echo "upgrade was already completed.\n"; | ||||
|  | ||||
|     } catch (Exception $e) { | ||||
|         echo "Creating '$changesTable' table.\n"; | ||||
|  | ||||
|         switch ($driver) { | ||||
|  | ||||
|             case 'mysql' : | ||||
|                 $pdo->exec(" | ||||
|     CREATE TABLE $changesTable ( | ||||
|         id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|         uri VARCHAR(200) NOT NULL, | ||||
|         synctoken INT(11) UNSIGNED NOT NULL, | ||||
|         {$itemType}id INT(11) UNSIGNED NOT NULL, | ||||
|         operation TINYINT(1) NOT NULL, | ||||
|         INDEX {$itemType}id_synctoken ({$itemType}id, synctoken) | ||||
|     ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|                 "); | ||||
|                 break; | ||||
|             case 'sqlite' : | ||||
|                 $pdo->exec(" | ||||
|  | ||||
|     CREATE TABLE $changesTable ( | ||||
|         id integer primary key asc, | ||||
|         uri text, | ||||
|         synctoken integer, | ||||
|         {$itemType}id integer, | ||||
|         operation bool | ||||
|     ); | ||||
|  | ||||
|                 "); | ||||
|                 $pdo->exec("CREATE INDEX {$itemType}id_synctoken ON $changesTable ({$itemType}id, synctoken);"); | ||||
|                 break; | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| try { | ||||
|     $pdo->query("SELECT * FROM calendarsubscriptions LIMIT 1"); | ||||
|  | ||||
|     echo "'calendarsubscriptions' already exists. Assuming that this part of the\n"; | ||||
|     echo "upgrade was already completed.\n"; | ||||
|  | ||||
| } catch (Exception $e) { | ||||
|     echo "Creating calendarsubscriptions table.\n"; | ||||
|  | ||||
|     switch ($driver) { | ||||
|  | ||||
|         case 'mysql' : | ||||
|             $pdo->exec(" | ||||
| CREATE TABLE calendarsubscriptions ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     uri VARCHAR(200) NOT NULL, | ||||
|     principaluri VARCHAR(100) NOT NULL, | ||||
|     source TEXT, | ||||
|     displayname VARCHAR(100), | ||||
|     refreshrate VARCHAR(10), | ||||
|     calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', | ||||
|     calendarcolor VARCHAR(10), | ||||
|     striptodos TINYINT(1) NULL, | ||||
|     stripalarms TINYINT(1) NULL, | ||||
|     stripattachments TINYINT(1) NULL, | ||||
|     lastmodified INT(11) UNSIGNED, | ||||
|     UNIQUE(principaluri, uri) | ||||
| ); | ||||
|             "); | ||||
|             break; | ||||
|         case 'sqlite' : | ||||
|             $pdo->exec(" | ||||
|  | ||||
| CREATE TABLE calendarsubscriptions ( | ||||
|     id integer primary key asc, | ||||
|     uri text, | ||||
|     principaluri text, | ||||
|     source text, | ||||
|     displayname text, | ||||
|     refreshrate text, | ||||
|     calendarorder integer, | ||||
|     calendarcolor text, | ||||
|     striptodos bool, | ||||
|     stripalarms bool, | ||||
|     stripattachments bool, | ||||
|     lastmodified int | ||||
| ); | ||||
|             "); | ||||
|  | ||||
|             $pdo->exec("CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri);"); | ||||
|             break; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| try { | ||||
|     $pdo->query("SELECT * FROM propertystorage LIMIT 1"); | ||||
|  | ||||
|     echo "'propertystorage' already exists. Assuming that this part of the\n"; | ||||
|     echo "upgrade was already completed.\n"; | ||||
|  | ||||
| } catch (Exception $e) { | ||||
|     echo "Creating propertystorage table.\n"; | ||||
|  | ||||
|     switch ($driver) { | ||||
|  | ||||
|         case 'mysql' : | ||||
|             $pdo->exec(" | ||||
| CREATE TABLE propertystorage ( | ||||
|     id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     path VARBINARY(1024) NOT NULL, | ||||
|     name VARBINARY(100) NOT NULL, | ||||
|     value MEDIUMBLOB | ||||
| ); | ||||
|             "); | ||||
|             $pdo->exec(" | ||||
| CREATE UNIQUE INDEX path_property ON propertystorage (path(600), name(100)); | ||||
|             "); | ||||
|             break; | ||||
|         case 'sqlite' : | ||||
|             $pdo->exec(" | ||||
| CREATE TABLE propertystorage ( | ||||
|     id integer primary key asc, | ||||
|     path TEXT, | ||||
|     name TEXT, | ||||
|     value TEXT | ||||
| ); | ||||
|             "); | ||||
|             $pdo->exec(" | ||||
| CREATE UNIQUE INDEX path_property ON propertystorage (path, name); | ||||
|             "); | ||||
|  | ||||
|             break; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| echo "Upgrading cards table to 2.0 schema\n"; | ||||
|  | ||||
| try { | ||||
|  | ||||
|     $create = false; | ||||
|     $row = $pdo->query("SELECT * FROM cards LIMIT 1")->fetch(); | ||||
|     if (!$row) { | ||||
|         $random = mt_rand(1000, 9999); | ||||
|         echo "There was no data in the cards table, so we're re-creating it\n"; | ||||
|         echo "The old table will be renamed to cards_old$random, just in case.\n"; | ||||
|  | ||||
|         $create = true; | ||||
|  | ||||
|         switch ($driver) { | ||||
|             case 'mysql' : | ||||
|                 $pdo->exec("RENAME TABLE cards TO cards_old$random"); | ||||
|                 break; | ||||
|             case 'sqlite' : | ||||
|                 $pdo->exec("ALTER TABLE cards RENAME TO cards_old$random"); | ||||
|                 break; | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } catch (Exception $e) { | ||||
|  | ||||
|     echo "Exception while checking cards table. Assuming that the table does not yet exist.\n"; | ||||
|     echo "Debug: ", $e->getMessage(), "\n"; | ||||
|     $create = true; | ||||
|  | ||||
| } | ||||
|  | ||||
| if ($create) { | ||||
|     switch ($driver) { | ||||
|         case 'mysql' : | ||||
|             $pdo->exec(" | ||||
| CREATE TABLE cards ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     addressbookid INT(11) UNSIGNED NOT NULL, | ||||
|     carddata MEDIUMBLOB, | ||||
|     uri VARCHAR(200), | ||||
|     lastmodified INT(11) UNSIGNED, | ||||
|     etag VARBINARY(32), | ||||
|     size INT(11) UNSIGNED NOT NULL | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|             "); | ||||
|             break; | ||||
|  | ||||
|         case 'sqlite' : | ||||
|  | ||||
|             $pdo->exec(" | ||||
| CREATE TABLE cards ( | ||||
|     id integer primary key asc, | ||||
|     addressbookid integer, | ||||
|     carddata blob, | ||||
|     uri text, | ||||
|     lastmodified integer, | ||||
|     etag text, | ||||
|     size integer | ||||
| ); | ||||
|             "); | ||||
|             break; | ||||
|  | ||||
|     } | ||||
| } else { | ||||
|     switch ($driver) { | ||||
|         case 'mysql' : | ||||
|             $pdo->exec(" | ||||
|                 ALTER TABLE cards | ||||
|                 ADD etag VARBINARY(32), | ||||
|                 ADD size INT(11) UNSIGNED NOT NULL; | ||||
|             "); | ||||
|             break; | ||||
|  | ||||
|         case 'sqlite' : | ||||
|  | ||||
|             $pdo->exec(" | ||||
|                 ALTER TABLE cards ADD etag text; | ||||
|                 ALTER TABLE cards ADD size integer; | ||||
|             "); | ||||
|             break; | ||||
|  | ||||
|     } | ||||
|     echo "Reading all old vcards and populating etag and size fields.\n"; | ||||
|     $result = $pdo->query('SELECT id, carddata FROM cards'); | ||||
|     $stmt = $pdo->prepare('UPDATE cards SET etag = ?, size = ? WHERE id = ?'); | ||||
|     while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { | ||||
|         $stmt->execute([ | ||||
|             md5($row['carddata']), | ||||
|             strlen($row['carddata']), | ||||
|             $row['id'] | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| echo "Upgrade to 2.0 schema completed.\n"; | ||||
							
								
								
									
										180
									
								
								vendor/sabre/dav/bin/migrateto21.php
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										180
									
								
								vendor/sabre/dav/bin/migrateto21.php
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| #!/usr/bin/env php | ||||
| <?php | ||||
|  | ||||
| echo "SabreDAV migrate script for version 2.1\n"; | ||||
|  | ||||
| if ($argc < 2) { | ||||
|  | ||||
|     echo <<<HELLO | ||||
|  | ||||
| This script help you migrate from a pre-2.1 database to 2.1. | ||||
|  | ||||
| Changes: | ||||
|   The 'calendarobjects' table will be upgraded. | ||||
|   'schedulingobjects' will be created. | ||||
|  | ||||
| If you don't use the default PDO CalDAV or CardDAV backend, it's pointless to | ||||
| run this script. | ||||
|  | ||||
| Keep in mind that ALTER TABLE commands will be executed. If you have a large | ||||
| dataset this may mean that this process takes a while. | ||||
|  | ||||
| Lastly: Make a back-up first. This script has been tested, but the amount of | ||||
| potential variants are extremely high, so it's impossible to deal with every | ||||
| possible situation. | ||||
|  | ||||
| In the worst case, you will lose all your data. This is not an overstatement. | ||||
|  | ||||
| Usage: | ||||
|  | ||||
| php {$argv[0]} [pdo-dsn] [username] [password] | ||||
|  | ||||
| For example: | ||||
|  | ||||
| php {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password | ||||
| php {$argv[0]} sqlite:data/sabredav.db | ||||
|  | ||||
| HELLO; | ||||
|  | ||||
|     exit(); | ||||
|  | ||||
| } | ||||
|  | ||||
| // There's a bunch of places where the autoloader could be, so we'll try all of | ||||
| // them. | ||||
| $paths = [ | ||||
|     __DIR__ . '/../vendor/autoload.php', | ||||
|     __DIR__ . '/../../../autoload.php', | ||||
| ]; | ||||
|  | ||||
| foreach ($paths as $path) { | ||||
|     if (file_exists($path)) { | ||||
|         include $path; | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| $dsn = $argv[1]; | ||||
| $user = isset($argv[2]) ? $argv[2] : null; | ||||
| $pass = isset($argv[3]) ? $argv[3] : null; | ||||
|  | ||||
| echo "Connecting to database: " . $dsn . "\n"; | ||||
|  | ||||
| $pdo = new PDO($dsn, $user, $pass); | ||||
| $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||||
| $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); | ||||
|  | ||||
| $driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME); | ||||
|  | ||||
| switch ($driver) { | ||||
|  | ||||
|     case 'mysql' : | ||||
|         echo "Detected MySQL.\n"; | ||||
|         break; | ||||
|     case 'sqlite' : | ||||
|         echo "Detected SQLite.\n"; | ||||
|         break; | ||||
|     default : | ||||
|         echo "Error: unsupported driver: " . $driver . "\n"; | ||||
|         die(-1); | ||||
| } | ||||
|  | ||||
| echo "Upgrading 'calendarobjects'\n"; | ||||
| $addUid = false; | ||||
| try { | ||||
|     $result = $pdo->query('SELECT * FROM calendarobjects LIMIT 1'); | ||||
|     $row = $result->fetch(\PDO::FETCH_ASSOC); | ||||
|  | ||||
|     if (!$row) { | ||||
|         echo "No data in table. Going to try to add the uid field anyway.\n"; | ||||
|         $addUid = true; | ||||
|     } elseif (array_key_exists('uid', $row)) { | ||||
|         echo "uid field exists. Assuming that this part of the migration has\n"; | ||||
|         echo "Already been completed.\n"; | ||||
|     } else { | ||||
|         echo "2.0 schema detected.\n"; | ||||
|         $addUid = true; | ||||
|     } | ||||
|  | ||||
| } catch (Exception $e) { | ||||
|     echo "Could not find a calendarobjects table. Skipping this part of the\n"; | ||||
|     echo "upgrade.\n"; | ||||
| } | ||||
|  | ||||
| if ($addUid) { | ||||
|  | ||||
|     switch ($driver) { | ||||
|         case 'mysql' : | ||||
|             $pdo->exec('ALTER TABLE calendarobjects ADD uid VARCHAR(200)'); | ||||
|             break; | ||||
|         case 'sqlite' : | ||||
|             $pdo->exec('ALTER TABLE calendarobjects ADD uid TEXT'); | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     $result = $pdo->query('SELECT id, calendardata FROM calendarobjects'); | ||||
|     $stmt = $pdo->prepare('UPDATE calendarobjects SET uid = ? WHERE id = ?'); | ||||
|     $counter = 0; | ||||
|  | ||||
|     while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { | ||||
|  | ||||
|         try { | ||||
|             $vobj = \Sabre\VObject\Reader::read($row['calendardata']); | ||||
|         } catch (\Exception $e) { | ||||
|             echo "Warning! Item with id $row[id] could not be parsed!\n"; | ||||
|             continue; | ||||
|         } | ||||
|         $uid = null; | ||||
|         $item = $vobj->getBaseComponent(); | ||||
|         if (!isset($item->UID)) { | ||||
|             echo "Warning! Item with id $item[id] does NOT have a UID property and this is required.\n"; | ||||
|             continue; | ||||
|         } | ||||
|         $uid = (string)$item->UID; | ||||
|         $stmt->execute([$uid, $row['id']]); | ||||
|         $counter++; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| echo "Creating 'schedulingobjects'\n"; | ||||
|  | ||||
| switch ($driver) { | ||||
|  | ||||
|     case 'mysql' : | ||||
|         $pdo->exec('CREATE TABLE IF NOT EXISTS schedulingobjects | ||||
| ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     principaluri VARCHAR(255), | ||||
|     calendardata MEDIUMBLOB, | ||||
|     uri VARCHAR(200), | ||||
|     lastmodified INT(11) UNSIGNED, | ||||
|     etag VARCHAR(32), | ||||
|     size INT(11) UNSIGNED NOT NULL | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|         '); | ||||
|         break; | ||||
|  | ||||
|  | ||||
|     case 'sqlite' : | ||||
|         $pdo->exec('CREATE TABLE IF NOT EXISTS schedulingobjects ( | ||||
|     id integer primary key asc, | ||||
|     principaluri text, | ||||
|     calendardata blob, | ||||
|     uri text, | ||||
|     lastmodified integer, | ||||
|     etag text, | ||||
|     size integer | ||||
| ) | ||||
| '); | ||||
|         break; | ||||
|         $pdo->exec(' | ||||
|             CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri); | ||||
|         '); | ||||
|         break; | ||||
| } | ||||
|  | ||||
| echo "Done.\n"; | ||||
|  | ||||
| echo "Upgrade to 2.1 schema completed.\n"; | ||||
							
								
								
									
										171
									
								
								vendor/sabre/dav/bin/migrateto30.php
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										171
									
								
								vendor/sabre/dav/bin/migrateto30.php
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| #!/usr/bin/env php | ||||
| <?php | ||||
|  | ||||
| echo "SabreDAV migrate script for version 3.0\n"; | ||||
|  | ||||
| if ($argc < 2) { | ||||
|  | ||||
|     echo <<<HELLO | ||||
|  | ||||
| This script help you migrate from a pre-3.0 database to 3.0 and later | ||||
|  | ||||
| Changes: | ||||
|   * The propertystorage table has changed to allow storage of complex | ||||
|     properties. | ||||
|   * the vcardurl field in the principals table is no more. This was moved to | ||||
|     the propertystorage table. | ||||
|  | ||||
| Keep in mind that ALTER TABLE commands will be executed. If you have a large | ||||
| dataset this may mean that this process takes a while. | ||||
|  | ||||
| Lastly: Make a back-up first. This script has been tested, but the amount of | ||||
| potential variants are extremely high, so it's impossible to deal with every | ||||
| possible situation. | ||||
|  | ||||
| In the worst case, you will lose all your data. This is not an overstatement. | ||||
|  | ||||
| Usage: | ||||
|  | ||||
| php {$argv[0]} [pdo-dsn] [username] [password] | ||||
|  | ||||
| For example: | ||||
|  | ||||
| php {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password | ||||
| php {$argv[0]} sqlite:data/sabredav.db | ||||
|  | ||||
| HELLO; | ||||
|  | ||||
|     exit(); | ||||
|  | ||||
| } | ||||
|  | ||||
| // There's a bunch of places where the autoloader could be, so we'll try all of | ||||
| // them. | ||||
| $paths = [ | ||||
|     __DIR__ . '/../vendor/autoload.php', | ||||
|     __DIR__ . '/../../../autoload.php', | ||||
| ]; | ||||
|  | ||||
| foreach ($paths as $path) { | ||||
|     if (file_exists($path)) { | ||||
|         include $path; | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| $dsn = $argv[1]; | ||||
| $user = isset($argv[2]) ? $argv[2] : null; | ||||
| $pass = isset($argv[3]) ? $argv[3] : null; | ||||
|  | ||||
| echo "Connecting to database: " . $dsn . "\n"; | ||||
|  | ||||
| $pdo = new PDO($dsn, $user, $pass); | ||||
| $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||||
| $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); | ||||
|  | ||||
| $driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME); | ||||
|  | ||||
| switch ($driver) { | ||||
|  | ||||
|     case 'mysql' : | ||||
|         echo "Detected MySQL.\n"; | ||||
|         break; | ||||
|     case 'sqlite' : | ||||
|         echo "Detected SQLite.\n"; | ||||
|         break; | ||||
|     default : | ||||
|         echo "Error: unsupported driver: " . $driver . "\n"; | ||||
|         die(-1); | ||||
| } | ||||
|  | ||||
| echo "Upgrading 'propertystorage'\n"; | ||||
| $addValueType = false; | ||||
| try { | ||||
|     $result = $pdo->query('SELECT * FROM propertystorage LIMIT 1'); | ||||
|     $row = $result->fetch(\PDO::FETCH_ASSOC); | ||||
|  | ||||
|     if (!$row) { | ||||
|         echo "No data in table. Going to re-create the table.\n"; | ||||
|         $random = mt_rand(1000, 9999); | ||||
|         echo "Renaming propertystorage -> propertystorage_old$random and creating new table.\n"; | ||||
|  | ||||
|         switch ($driver) { | ||||
|  | ||||
|             case 'mysql' : | ||||
|                 $pdo->exec('RENAME TABLE propertystorage TO propertystorage_old' . $random); | ||||
|                 $pdo->exec(' | ||||
|     CREATE TABLE propertystorage ( | ||||
|         id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|         path VARBINARY(1024) NOT NULL, | ||||
|         name VARBINARY(100) NOT NULL, | ||||
|         valuetype INT UNSIGNED, | ||||
|         value MEDIUMBLOB | ||||
|     ); | ||||
|                 '); | ||||
|                 $pdo->exec('CREATE UNIQUE INDEX path_property_' . $random . '  ON propertystorage (path(600), name(100));'); | ||||
|                 break; | ||||
|             case 'sqlite' : | ||||
|                 $pdo->exec('ALTER TABLE propertystorage RENAME TO propertystorage_old' . $random); | ||||
|                 $pdo->exec(' | ||||
| CREATE TABLE propertystorage ( | ||||
|     id integer primary key asc, | ||||
|     path text, | ||||
|     name text, | ||||
|     valuetype integer, | ||||
|     value blob | ||||
| );'); | ||||
|  | ||||
|                 $pdo->exec('CREATE UNIQUE INDEX path_property_' . $random . ' ON propertystorage (path, name);'); | ||||
|                 break; | ||||
|  | ||||
|         } | ||||
|     } elseif (array_key_exists('valuetype', $row)) { | ||||
|         echo "valuetype field exists. Assuming that this part of the migration has\n"; | ||||
|         echo "Already been completed.\n"; | ||||
|     } else { | ||||
|         echo "2.1 schema detected. Going to perform upgrade.\n"; | ||||
|         $addValueType = true; | ||||
|     } | ||||
|  | ||||
| } catch (Exception $e) { | ||||
|     echo "Could not find a propertystorage table. Skipping this part of the\n"; | ||||
|     echo "upgrade.\n"; | ||||
|     echo $e->getMessage(), "\n"; | ||||
| } | ||||
|  | ||||
| if ($addValueType) { | ||||
|  | ||||
|     switch ($driver) { | ||||
|         case 'mysql' : | ||||
|             $pdo->exec('ALTER TABLE propertystorage ADD valuetype INT UNSIGNED'); | ||||
|             break; | ||||
|         case 'sqlite' : | ||||
|             $pdo->exec('ALTER TABLE propertystorage ADD valuetype INT'); | ||||
|  | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     $pdo->exec('UPDATE propertystorage SET valuetype = 1 WHERE valuetype IS NULL '); | ||||
|  | ||||
| } | ||||
|  | ||||
| echo "Migrating vcardurl\n"; | ||||
|  | ||||
| $result = $pdo->query('SELECT id, uri, vcardurl FROM principals WHERE vcardurl IS NOT NULL'); | ||||
| $stmt1 = $pdo->prepare('INSERT INTO propertystorage (path, name, valuetype, value) VALUES (?, ?, 3, ?)'); | ||||
|  | ||||
| while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { | ||||
|  | ||||
|     // Inserting the new record | ||||
|     $stmt1->execute([ | ||||
|         'addressbooks/' . basename($row['uri']), | ||||
|         '{http://calendarserver.org/ns/}me-card', | ||||
|         serialize(new Sabre\DAV\Xml\Property\Href($row['vcardurl'])) | ||||
|     ]); | ||||
|  | ||||
|     echo serialize(new Sabre\DAV\Xml\Property\Href($row['vcardurl'])); | ||||
|  | ||||
| } | ||||
|  | ||||
| echo "Done.\n"; | ||||
| echo "Upgrade to 3.0 schema completed.\n"; | ||||
| @@ -6,7 +6,7 @@ | ||||
| # http://www.rooftopsolutions.nl/ | ||||
| # | ||||
| # This utility is distributed along with SabreDAV | ||||
| # license: http://code.google.com/p/sabredav/wiki/License Modified BSD License | ||||
| # license: http://sabre.io/license/ Modified BSD License | ||||
| 
 | ||||
| import os | ||||
| from optparse import OptionParser | ||||
| @@ -16,16 +16,16 @@ def getfreespace(path): | ||||
|     stat = os.statvfs(path) | ||||
|     return stat.f_frsize * stat.f_bavail | ||||
| 
 | ||||
| def getbytesleft(path,treshold): | ||||
|     return getfreespace(path)-treshold | ||||
| def getbytesleft(path,threshold): | ||||
|     return getfreespace(path)-threshold | ||||
| 
 | ||||
| def run(cacheDir, treshold, sleep=5, simulate=False, min_erase = 0): | ||||
| def run(cacheDir, threshold, sleep=5, simulate=False, min_erase = 0): | ||||
| 
 | ||||
|     bytes = getbytesleft(cacheDir,treshold) | ||||
|     bytes = getbytesleft(cacheDir,threshold) | ||||
|     if (bytes>0): | ||||
|         print "Bytes to go before we hit treshhold:", bytes | ||||
|         print "Bytes to go before we hit threshold:", bytes | ||||
|     else: | ||||
|         print "Treshold exceeded with:", -bytes, "bytes" | ||||
|         print "Threshold exceeded with:", -bytes, "bytes" | ||||
|         dir = os.listdir(cacheDir) | ||||
|         dir2 = [] | ||||
|         for file in dir: | ||||
| @@ -46,7 +46,7 @@ def run(cacheDir, treshold, sleep=5, simulate=False, min_erase = 0): | ||||
|         left = min_erase | ||||
| 
 | ||||
|         # If the min_erase setting is lower than the amount of bytes over | ||||
|         # the treshold, we use that number instead. | ||||
|         # the threshold, we use that number instead. | ||||
|         if left < -bytes : | ||||
|             left = -bytes | ||||
| 
 | ||||
| @@ -72,8 +72,8 @@ def run(cacheDir, treshold, sleep=5, simulate=False, min_erase = 0): | ||||
| 
 | ||||
| def main(): | ||||
|     parser = OptionParser( | ||||
|         version="naturalselecton v0.3", | ||||
|         description="Cache directory manager. Deletes cache entries based on accesstime and free space tresholds.\n" + | ||||
|         version="naturalselection v0.3", | ||||
|         description="Cache directory manager. Deletes cache entries based on accesstime and free space thresholds.\n" + | ||||
|             "This utility is distributed alongside SabreDAV.", | ||||
|         usage="usage: %prog [options] cacheDirectory", | ||||
|     ) | ||||
| @@ -98,15 +98,15 @@ def main(): | ||||
|         default=5 | ||||
|     ) | ||||
|     parser.add_option( | ||||
|         '-l','--treshold', | ||||
|         help="Treshhold in bytes (default = 10737418240, which is 10GB)", | ||||
|         '-l','--threshold', | ||||
|         help="Threshold in bytes (default = 10737418240, which is 10GB)", | ||||
|         type="int", | ||||
|         dest="treshold", | ||||
|         dest="threshold", | ||||
|         default=10737418240 | ||||
|     ) | ||||
|     parser.add_option( | ||||
|         '-m', '--min-erase', | ||||
|         help="Minimum number of bytes to erase when the treshold is reached. " + | ||||
|         help="Minimum number of bytes to erase when the threshold is reached. " + | ||||
|             "Setting this option higher will reduce the amount of times the cache directory will need to be scanned. " + | ||||
|             "(the default is 1073741824, which is 1GB.)", | ||||
|         type="int", | ||||
| @@ -130,7 +130,7 @@ def main(): | ||||
|             cacheDir, | ||||
|             sleep=options.sleep, | ||||
|             simulate=options.simulate, | ||||
|             treshold=options.treshold, | ||||
|             threshold=options.threshold, | ||||
|             min_erase=options.min_erase | ||||
|         ) | ||||
|         if runs>0: | ||||
							
								
								
									
										4
									
								
								vendor/sabre/dav/bin/sabredav.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/sabre/dav/bin/sabredav.php
									
									
									
									
										vendored
									
									
								
							| @@ -27,10 +27,10 @@ if (php_sapi_name()!=='cli-server') { | ||||
| // Finding composer | ||||
|  | ||||
|  | ||||
| $paths = array( | ||||
| $paths = [ | ||||
|     __DIR__ . '/../vendor/autoload.php', | ||||
|     __DIR__ . '/../../../autoload.php', | ||||
| ); | ||||
| ]; | ||||
|  | ||||
| foreach ($paths as $path) { | ||||
|     if (file_exists($path)) { | ||||
|   | ||||
| @@ -35,22 +35,23 @@ $carddavBackend   = new Sabre\CardDAV\Backend\PDO($pdo); | ||||
| //$caldavBackend    = new Sabre\CalDAV\Backend\PDO($pdo); | ||||
|  | ||||
| // Setting up the directory tree // | ||||
| $nodes = array( | ||||
| $nodes = [ | ||||
|     new Sabre\DAVACL\PrincipalCollection($principalBackend), | ||||
| //    new Sabre\CalDAV\CalendarRootNode($authBackend, $caldavBackend), | ||||
| //    new Sabre\CalDAV\CalendarRoot($authBackend, $caldavBackend), | ||||
|     new Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend), | ||||
| ); | ||||
| ]; | ||||
|  | ||||
| // The object tree needs in turn to be passed to the server class | ||||
| $server = new Sabre\DAV\Server($nodes); | ||||
| $server->setBaseUri($baseUri); | ||||
|  | ||||
| // Plugins | ||||
| $server->addPlugin(new Sabre\DAV\Auth\Plugin($authBackend,'SabreDAV')); | ||||
| $server->addPlugin(new Sabre\DAV\Auth\Plugin($authBackend)); | ||||
| $server->addPlugin(new Sabre\DAV\Browser\Plugin()); | ||||
| //$server->addPlugin(new Sabre\CalDAV\Plugin()); | ||||
| $server->addPlugin(new Sabre\CardDAV\Plugin()); | ||||
| $server->addPlugin(new Sabre\DAVACL\Plugin()); | ||||
| $server->addPlugin(new Sabre\DAV\Sync\Plugin()); | ||||
|  | ||||
| // And off we go! | ||||
| $server->exec(); | ||||
|   | ||||
							
								
								
									
										26
									
								
								vendor/sabre/dav/examples/basicauth.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/sabre/dav/examples/basicauth.php
									
									
									
									
										vendored
									
									
								
							| @@ -1,26 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| // !!!! Make sure the Sabre directory is in the include_path !!! | ||||
| // example: | ||||
| // set_include_path('lib/' . PATH_SEPARATOR . get_include_path()); | ||||
|  | ||||
| // settings | ||||
| date_default_timezone_set('Canada/Eastern'); | ||||
|  | ||||
| // Files we need | ||||
| require_once 'vendor/autoload.php'; | ||||
|  | ||||
| $u = 'admin'; | ||||
| $p = '1234'; | ||||
|  | ||||
| $auth = new \Sabre\HTTP\BasicAuth(); | ||||
|  | ||||
| $result = $auth->getUserPass(); | ||||
|  | ||||
| if (!$result || $result[0]!=$u || $result[1]!=$p) { | ||||
|  | ||||
|     $auth->requireLogin(); | ||||
|     echo "Authentication required\n"; | ||||
|     die(); | ||||
|  | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/sabre/dav/examples/digestauth.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/sabre/dav/examples/digestauth.php
									
									
									
									
										vendored
									
									
								
							| @@ -1,25 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| // !!!! Make sure the Sabre directory is in the include_path !!! | ||||
| // example: | ||||
| // set_include_path('lib/' . PATH_SEPARATOR . get_include_path()); | ||||
|  | ||||
| // settings | ||||
| date_default_timezone_set('Canada/Eastern'); | ||||
|  | ||||
| // Files we need | ||||
| require_once 'vendor/autoload.php'; | ||||
|  | ||||
| $u = 'admin'; | ||||
| $p = '1234'; | ||||
|  | ||||
| $auth = new \Sabre\HTTP\DigestAuth(); | ||||
| $auth->init(); | ||||
|  | ||||
| if ($auth->getUsername() != $u || !$auth->validatePassword($p)) { | ||||
|  | ||||
|     $auth->requireLogin(); | ||||
|     echo "Authentication required\n"; | ||||
|     die(); | ||||
|  | ||||
| } | ||||
							
								
								
									
										123
									
								
								vendor/sabre/dav/examples/simplefsserver.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										123
									
								
								vendor/sabre/dav/examples/simplefsserver.php
									
									
									
									
										vendored
									
									
								
							| @@ -1,123 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| // !!!! Make sure the Sabre directory is in the include_path !!! | ||||
| // example: | ||||
| // set_include_path('lib/' . PATH_SEPARATOR . get_include_path()); | ||||
|  | ||||
| /* | ||||
|  | ||||
| This example demonstrates a simple way to create your own virtual filesystems. | ||||
| By extending the _File and Directory classes, you can easily create a tree | ||||
| based on various datasources. | ||||
|  | ||||
| The most obvious example is the filesystem itself. A more complete and documented | ||||
| example can be found in: | ||||
|  | ||||
| lib/Sabre/DAV/FS/Node.php | ||||
| lib/Sabre/DAV/FS/Directory.php | ||||
| lib/Sabre/DAV/FS/File.php | ||||
|  | ||||
| */ | ||||
|  | ||||
| // settings | ||||
| date_default_timezone_set('Canada/Eastern'); | ||||
| $publicDir = 'public'; | ||||
|  | ||||
| // Files we need | ||||
| require_once 'vendor/autoload.php'; | ||||
|  | ||||
| class MyCollection extends Sabre\DAV\Collection { | ||||
|  | ||||
|   private $myPath; | ||||
|  | ||||
|   function __construct($myPath) { | ||||
|  | ||||
|     $this->myPath = $myPath; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   function getChildren() { | ||||
|  | ||||
|     $children = array(); | ||||
|     // Loop through the directory, and create objects for each node | ||||
|     foreach(scandir($this->myPath) as $node) { | ||||
|  | ||||
|       // Ignoring files staring with . | ||||
|       if ($node[0]==='.') continue; | ||||
|  | ||||
|       $children[] = $this->getChild($node); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     return $children; | ||||
|  | ||||
|   } | ||||
|  | ||||
|     function getChild($name) { | ||||
|  | ||||
|         $path = $this->myPath . '/' . $name; | ||||
|  | ||||
|         // We have to throw a NotFound exception if the file didn't exist | ||||
|         if (!file\exists($this->myPath)) throw new \Sabre\DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found'); | ||||
|         // Some added security | ||||
|  | ||||
|         if ($name[0]=='.')  throw new \Sabre\DAV\Exception\Forbidden('Access denied'); | ||||
|  | ||||
|         if (is_dir($path)) { | ||||
|  | ||||
|             return new \MyCollection($name); | ||||
|  | ||||
|         } else { | ||||
|  | ||||
|             return new \MyFile($path); | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function getName() { | ||||
|  | ||||
|         return basename($this->myPath); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| class MyFile extends \Sabre\DAV\File { | ||||
|  | ||||
|   private $myPath; | ||||
|  | ||||
|   function __construct($myPath) { | ||||
|  | ||||
|     $this->myPath = $myPath; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   function getName() { | ||||
|  | ||||
|       return basename($this->myPath); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   function get() { | ||||
|  | ||||
|     return fopen($this->myPath,'r'); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   function getSize() { | ||||
|  | ||||
|       return filesize($this->myPath); | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| // Make sure there is a directory in your current directory named 'public'. We will be exposing that directory to WebDAV | ||||
| $rootNode = new \MyCollection($publicDir); | ||||
|  | ||||
| // The rootNode needs to be passed to the server object. | ||||
| $server = new \Sabre\DAV\Server($rootNode); | ||||
|  | ||||
| // And off we go! | ||||
| $server->exec(); | ||||
| @@ -1,18 +1,28 @@ | ||||
| CREATE TABLE addressbooks ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     principaluri VARCHAR(255), | ||||
|     principaluri VARBINARY(255), | ||||
|     displayname VARCHAR(255), | ||||
|     uri VARCHAR(200), | ||||
|     uri VARBINARY(200), | ||||
|     description TEXT, | ||||
|     ctag INT(11) UNSIGNED NOT NULL DEFAULT '1', | ||||
|     UNIQUE(principaluri, uri) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|     synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1', | ||||
|     UNIQUE(principaluri(100), uri(100)) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| CREATE TABLE cards ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     addressbookid INT(11) UNSIGNED NOT NULL, | ||||
|     carddata MEDIUMBLOB, | ||||
|     uri VARCHAR(200), | ||||
|     lastmodified INT(11) UNSIGNED | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|     uri VARBINARY(200), | ||||
|     lastmodified INT(11) UNSIGNED, | ||||
|     etag VARBINARY(32), | ||||
|     size INT(11) UNSIGNED NOT NULL | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| CREATE TABLE addressbookchanges ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     uri VARBINARY(200) NOT NULL, | ||||
|     synctoken INT(11) UNSIGNED NOT NULL, | ||||
|     addressbookid INT(11) UNSIGNED NOT NULL, | ||||
|     operation TINYINT(1) NOT NULL, | ||||
|     INDEX addressbookid_synctoken (addressbookid, synctoken) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|   | ||||
| @@ -1,28 +1,64 @@ | ||||
| CREATE TABLE calendarobjects ( | ||||
|     id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     calendardata MEDIUMBLOB, | ||||
|     uri VARCHAR(200), | ||||
|     uri VARBINARY(200), | ||||
|     calendarid INTEGER UNSIGNED NOT NULL, | ||||
|     lastmodified INT(11) UNSIGNED, | ||||
|     etag VARCHAR(32), | ||||
|     etag VARBINARY(32), | ||||
|     size INT(11) UNSIGNED NOT NULL, | ||||
|     componenttype VARCHAR(8), | ||||
|     componenttype VARBINARY(8), | ||||
|     firstoccurence INT(11) UNSIGNED, | ||||
|     lastoccurence INT(11) UNSIGNED, | ||||
|     uid VARBINARY(200), | ||||
|     UNIQUE(calendarid, uri) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| CREATE TABLE calendars ( | ||||
|     id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     principaluri VARCHAR(100), | ||||
|     principaluri VARBINARY(100), | ||||
|     displayname VARCHAR(100), | ||||
|     uri VARCHAR(200), | ||||
|     ctag INTEGER UNSIGNED NOT NULL DEFAULT '0', | ||||
|     uri VARBINARY(200), | ||||
|     synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1', | ||||
|     description TEXT, | ||||
|     calendarorder INTEGER UNSIGNED NOT NULL DEFAULT '0', | ||||
|     calendarcolor VARCHAR(10), | ||||
|     calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', | ||||
|     calendarcolor VARBINARY(10), | ||||
|     timezone TEXT, | ||||
|     components VARCHAR(20), | ||||
|     components VARBINARY(21), | ||||
|     transparent TINYINT(1) NOT NULL DEFAULT '0', | ||||
|     UNIQUE(principaluri, uri) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| CREATE TABLE calendarchanges ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     uri VARBINARY(200) NOT NULL, | ||||
|     synctoken INT(11) UNSIGNED NOT NULL, | ||||
|     calendarid INT(11) UNSIGNED NOT NULL, | ||||
|     operation TINYINT(1) NOT NULL, | ||||
|     INDEX calendarid_synctoken (calendarid, synctoken) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| CREATE TABLE calendarsubscriptions ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     uri VARBINARY(200) NOT NULL, | ||||
|     principaluri VARBINARY(100) NOT NULL, | ||||
|     source TEXT, | ||||
|     displayname VARCHAR(100), | ||||
|     refreshrate VARCHAR(10), | ||||
|     calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', | ||||
|     calendarcolor VARBINARY(10), | ||||
|     striptodos TINYINT(1) NULL, | ||||
|     stripalarms TINYINT(1) NULL, | ||||
|     stripattachments TINYINT(1) NULL, | ||||
|     lastmodified INT(11) UNSIGNED, | ||||
|     UNIQUE(principaluri, uri) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| CREATE TABLE schedulingobjects ( | ||||
|     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     principaluri VARBINARY(255), | ||||
|     calendardata MEDIUMBLOB, | ||||
|     uri VARBINARY(200), | ||||
|     lastmodified INT(11) UNSIGNED, | ||||
|     etag VARBINARY(32), | ||||
|     size INT(11) UNSIGNED NOT NULL | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|   | ||||
| @@ -3,11 +3,10 @@ CREATE TABLE locks ( | ||||
|     owner VARCHAR(100), | ||||
|     timeout INTEGER UNSIGNED, | ||||
|     created INTEGER, | ||||
|     token VARCHAR(100), | ||||
|     token VARBINARY(100), | ||||
|     scope TINYINT, | ||||
|     depth TINYINT, | ||||
|     uri VARCHAR(1000), | ||||
|     uri VARBINARY(1000), | ||||
|     INDEX(token), | ||||
|     INDEX(uri) | ||||
| ); | ||||
|  | ||||
|     INDEX(uri(100)) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|   | ||||
| @@ -1,19 +1,17 @@ | ||||
| CREATE TABLE principals ( | ||||
|     id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     uri VARCHAR(200) NOT NULL, | ||||
|     email VARCHAR(80), | ||||
|     uri VARBINARY(200) NOT NULL, | ||||
|     email VARBINARY(80), | ||||
|     displayname VARCHAR(80), | ||||
|     vcardurl VARCHAR(255), | ||||
|     UNIQUE(uri) | ||||
| ); | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| CREATE TABLE groupmembers ( | ||||
|     id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     principal_id INTEGER UNSIGNED NOT NULL, | ||||
|     member_id INTEGER UNSIGNED NOT NULL, | ||||
|     UNIQUE(principal_id, member_id) | ||||
| ); | ||||
|  | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| INSERT INTO principals (uri,email,displayname) VALUES | ||||
| ('principals/admin', 'admin@example.org','Administrator'), | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| CREATE TABLE users ( | ||||
|     id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, | ||||
|     username VARCHAR(50), | ||||
|     digesta1 VARCHAR(32), | ||||
|     username VARBINARY(50), | ||||
|     digesta1 VARBINARY(32), | ||||
|     UNIQUE(username) | ||||
| ); | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | ||||
|  | ||||
| INSERT INTO users (username,digesta1) VALUES | ||||
| ('admin',  '87fd274b7b6c01e48d7c2f965da8ddf7'); | ||||
|   | ||||
| @@ -4,7 +4,7 @@ CREATE TABLE addressbooks ( | ||||
|     displayname VARCHAR(255), | ||||
|     uri VARCHAR(200), | ||||
|     description TEXT, | ||||
|     ctag INTEGER NOT NULL DEFAULT 1 | ||||
|     synctoken INTEGER NOT NULL DEFAULT 1 | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY addressbooks | ||||
| @@ -18,7 +18,9 @@ CREATE TABLE cards ( | ||||
|     addressbookid INTEGER NOT NULL, | ||||
|     carddata TEXT, | ||||
|     uri VARCHAR(200), | ||||
|     lastmodified INTEGER | ||||
|     lastmodified INTEGER, | ||||
|     etag VARCHAR(32), | ||||
|     size INTEGER NOT NULL | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY cards | ||||
| @@ -31,3 +33,20 @@ ALTER TABLE ONLY cards | ||||
|     ADD CONSTRAINT cards_addressbookid_fkey FOREIGN KEY (addressbookid) REFERENCES addressbooks(id) | ||||
|         ON DELETE CASCADE; | ||||
|  | ||||
| CREATE TABLE addressbookchanges ( | ||||
|     id SERIAL NOT NULL, | ||||
|     uri VARCHAR(200) NOT NULL, | ||||
|     synctoken INTEGER NOT NULL, | ||||
|     addressbookid INTEGER NOT NULL, | ||||
|     operation SMALLINT NOT NULL | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY addressbookchanges | ||||
|     ADD CONSTRAINT addressbookchanges_pkey PRIMARY KEY (id); | ||||
|  | ||||
| CREATE INDEX addressbookchanges_addressbookid_synctoken_ix | ||||
|     ON addressbookchanges USING btree (addressbookid, synctoken); | ||||
|  | ||||
| ALTER TABLE ONLY addressbookchanges | ||||
|     ADD CONSTRAINT addressbookchanges_addressbookid_fkey FOREIGN KEY (addressbookid) REFERENCES addressbooks(id) | ||||
|         ON DELETE CASCADE; | ||||
|   | ||||
| @@ -3,12 +3,13 @@ CREATE TABLE calendars ( | ||||
|     principaluri VARCHAR(100), | ||||
|     displayname VARCHAR(100), | ||||
|     uri VARCHAR(200), | ||||
|     ctag INTEGER NOT NULL DEFAULT 0, | ||||
|     synctoken INTEGER NOT NULL DEFAULT 1, | ||||
|     description TEXT, | ||||
|     calendarorder INTEGER NOT NULL DEFAULT 0, | ||||
|     calendarcolor VARCHAR(10), | ||||
|     timezone TEXT, | ||||
|     components VARCHAR(20), | ||||
|     uid VARCHAR(200), | ||||
|     transparent SMALLINT NOT NULL DEFAULT '0' | ||||
| ); | ||||
|  | ||||
| @@ -20,15 +21,16 @@ CREATE UNIQUE INDEX calendars_ukey | ||||
|  | ||||
| CREATE TABLE calendarobjects ( | ||||
|     id SERIAL NOT NULL, | ||||
|     calendarid INTEGER NOT NULL, | ||||
|     calendardata TEXT, | ||||
|     uri VARCHAR(200), | ||||
|     calendarid INTEGER NOT NULL, | ||||
|     lastmodified INTEGER, | ||||
|     etag VARCHAR(32), | ||||
|     size INTEGER NOT NULL, | ||||
|     componenttype VARCHAR(8), | ||||
|     lastmodified INTEGER, | ||||
|     firstoccurence INTEGER, | ||||
|     lastoccurence INTEGER | ||||
|     lastoccurence INTEGER, | ||||
|     uid VARCHAR(200) | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY calendarobjects | ||||
| @@ -40,3 +42,52 @@ CREATE UNIQUE INDEX calendarobjects_ukey | ||||
| ALTER TABLE ONLY calendarobjects | ||||
|     ADD CONSTRAINT calendarobjects_calendarid_fkey FOREIGN KEY (calendarid) REFERENCES calendars(id) | ||||
|         ON DELETE CASCADE; | ||||
|  | ||||
| CREATE TABLE calendarsubscriptions ( | ||||
|     id SERIAL NOT NULL, | ||||
|     uri VARCHAR(200) NOT NULL, | ||||
|     principaluri VARCHAR(100) NOT NULL, | ||||
|     source TEXT, | ||||
|     displayname VARCHAR(100), | ||||
|     refreshrate VARCHAR(10), | ||||
|     calendarorder INTEGER NOT NULL DEFAULT 0, | ||||
|     calendarcolor VARCHAR(10), | ||||
|     striptodos SMALLINT NULL, | ||||
|     stripalarms SMALLINT NULL, | ||||
|     stripattachments SMALLINT NULL, | ||||
|     lastmodified INTEGER | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY calendarsubscriptions | ||||
|     ADD CONSTRAINT calendarsubscriptions_pkey PRIMARY KEY (id); | ||||
|  | ||||
| CREATE UNIQUE INDEX calendarsubscriptions_ukey | ||||
|     ON calendarsubscriptions USING btree (principaluri, uri); | ||||
|  | ||||
| CREATE TABLE calendarchanges ( | ||||
|     id SERIAL NOT NULL, | ||||
|     uri VARCHAR(200) NOT NULL, | ||||
|     synctoken INTEGER NOT NULL, | ||||
|     calendarid INTEGER NOT NULL, | ||||
|     operation SMALLINT NOT NULL DEFAULT 0 | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY calendarchanges | ||||
|     ADD CONSTRAINT calendarchanges_pkey PRIMARY KEY (id); | ||||
|  | ||||
| CREATE INDEX calendarchanges_calendarid_synctoken_ix | ||||
|     ON calendarchanges USING btree (calendarid, synctoken); | ||||
|  | ||||
| ALTER TABLE ONLY calendarchanges | ||||
|     ADD CONSTRAINT calendarchanges_calendar_fk FOREIGN KEY (calendarid) REFERENCES calendars(id) | ||||
|         ON DELETE CASCADE; | ||||
|  | ||||
| CREATE TABLE schedulingobjects ( | ||||
|     id SERIAL NOT NULL, | ||||
|     principaluri VARCHAR(255), | ||||
|     calendardata BYTEA, | ||||
|     uri VARCHAR(200), | ||||
|     lastmodified INTEGER, | ||||
|     etag VARCHAR(32), | ||||
|     size INTEGER NOT NULL | ||||
| ); | ||||
|   | ||||
							
								
								
									
										12
									
								
								vendor/sabre/dav/examples/sql/pgsql.locks.sql
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/sabre/dav/examples/sql/pgsql.locks.sql
									
									
									
									
										vendored
									
									
								
							| @@ -4,10 +4,16 @@ CREATE TABLE locks ( | ||||
|     timeout INTEGER, | ||||
|     created INTEGER, | ||||
|     token VARCHAR(100), | ||||
|     scope smallint, | ||||
|     depth smallint, | ||||
|     uri text | ||||
|     scope SMALLINT, | ||||
|     depth SMALLINT, | ||||
|     uri TEXT | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY locks | ||||
|     ADD CONSTRAINT locks_pkey PRIMARY KEY (id); | ||||
|  | ||||
| CREATE INDEX locks_token_ix | ||||
|     ON locks USING btree (token); | ||||
|  | ||||
| CREATE INDEX locks_uri_ix | ||||
|     ON locks USING btree (uri); | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| CREATE TABLE principals ( | ||||
|     id SERIAL NOT NULL, | ||||
|     uri VARCHAR(100) NOT NULL, | ||||
|     uri VARCHAR(200) NOT NULL, | ||||
|     email VARCHAR(80), | ||||
|     displayname VARCHAR(80), | ||||
|     vcardurl VARCHAR(255) | ||||
|     displayname VARCHAR(80) | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY principals | ||||
| @@ -28,10 +27,9 @@ ALTER TABLE ONLY groupmembers | ||||
|     ADD CONSTRAINT groupmembers_principal_id_fkey FOREIGN KEY (principal_id) REFERENCES principals(id) | ||||
|         ON DELETE CASCADE; | ||||
|  | ||||
| -- Is this correct correct link ... or not? | ||||
| -- ALTER TABLE ONLY groupmembers | ||||
| --     ADD CONSTRAINT groupmembers_member_id_id_fkey FOREIGN KEY (member_id) REFERENCES users(id) | ||||
| --         ON DELETE CASCADE; | ||||
| ALTER TABLE ONLY groupmembers | ||||
|     ADD CONSTRAINT groupmembers_member_id_id_fkey FOREIGN KEY (member_id) REFERENCES principals(id) | ||||
|         ON DELETE CASCADE; | ||||
|  | ||||
| INSERT INTO principals (uri,email,displayname) VALUES | ||||
| ('principals/admin', 'admin@example.org','Administrator'), | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| CREATE TABLE users ( | ||||
|     id SERIAL NOT NULL, | ||||
|     username VARCHAR(50), | ||||
|     digesta1 VARCHAR(32), | ||||
|     UNIQUE(username) | ||||
|     digesta1 VARCHAR(32) | ||||
| ); | ||||
|  | ||||
| ALTER TABLE ONLY users | ||||
|   | ||||
| @@ -1,17 +1,28 @@ | ||||
| CREATE TABLE addressbooks ( | ||||
|     id integer primary key asc, | ||||
|     principaluri text, | ||||
|     id integer primary key asc NOT NULL, | ||||
|     principaluri text NOT NULL, | ||||
|     displayname text, | ||||
|     uri text, | ||||
|     uri text NOT NULL, | ||||
|     description text, | ||||
| 	ctag integer | ||||
|     synctoken integer DEFAULT 1 NOT NULL | ||||
| ); | ||||
|  | ||||
| CREATE TABLE cards ( | ||||
| 	id integer primary key asc, | ||||
|     addressbookid integer, | ||||
|     id integer primary key asc NOT NULL, | ||||
|     addressbookid integer NOT NULL, | ||||
|     carddata blob, | ||||
|     uri text, | ||||
|     lastmodified integer | ||||
|     uri text NOT NULL, | ||||
|     lastmodified integer, | ||||
|     etag text, | ||||
|     size integer | ||||
| ); | ||||
|  | ||||
| CREATE TABLE addressbookchanges ( | ||||
|     id integer primary key asc NOT NULL, | ||||
|     uri text, | ||||
|     synctoken integer NOT NULL, | ||||
|     addressbookid integer NOT NULL, | ||||
|     operation integer NOT NULL | ||||
| ); | ||||
|  | ||||
| CREATE INDEX addressbookid_synctoken ON addressbookchanges (addressbookid, synctoken); | ||||
|   | ||||
| @@ -1,26 +1,64 @@ | ||||
| CREATE TABLE calendarobjects ( | ||||
|     id integer primary key asc, | ||||
|     calendardata blob, | ||||
|     uri text, | ||||
|     calendarid integer, | ||||
|     lastmodified integer, | ||||
|     etag text, | ||||
|     size integer, | ||||
|     id integer primary key asc NOT NULL, | ||||
|     calendardata blob NOT NULL, | ||||
|     uri text NOT NULL, | ||||
|     calendarid integer NOT NULL, | ||||
|     lastmodified integer NOT NULL, | ||||
|     etag text NOT NULL, | ||||
|     size integer NOT NULL, | ||||
|     componenttype text, | ||||
|     firstoccurence integer, | ||||
|     lastoccurence integer | ||||
|     lastoccurence integer, | ||||
|     uid text | ||||
| ); | ||||
|  | ||||
| CREATE TABLE calendars ( | ||||
|     id integer primary key asc, | ||||
|     principaluri text, | ||||
|     id integer primary key asc NOT NULL, | ||||
|     principaluri text NOT NULL, | ||||
|     displayname text, | ||||
|     uri text, | ||||
|     ctag integer, | ||||
|     uri text NOT NULL, | ||||
|     synctoken integer DEFAULT 1 NOT NULL, | ||||
|     description text, | ||||
|     calendarorder integer, | ||||
|     calendarcolor text, | ||||
|     timezone text, | ||||
|     components text, | ||||
|     components text NOT NULL, | ||||
|     transparent bool | ||||
| ); | ||||
|  | ||||
| CREATE TABLE calendarchanges ( | ||||
|     id integer primary key asc NOT NULL, | ||||
|     uri text, | ||||
|     synctoken integer NOT NULL, | ||||
|     calendarid integer NOT NULL, | ||||
|     operation integer NOT NULL | ||||
| ); | ||||
|  | ||||
| CREATE INDEX calendarid_synctoken ON calendarchanges (calendarid, synctoken); | ||||
|  | ||||
| CREATE TABLE calendarsubscriptions ( | ||||
|     id integer primary key asc NOT NULL, | ||||
|     uri text NOT NULL, | ||||
|     principaluri text NOT NULL, | ||||
|     source text NOT NULL, | ||||
|     displayname text, | ||||
|     refreshrate text, | ||||
|     calendarorder integer, | ||||
|     calendarcolor text, | ||||
|     striptodos bool, | ||||
|     stripalarms bool, | ||||
|     stripattachments bool, | ||||
|     lastmodified int | ||||
| ); | ||||
|  | ||||
| CREATE TABLE schedulingobjects ( | ||||
|     id integer primary key asc NOT NULL, | ||||
|     principaluri text NOT NULL, | ||||
|     calendardata blob, | ||||
|     uri text NOT NULL, | ||||
|     lastmodified integer, | ||||
|     etag text NOT NULL, | ||||
|     size integer NOT NULL | ||||
| ); | ||||
|  | ||||
| CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| BEGIN TRANSACTION; | ||||
| CREATE TABLE locks ( | ||||
| 	id integer primary key asc, | ||||
| 	id integer primary key asc NOT NULL, | ||||
| 	owner text, | ||||
| 	timeout integer, | ||||
| 	created integer, | ||||
|   | ||||
| @@ -1,16 +1,15 @@ | ||||
| CREATE TABLE principals ( | ||||
|     id INTEGER PRIMARY KEY ASC, | ||||
|     uri TEXT, | ||||
|     id INTEGER PRIMARY KEY ASC NOT NULL, | ||||
|     uri TEXT NOT NULL, | ||||
|     email TEXT, | ||||
|     displayname TEXT, | ||||
|     vcardurl TEXT, | ||||
|     UNIQUE(uri) | ||||
| ); | ||||
|  | ||||
| CREATE TABLE groupmembers ( | ||||
|     id INTEGER PRIMARY KEY ASC, | ||||
|     principal_id INTEGER, | ||||
|     member_id INTEGER, | ||||
|     id INTEGER PRIMARY KEY ASC NOT NULL, | ||||
|     principal_id INTEGER NOT NULL, | ||||
|     member_id INTEGER NOT NULL, | ||||
|     UNIQUE(principal_id, member_id) | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| CREATE TABLE users ( | ||||
| 	id integer primary key asc, | ||||
| 	username TEXT, | ||||
| 	digesta1 TEXT, | ||||
| 	id integer primary key asc NOT NULL, | ||||
| 	username TEXT NOT NULL, | ||||
| 	digesta1 TEXT NOT NULL, | ||||
| 	UNIQUE(username) | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -23,10 +23,6 @@ | ||||
|     # This is also to prevent high memory usage | ||||
|     php_flag always_populate_raw_post_data off | ||||
|  | ||||
|     # This is almost a given, but magic quotes is *still* on on some | ||||
|     # linux distributions | ||||
|     php_flag magic_quotes_gpc off | ||||
|  | ||||
|     # SabreDAV is not compatible with mbstring function overloading | ||||
|     php_flag mbstring.func_overload off | ||||
|  | ||||
|   | ||||
							
								
								
									
										226
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/AbstractBackend.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/AbstractBackend.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,226 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Backend; | ||||
|  | ||||
| use Sabre\VObject; | ||||
| use Sabre\CalDAV; | ||||
|  | ||||
| /** | ||||
|  * Abstract Calendaring backend. Extend this class to create your own backends. | ||||
|  * | ||||
|  * Checkout the BackendInterface for all the methods that must be implemented. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| abstract class AbstractBackend implements BackendInterface { | ||||
|  | ||||
|     /** | ||||
|      * Updates properties for a calendar. | ||||
|      * | ||||
|      * The list of mutations is stored in a Sabre\DAV\PropPatch object. | ||||
|      * To do the actual updates, you must tell this object which properties | ||||
|      * you're going to process with the handle() method. | ||||
|      * | ||||
|      * Calling the handle method is like telling the PropPatch object "I | ||||
|      * promise I can handle updating this property". | ||||
|      * | ||||
|      * Read the PropPatch documenation for more info and examples. | ||||
|      * | ||||
|      * @param string $path | ||||
|      * @param \Sabre\DAV\PropPatch $propPatch | ||||
|      * @return void | ||||
|      */ | ||||
|     function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of calendar objects. | ||||
|      * | ||||
|      * This method should work identical to getCalendarObject, but instead | ||||
|      * return all the calendar objects in the list as an array. | ||||
|      * | ||||
|      * If the backend supports this, it may allow for some speed-ups. | ||||
|      * | ||||
|      * @param mixed $calendarId | ||||
|      * @param array $uris | ||||
|      * @return array | ||||
|      */ | ||||
|     function getMultipleCalendarObjects($calendarId, array $uris) { | ||||
|  | ||||
|         return array_map(function($uri) use ($calendarId) { | ||||
|             return $this->getCalendarObject($calendarId, $uri); | ||||
|         }, $uris); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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. | ||||
|      * | ||||
|      * Note that it is extremely likely that getCalendarObject for every path | ||||
|      * returned from this method will be called almost immediately after. You | ||||
|      * may want to anticipate this to speed up these requests. | ||||
|      * | ||||
|      * This method provides a default implementation, which parses *all* the | ||||
|      * iCalendar objects in the specified calendar. | ||||
|      * | ||||
|      * This default may well be good enough for personal use, and calendars | ||||
|      * that aren't very large. But if you anticipate high usage, big calendars | ||||
|      * or high loads, you are strongly adviced to optimize certain paths. | ||||
|      * | ||||
|      * The best way to do so is override this method and to optimize | ||||
|      * specifically for 'common filters'. | ||||
|      * | ||||
|      * Requests that are extremely common are: | ||||
|      *   * requests for just VEVENTS | ||||
|      *   * requests for just VTODO | ||||
|      *   * requests with a time-range-filter on either VEVENT or VTODO. | ||||
|      * | ||||
|      * ..and combinations of these requests. It may not be worth it to try to | ||||
|      * handle every possible situation and just rely on the (relatively | ||||
|      * easy to use) CalendarQueryValidator to handle the rest. | ||||
|      * | ||||
|      * Note that especially time-range-filters may be difficult to parse. A | ||||
|      * time-range filter specified on a VEVENT must for instance also handle | ||||
|      * recurrence rules correctly. | ||||
|      * A good example of how to interprete all these filters can also simply | ||||
|      * be found in \Sabre\CalDAV\CalendarQueryFilter. This class is as correct | ||||
|      * as possible, so it gives you a good idea on what type of stuff you need | ||||
|      * to think of. | ||||
|      * | ||||
|      * @param mixed $calendarId | ||||
|      * @param array $filters | ||||
|      * @return array | ||||
|      */ | ||||
|     function calendarQuery($calendarId, array $filters) { | ||||
|  | ||||
|         $result = []; | ||||
|         $objects = $this->getCalendarObjects($calendarId); | ||||
|  | ||||
|         foreach ($objects as $object) { | ||||
|  | ||||
|             if ($this->validateFilterForObject($object, $filters)) { | ||||
|                 $result[] = $object['uri']; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method validates if a filter (as passed to calendarQuery) matches | ||||
|      * the given object. | ||||
|      * | ||||
|      * @param array $object | ||||
|      * @param array $filters | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function validateFilterForObject(array $object, array $filters) { | ||||
|  | ||||
|         // Unfortunately, setting the 'calendardata' here is optional. If | ||||
|         // it was excluded, we actually need another call to get this as | ||||
|         // well. | ||||
|         if (!isset($object['calendardata'])) { | ||||
|             $object = $this->getCalendarObject($object['calendarid'], $object['uri']); | ||||
|         } | ||||
|  | ||||
|         $vObject = VObject\Reader::read($object['calendardata']); | ||||
|  | ||||
|         $validator = new CalDAV\CalendarQueryValidator(); | ||||
|         $result = $validator->validate($vObject, $filters); | ||||
|  | ||||
|         // Destroy circular references so PHP will GC the object. | ||||
|         $vObject->destroy(); | ||||
|  | ||||
|         return $result; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Searches through all of a users calendars and calendar objects to find | ||||
|      * an object with a specific UID. | ||||
|      * | ||||
|      * This method should return the path to this object, relative to the | ||||
|      * calendar home, so this path usually only contains two parts: | ||||
|      * | ||||
|      * calendarpath/objectpath.ics | ||||
|      * | ||||
|      * If the uid is not found, return null. | ||||
|      * | ||||
|      * This method should only consider * objects that the principal owns, so | ||||
|      * any calendars owned by other principals that also appear in this | ||||
|      * collection should be ignored. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @param string $uid | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getCalendarObjectByUID($principalUri, $uid) { | ||||
|  | ||||
|         // Note: this is a super slow naive implementation of this method. You | ||||
|         // are highly recommended to optimize it, if your backend allows it. | ||||
|         foreach ($this->getCalendarsForUser($principalUri) as $calendar) { | ||||
|  | ||||
|             // We must ignore calendars owned by other principals. | ||||
|             if ($calendar['principaluri'] !== $principalUri) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // Ignore calendars that are shared. | ||||
|             if (isset($calendar['{http://sabredav.org/ns}owner-principal']) && $calendar['{http://sabredav.org/ns}owner-principal'] !== $principalUri) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             $results = $this->calendarQuery( | ||||
|                 $calendar['id'], | ||||
|                 [ | ||||
|                     'name'         => 'VCALENDAR', | ||||
|                     'prop-filters' => [], | ||||
|                     'comp-filters' => [ | ||||
|                         [ | ||||
|                             'name'           => 'VEVENT', | ||||
|                             'is-not-defined' => false, | ||||
|                             'time-range'     => null, | ||||
|                             'comp-filters'   => [], | ||||
|                             'prop-filters'   => [ | ||||
|                                 [ | ||||
|                                     'name'           => 'UID', | ||||
|                                     'is-not-defined' => false, | ||||
|                                     'time-range'     => null, | ||||
|                                     'text-match'     => [ | ||||
|                                         'value'            => $uid, | ||||
|                                         'negate-condition' => false, | ||||
|                                         'collation'        => 'i;octet', | ||||
|                                     ], | ||||
|                                     'param-filters' => [], | ||||
|                                 ], | ||||
|                             ] | ||||
|                         ] | ||||
|                     ], | ||||
|                 ] | ||||
|             ); | ||||
|             if ($results) { | ||||
|                 // We have a match | ||||
|                 return $calendar['uri'] . '/' . $results[0]; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -5,7 +5,7 @@ namespace Sabre\CalDAV\Backend; | ||||
| /** | ||||
|  * Every CalDAV backend must at least implement this interface. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -17,7 +17,7 @@ interface BackendInterface { | ||||
|      * Every project is an array with the following keys: | ||||
|      *  * id, a unique id that will be used by other functions to modify the | ||||
|      *    calendar. This can be the same as the uri or a database key. | ||||
|      *  * uri, which the basename of the uri with which the calendar is | ||||
|      *  * uri, which is the basename of the uri with which the calendar is | ||||
|      *    accessed. | ||||
|      *  * principaluri. The owner of the calendar. Almost always the same as | ||||
|      *    principalUri passed to this method. | ||||
| @@ -25,82 +25,74 @@ interface BackendInterface { | ||||
|      * Furthermore it can contain webdav properties in clark notation. A very | ||||
|      * common one is '{DAV:}displayname'. | ||||
|      * | ||||
|      * Many clients also require: | ||||
|      * {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set | ||||
|      * For this property, you can just return an instance of | ||||
|      * Sabre\CalDAV\Property\SupportedCalendarComponentSet. | ||||
|      * | ||||
|      * If you return {http://sabredav.org/ns}read-only and set the value to 1, | ||||
|      * ACL will automatically be put in read-only mode. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getCalendarsForUser($principalUri); | ||||
|     function getCalendarsForUser($principalUri); | ||||
| 
 | ||||
|     /** | ||||
|      * Creates a new calendar for a principal. | ||||
|      * | ||||
|      * If the creation was a success, an id must be returned that can be used to reference | ||||
|      * this calendar in other methods, such as updateCalendar. | ||||
|      * If the creation was a success, an id must be returned that can be used to | ||||
|      * reference this calendar in other methods, such as updateCalendar. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @param string $calendarUri | ||||
|      * @param array $properties | ||||
|      * @return void | ||||
|      */ | ||||
|     public function createCalendar($principalUri,$calendarUri,array $properties); | ||||
|     function createCalendar($principalUri, $calendarUri, array $properties); | ||||
| 
 | ||||
|     /** | ||||
|      * Updates properties for a calendar. | ||||
|      * | ||||
|      * The mutations array uses the propertyName in clark-notation as key, | ||||
|      * and the array value for the property value. In the case a property | ||||
|      * should be deleted, the property value will be null. | ||||
|      * The list of mutations is stored in a Sabre\DAV\PropPatch object. | ||||
|      * To do the actual updates, you must tell this object which properties | ||||
|      * you're going to process with the handle() method. | ||||
|      * | ||||
|      * This method must be atomic. If one property cannot be changed, the | ||||
|      * entire operation must fail. | ||||
|      * Calling the handle method is like telling the PropPatch object "I
 | ||||
|      * promise I can handle updating this property".
 | ||||
|      * | ||||
|      * If the operation was successful, true can be returned. | ||||
|      * If the operation failed, false can be returned. | ||||
|      * Read the PropPatch documentation for more info and examples. | ||||
|      * | ||||
|      * Deletion of a non-existent property is always successful. | ||||
|      * | ||||
|      * Lastly, it is optional to return detailed information about any | ||||
|      * failures. In this case an array should be returned with the following | ||||
|      * structure: | ||||
|      * | ||||
|      * array( | ||||
|      *   403 => array( | ||||
|      *      '{DAV:}displayname' => null, | ||||
|      *   ), | ||||
|      *   424 => array( | ||||
|      *      '{DAV:}owner' => null, | ||||
|      *   ) | ||||
|      * ) | ||||
|      * | ||||
|      * In this example it was forbidden to update {DAV:}displayname. | ||||
|      * (403 Forbidden), which in turn also caused {DAV:}owner to fail | ||||
|      * (424 Failed Dependency) because the request needs to be atomic. | ||||
|      * | ||||
|      * @param mixed $calendarId | ||||
|      * @param array $mutations | ||||
|      * @return bool|array | ||||
|      * @param string $path | ||||
|      * @param \Sabre\DAV\PropPatch $propPatch | ||||
|      * @return void | ||||
|      */ | ||||
|     public function updateCalendar($calendarId, array $mutations); | ||||
|     function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch); | ||||
| 
 | ||||
|     /** | ||||
|      * Delete a calendar and all it's objects | ||||
|      * Delete a calendar and all its objects | ||||
|      * | ||||
|      * @param mixed $calendarId | ||||
|      * @return void | ||||
|      */ | ||||
|     public function deleteCalendar($calendarId); | ||||
|     function deleteCalendar($calendarId); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns all calendar objects within a calendar. | ||||
|      * | ||||
|      * Every item contains an array with the following keys: | ||||
|      *   * id - unique identifier which will be used for subsequent updates | ||||
|      *   * calendardata - The iCalendar-compatible calendar data | ||||
|      *   * uri - a unique key which will be used to construct the uri. This can be any arbitrary string. | ||||
|      *   * uri - a unique key which will be used to construct the uri. This can | ||||
|      *     be any arbitrary string, but making sure it ends with '.ics' is a | ||||
|      *     good idea. This is only the basename, or filename, not the full | ||||
|      *     path. | ||||
|      *   * lastmodified - a timestamp of the last modification time | ||||
|      *   * etag - An arbitrary string, surrounded by double-quotes. (e.g.: | ||||
|      *   '"abcdef"') | ||||
|      *   * calendarid - The calendarid as it was passed to this function. | ||||
|      *   * size - The size of the calendar objects, in bytes. | ||||
|      *   * component - optional, a string containing the type of object, such | ||||
|      *     as 'vevent' or 'vtodo'. If specified, this will be used to populate | ||||
|      *     the Content-Type header. | ||||
|      * | ||||
|      * Note that the etag is optional, but it's highly encouraged to return for | ||||
|      * speed reasons. | ||||
| @@ -116,12 +108,14 @@ interface BackendInterface { | ||||
|      * @param mixed $calendarId | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getCalendarObjects($calendarId); | ||||
|     function getCalendarObjects($calendarId); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns information from a single calendar object, based on it's object | ||||
|      * uri. | ||||
|      * | ||||
|      * The object uri is only the basename, or filename and not a full path. | ||||
|      * | ||||
|      * The returned array must have the same keys as getCalendarObjects. The | ||||
|      * 'calendardata' object is required here though, while it's not required | ||||
|      * for getCalendarObjects. | ||||
| @@ -132,14 +126,30 @@ interface BackendInterface { | ||||
|      * @param string $objectUri | ||||
|      * @return array|null | ||||
|      */ | ||||
|     public function getCalendarObject($calendarId,$objectUri); | ||||
|     function getCalendarObject($calendarId, $objectUri); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a list of calendar objects. | ||||
|      * | ||||
|      * This method should work identical to getCalendarObject, but instead | ||||
|      * return all the calendar objects in the list as an array. | ||||
|      * | ||||
|      * If the backend supports this, it may allow for some speed-ups. | ||||
|      * | ||||
|      * @param mixed $calendarId | ||||
|      * @param array $uris | ||||
|      * @return array | ||||
|      */ | ||||
|     function getMultipleCalendarObjects($calendarId, array $uris); | ||||
| 
 | ||||
|     /** | ||||
|      * Creates a new calendar object. | ||||
|      * | ||||
|      * It is possible return an etag from this function, which will be used in | ||||
|      * the response to this PUT request. Note that the ETag must be surrounded | ||||
|      * by double-quotes. | ||||
|      * The object uri is only the basename, or filename and not a full path. | ||||
|      * | ||||
|      * It is possible to return an etag from this function, which will be used | ||||
|      * in the response to this PUT request. Note that the ETag must be | ||||
|      * surrounded by double-quotes. | ||||
|      * | ||||
|      * However, you should only really return this ETag if you don't mangle the | ||||
|      * calendar-data. If the result of a subsequent GET to this object is not | ||||
| @@ -150,11 +160,13 @@ interface BackendInterface { | ||||
|      * @param string $calendarData | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function createCalendarObject($calendarId,$objectUri,$calendarData); | ||||
|     function createCalendarObject($calendarId, $objectUri, $calendarData); | ||||
| 
 | ||||
|     /** | ||||
|      * Updates an existing calendarobject, based on it's uri. | ||||
|      * | ||||
|      * The object uri is only the basename, or filename and not a full path. | ||||
|      * | ||||
|      * It is possible return an etag from this function, which will be used in | ||||
|      * the response to this PUT request. Note that the ETag must be surrounded | ||||
|      * by double-quotes. | ||||
| @@ -168,16 +180,18 @@ interface BackendInterface { | ||||
|      * @param string $calendarData | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function updateCalendarObject($calendarId,$objectUri,$calendarData); | ||||
|     function updateCalendarObject($calendarId, $objectUri, $calendarData); | ||||
| 
 | ||||
|     /** | ||||
|      * Deletes an existing calendar object. | ||||
|      * | ||||
|      * The object uri is only the basename, or filename and not a full path. | ||||
|      * | ||||
|      * @param mixed $calendarId | ||||
|      * @param string $objectUri | ||||
|      * @return void | ||||
|      */ | ||||
|     public function deleteCalendarObject($calendarId,$objectUri); | ||||
|     function deleteCalendarObject($calendarId, $objectUri); | ||||
| 
 | ||||
|     /** | ||||
|      * Performs a calendar-query on the contents of this calendar. | ||||
| @@ -228,6 +242,27 @@ interface BackendInterface { | ||||
|      * @param array $filters | ||||
|      * @return array | ||||
|      */ | ||||
|     public function calendarQuery($calendarId, array $filters); | ||||
|     function calendarQuery($calendarId, array $filters); | ||||
| 
 | ||||
|     /** | ||||
|      * Searches through all of a users calendars and calendar objects to find | ||||
|      * an object with a specific UID. | ||||
|      * | ||||
|      * This method should return the path to this object, relative to the | ||||
|      * calendar home, so this path usually only contains two parts: | ||||
|      * | ||||
|      * calendarpath/objectpath.ics | ||||
|      * | ||||
|      * If the uid is not found, return null. | ||||
|      * | ||||
|      * This method should only consider * objects that the principal owns, so | ||||
|      * any calendars owned by other principals that also appear in this | ||||
|      * collection should be ignored. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @param string $uid | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getCalendarObjectByUID($principalUri, $uid); | ||||
| 
 | ||||
| } | ||||
| @@ -2,6 +2,8 @@ | ||||
| 
 | ||||
| namespace Sabre\CalDAV\Backend; | ||||
| 
 | ||||
| use Sabre\CalDAV\Xml\Notification\NotificationInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Adds caldav notification support to a backend. | ||||
|  * | ||||
| @@ -16,7 +18,7 @@ namespace Sabre\CalDAV\Backend; | ||||
|  * | ||||
|  * The primary usecase is to allow for calendar-sharing. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -25,13 +27,10 @@ interface NotificationSupport extends BackendInterface { | ||||
|     /** | ||||
|      * Returns a list of notifications for a given principal url. | ||||
|      * | ||||
|      * The returned array should only consist of implementations of | ||||
|      * \Sabre\CalDAV\Notifications\INotificationType. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @return array | ||||
|      * @return NotificationInterface[] | ||||
|      */ | ||||
|     public function getNotificationsForPrincipal($principalUri); | ||||
|     function getNotificationsForPrincipal($principalUri); | ||||
| 
 | ||||
|     /** | ||||
|      * This deletes a specific notifcation. | ||||
| @@ -39,9 +38,9 @@ interface NotificationSupport extends BackendInterface { | ||||
|      * This may be called by a client once it deems a notification handled. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @param \Sabre\CalDAV\Notifications\INotificationType $notification | ||||
|      * @param NotificationInterface $notification | ||||
|      * @return void | ||||
|      */ | ||||
|     public function deleteNotification($principalUri, \Sabre\CalDAV\Notifications\INotificationType $notification); | ||||
|     function deleteNotification($principalUri, NotificationInterface $notification); | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										1210
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/PDO.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1210
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/PDO.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										65
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/SchedulingSupport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/SchedulingSupport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Backend; | ||||
|  | ||||
| /** | ||||
|  * Implementing this interface adds CalDAV Scheduling support to your caldav | ||||
|  * server, as defined in rfc6638. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| interface SchedulingSupport extends BackendInterface { | ||||
|  | ||||
|     /** | ||||
|      * Returns a single scheduling object for the inbox collection. | ||||
|      * | ||||
|      * The returned array should contain the following elements: | ||||
|      *   * uri - A unique basename for the object. This will be used to | ||||
|      *           construct a full uri. | ||||
|      *   * calendardata - The iCalendar object | ||||
|      *   * lastmodified - The last modification date. Can be an int for a unix | ||||
|      *                    timestamp, or a PHP DateTime object. | ||||
|      *   * etag - A unique token that must change if the object changed. | ||||
|      *   * size - The size of the object, in bytes. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @param string $objectUri | ||||
|      * @return array | ||||
|      */ | ||||
|     function getSchedulingObject($principalUri, $objectUri); | ||||
|  | ||||
|     /** | ||||
|      * Returns all scheduling objects for the inbox collection. | ||||
|      * | ||||
|      * These objects should be returned as an array. Every item in the array | ||||
|      * should follow the same structure as returned from getSchedulingObject. | ||||
|      * | ||||
|      * The main difference is that 'calendardata' is optional. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @return array | ||||
|      */ | ||||
|     function getSchedulingObjects($principalUri); | ||||
|  | ||||
|     /** | ||||
|      * Deletes a scheduling object from the inbox collection. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @param string $objectUri | ||||
|      * @return void | ||||
|      */ | ||||
|     function deleteSchedulingObject($principalUri, $objectUri); | ||||
|  | ||||
|     /** | ||||
|      * Creates a new scheduling object. This should land in a users' inbox. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @param string $objectUri | ||||
|      * @param string $objectData | ||||
|      * @return void | ||||
|      */ | ||||
|     function createSchedulingObject($principalUri, $objectUri, $objectData); | ||||
|  | ||||
| } | ||||
| @@ -70,7 +70,7 @@ namespace Sabre\CalDAV\Backend; | ||||
|  * In the case of an invite, the sharee may reply with an 'accept' or | ||||
|  * 'decline'. These are always represented by: | ||||
|  * | ||||
|  * Sabre\CalDAV\Notifications\Notification\Invite | ||||
|  * Sabre\CalDAV\Notifications\Notification\InviteReply | ||||
|  * | ||||
|  * | ||||
|  * Calendar access by sharees | ||||
| @@ -136,7 +136,7 @@ namespace Sabre\CalDAV\Backend; | ||||
|  *   * unpublished | ||||
|  * | ||||
|  * If a calendar is published, the following property should be returned | ||||
|  * for each calendar in getCalendarsForPrincipal. | ||||
|  * for each calendar in getCalendarsForUser. | ||||
|  * | ||||
|  * {http://calendarserver.org/ns/}publish-url | ||||
|  * | ||||
| @@ -157,7 +157,7 @@ namespace Sabre\CalDAV\Backend; | ||||
|  * ============================================== | ||||
|  * | ||||
|  * If Sabre\CalDAV\Property\AllowedSharingModes is returned from | ||||
|  * getCalendarsByUser, this allows the server to specify whether either sharing, | ||||
|  * getCalendarsForUser, this allows the server to specify whether either sharing, | ||||
|  * or publishing is supported. | ||||
|  * | ||||
|  * This allows a client to determine in advance which features are available, | ||||
| @@ -165,7 +165,7 @@ namespace Sabre\CalDAV\Backend; | ||||
|  * the backend, the SharingPlugin automatically injects it and assumes both | ||||
|  * features are available. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
							
								
								
									
										89
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/SubscriptionSupport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/SubscriptionSupport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Backend; | ||||
|  | ||||
| use Sabre\DAV; | ||||
|  | ||||
| /** | ||||
|  * Every CalDAV backend must at least implement this interface. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| interface SubscriptionSupport extends BackendInterface { | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of subscriptions for a principal. | ||||
|      * | ||||
|      * Every subscription is an array with the following keys: | ||||
|      *  * id, a unique id that will be used by other functions to modify the | ||||
|      *    subscription. This can be the same as the uri or a database key. | ||||
|      *  * uri. This is just the 'base uri' or 'filename' of the subscription. | ||||
|      *  * principaluri. The owner of the subscription. Almost always the same as | ||||
|      *    principalUri passed to this method. | ||||
|      * | ||||
|      * Furthermore, all the subscription info must be returned too: | ||||
|      * | ||||
|      * 1. {DAV:}displayname | ||||
|      * 2. {http://apple.com/ns/ical/}refreshrate | ||||
|      * 3. {http://calendarserver.org/ns/}subscribed-strip-todos (omit if todos | ||||
|      *    should not be stripped). | ||||
|      * 4. {http://calendarserver.org/ns/}subscribed-strip-alarms (omit if alarms | ||||
|      *    should not be stripped). | ||||
|      * 5. {http://calendarserver.org/ns/}subscribed-strip-attachments (omit if | ||||
|      *    attachments should not be stripped). | ||||
|      * 6. {http://calendarserver.org/ns/}source (Must be a | ||||
|      *     Sabre\DAV\Property\Href). | ||||
|      * 7. {http://apple.com/ns/ical/}calendar-color | ||||
|      * 8. {http://apple.com/ns/ical/}calendar-order | ||||
|      * 9. {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set | ||||
|      *    (should just be an instance of | ||||
|      *    Sabre\CalDAV\Property\SupportedCalendarComponentSet, with a bunch of | ||||
|      *    default components). | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @return array | ||||
|      */ | ||||
|     function getSubscriptionsForUser($principalUri); | ||||
|  | ||||
|     /** | ||||
|      * Creates a new subscription for a principal. | ||||
|      * | ||||
|      * If the creation was a success, an id must be returned that can be used to reference | ||||
|      * this subscription in other methods, such as updateSubscription. | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      * @param string $uri | ||||
|      * @param array $properties | ||||
|      * @return mixed | ||||
|      */ | ||||
|     function createSubscription($principalUri, $uri, array $properties); | ||||
|  | ||||
|     /** | ||||
|      * Updates a subscription | ||||
|      * | ||||
|      * The list of mutations is stored in a Sabre\DAV\PropPatch object. | ||||
|      * To do the actual updates, you must tell this object which properties | ||||
|      * you're going to process with the handle() method. | ||||
|      * | ||||
|      * Calling the handle method is like telling the PropPatch object "I | ||||
|      * promise I can handle updating this property". | ||||
|      * | ||||
|      * Read the PropPatch documenation for more info and examples. | ||||
|      * | ||||
|      * @param mixed $subscriptionId | ||||
|      * @param \Sabre\DAV\PropPatch $propPatch | ||||
|      * @return void | ||||
|      */ | ||||
|     function updateSubscription($subscriptionId, DAV\PropPatch $propPatch); | ||||
|  | ||||
|     /** | ||||
|      * Deletes a subscription. | ||||
|      * | ||||
|      * @param mixed $subscriptionId | ||||
|      * @return void | ||||
|      */ | ||||
|     function deleteSubscription($subscriptionId); | ||||
|  | ||||
| } | ||||
							
								
								
									
										81
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/SyncSupport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								vendor/sabre/dav/lib/CalDAV/Backend/SyncSupport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Backend; | ||||
|  | ||||
| /** | ||||
|  * WebDAV-sync support for CalDAV backends. | ||||
|  * | ||||
|  * In order for backends to advertise support for WebDAV-sync, this interface | ||||
|  * must be implemented. | ||||
|  * | ||||
|  * Implementing this can result in a significant reduction of bandwidth and CPU | ||||
|  * time. | ||||
|  * | ||||
|  * For this to work, you _must_ return a {http://sabredav.org/ns}sync-token | ||||
|  * property from getCalendarsFromUser. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| interface SyncSupport extends BackendInterface { | ||||
|  | ||||
|     /** | ||||
|      * The getChanges method returns all the changes that have happened, since | ||||
|      * the specified syncToken in the specified calendar. | ||||
|      * | ||||
|      * This function should return an array, such as the following: | ||||
|      * | ||||
|      * [ | ||||
|      *   'syncToken' => 'The current synctoken', | ||||
|      *   'added'   => [ | ||||
|      *      'new.txt', | ||||
|      *   ], | ||||
|      *   'modified'   => [ | ||||
|      *      'modified.txt', | ||||
|      *   ], | ||||
|      *   'deleted' => [ | ||||
|      *      'foo.php.bak', | ||||
|      *      'old.txt' | ||||
|      *   ] | ||||
|      * ); | ||||
|      * | ||||
|      * The returned syncToken property should reflect the *current* syncToken | ||||
|      * of the calendar, as reported in the {http://sabredav.org/ns}sync-token | ||||
|      * property This is * needed here too, to ensure the operation is atomic. | ||||
|      * | ||||
|      * If the $syncToken argument is specified as null, this is an initial | ||||
|      * sync, and all members should be reported. | ||||
|      * | ||||
|      * The modified property is an array of nodenames that have changed since | ||||
|      * the last token. | ||||
|      * | ||||
|      * The deleted property is an array with nodenames, that have been deleted | ||||
|      * from collection. | ||||
|      * | ||||
|      * The $syncLevel argument is basically the 'depth' of the report. If it's | ||||
|      * 1, you only have to report changes that happened only directly in | ||||
|      * immediate descendants. If it's 2, it should also include changes from | ||||
|      * the nodes below the child collections. (grandchildren) | ||||
|      * | ||||
|      * The $limit argument allows a client to specify how many results should | ||||
|      * be returned at most. If the limit is not specified, it should be treated | ||||
|      * as infinite. | ||||
|      * | ||||
|      * If the limit (infinite or not) is higher than you're willing to return, | ||||
|      * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception. | ||||
|      * | ||||
|      * If the syncToken is expired (due to data cleanup) or unknown, you must | ||||
|      * return null. | ||||
|      * | ||||
|      * The limit is 'suggestive'. You are free to ignore it. | ||||
|      * | ||||
|      * @param string $calendarId | ||||
|      * @param string $syncToken | ||||
|      * @param int $syncLevel | ||||
|      * @param int $limit | ||||
|      * @return array | ||||
|      */ | ||||
|     function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null); | ||||
|  | ||||
| } | ||||
							
								
								
									
										527
									
								
								vendor/sabre/dav/lib/CalDAV/Calendar.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										527
									
								
								vendor/sabre/dav/lib/CalDAV/Calendar.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,527 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV; | ||||
|  | ||||
| use Sabre\DAV; | ||||
| use Sabre\DAVACL; | ||||
| use Sabre\DAV\PropPatch; | ||||
|  | ||||
| /** | ||||
|  * This object represents a CalDAV calendar. | ||||
|  * | ||||
|  * A calendar can contain multiple TODO and or Events. These are represented | ||||
|  * as \Sabre\CalDAV\CalendarObject objects. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, DAV\IMultiGet { | ||||
|  | ||||
|     /** | ||||
|      * This is an array with calendar information | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $calendarInfo; | ||||
|  | ||||
|     /** | ||||
|      * CalDAV backend | ||||
|      * | ||||
|      * @var Backend\BackendInterface | ||||
|      */ | ||||
|     protected $caldavBackend; | ||||
|  | ||||
|     /** | ||||
|      * Constructor | ||||
|      * | ||||
|      * @param Backend\BackendInterface $caldavBackend | ||||
|      * @param array $calendarInfo | ||||
|      */ | ||||
|     function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo) { | ||||
|  | ||||
|         $this->caldavBackend = $caldavBackend; | ||||
|         $this->calendarInfo = $calendarInfo; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the name of the calendar | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     function getName() { | ||||
|  | ||||
|         return $this->calendarInfo['uri']; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Updates properties on this node. | ||||
|      * | ||||
|      * This method received a PropPatch object, which contains all the | ||||
|      * information about the update. | ||||
|      * | ||||
|      * To update specific properties, call the 'handle' method on this object. | ||||
|      * Read the PropPatch documentation for more information. | ||||
|      * | ||||
|      * @param PropPatch $propPatch | ||||
|      * @return void | ||||
|      */ | ||||
|     function propPatch(PropPatch $propPatch) { | ||||
|  | ||||
|         return $this->caldavBackend->updateCalendar($this->calendarInfo['id'], $propPatch); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the list of properties | ||||
|      * | ||||
|      * @param array $requestedProperties | ||||
|      * @return array | ||||
|      */ | ||||
|     function getProperties($requestedProperties) { | ||||
|  | ||||
|         $response = []; | ||||
|  | ||||
|         foreach ($this->calendarInfo as $propName => $propValue) { | ||||
|  | ||||
|             if ($propName[0] === '{') | ||||
|                 $response[$propName] = $this->calendarInfo[$propName]; | ||||
|  | ||||
|         } | ||||
|         return $response; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a calendar object | ||||
|      * | ||||
|      * The contained calendar objects are for example Events or Todo's. | ||||
|      * | ||||
|      * @param string $name | ||||
|      * @return \Sabre\CalDAV\ICalendarObject | ||||
|      */ | ||||
|     function getChild($name) { | ||||
|  | ||||
|         $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name); | ||||
|  | ||||
|         if (!$obj) throw new DAV\Exception\NotFound('Calendar object not found'); | ||||
|  | ||||
|         $obj['acl'] = $this->getChildACL(); | ||||
|  | ||||
|         return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the full list of calendar objects | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     function getChildren() { | ||||
|  | ||||
|         $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']); | ||||
|         $children = []; | ||||
|         foreach ($objs as $obj) { | ||||
|             $obj['acl'] = $this->getChildACL(); | ||||
|             $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); | ||||
|         } | ||||
|         return $children; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method receives a list of paths in it's first argument. | ||||
|      * It must return an array with Node objects. | ||||
|      * | ||||
|      * If any children are not found, you do not have to return them. | ||||
|      * | ||||
|      * @param string[] $paths | ||||
|      * @return array | ||||
|      */ | ||||
|     function getMultipleChildren(array $paths) { | ||||
|  | ||||
|         $objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths); | ||||
|         $children = []; | ||||
|         foreach ($objs as $obj) { | ||||
|             $obj['acl'] = $this->getChildACL(); | ||||
|             $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); | ||||
|         } | ||||
|         return $children; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Checks if a child-node exists. | ||||
|      * | ||||
|      * @param string $name | ||||
|      * @return bool | ||||
|      */ | ||||
|     function childExists($name) { | ||||
|  | ||||
|         $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name); | ||||
|         if (!$obj) | ||||
|             return false; | ||||
|         else | ||||
|             return true; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new directory | ||||
|      * | ||||
|      * We actually block this, as subdirectories are not allowed in calendars. | ||||
|      * | ||||
|      * @param string $name | ||||
|      * @return void | ||||
|      */ | ||||
|     function createDirectory($name) { | ||||
|  | ||||
|         throw new DAV\Exception\MethodNotAllowed('Creating collections in calendar objects is not allowed'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new file | ||||
|      * | ||||
|      * The contents of the new file must be a valid ICalendar string. | ||||
|      * | ||||
|      * @param string $name | ||||
|      * @param resource $calendarData | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function createFile($name, $calendarData = null) { | ||||
|  | ||||
|         if (is_resource($calendarData)) { | ||||
|             $calendarData = stream_get_contents($calendarData); | ||||
|         } | ||||
|         return $this->caldavBackend->createCalendarObject($this->calendarInfo['id'], $name, $calendarData); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Deletes the calendar. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     function delete() { | ||||
|  | ||||
|         $this->caldavBackend->deleteCalendar($this->calendarInfo['id']); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Renames the calendar. Note that most calendars use the | ||||
|      * {DAV:}displayname to display a name to display a name. | ||||
|      * | ||||
|      * @param string $newName | ||||
|      * @return void | ||||
|      */ | ||||
|     function setName($newName) { | ||||
|  | ||||
|         throw new DAV\Exception\MethodNotAllowed('Renaming calendars is not yet supported'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the last modification date as a unix timestamp. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     function getLastModified() { | ||||
|  | ||||
|         return null; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the owner principal | ||||
|      * | ||||
|      * This must be a url to a principal, or null if there's no owner | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getOwner() { | ||||
|  | ||||
|         return $this->calendarInfo['principaluri']; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a group principal | ||||
|      * | ||||
|      * This must be a url to a principal, or null if there's no owner | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getGroup() { | ||||
|  | ||||
|         return null; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     function getACL() { | ||||
|  | ||||
|         $acl = [ | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-read', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy', | ||||
|                 'principal' => '{DAV:}authenticated', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|  | ||||
|         ]; | ||||
|         if (empty($this->calendarInfo['{http://sabredav.org/ns}read-only'])) { | ||||
|             $acl[] = [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ]; | ||||
|             $acl[] = [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $acl; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method returns the ACL's for calendar objects in this calendar. | ||||
|      * The result of this method automatically gets passed to the | ||||
|      * calendar-object nodes in the calendar. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     function getChildACL() { | ||||
|  | ||||
|         $acl = [ | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|  | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-read', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|  | ||||
|         ]; | ||||
|         if (empty($this->calendarInfo['{http://sabredav.org/ns}read-only'])) { | ||||
|             $acl[] = [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ]; | ||||
|             $acl[] = [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ]; | ||||
|  | ||||
|         } | ||||
|         return $acl; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Updates the ACL | ||||
|      * | ||||
|      * This method will receive a list of new ACE's. | ||||
|      * | ||||
|      * @param array $acl | ||||
|      * @return void | ||||
|      */ | ||||
|     function setACL(array $acl) { | ||||
|  | ||||
|         throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the list of supported privileges for this node. | ||||
|      * | ||||
|      * The returned data structure is a list of nested privileges. | ||||
|      * See \Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple | ||||
|      * standard structure. | ||||
|      * | ||||
|      * If null is returned from this method, the default privilege set is used, | ||||
|      * which is fine for most common usecases. | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     function getSupportedPrivilegeSet() { | ||||
|  | ||||
|         $default = DAVACL\Plugin::getDefaultSupportedPrivilegeSet(); | ||||
|  | ||||
|         // We need to inject 'read-free-busy' in the tree, aggregated under | ||||
|         // {DAV:}read. | ||||
|         foreach ($default['aggregates'] as &$agg) { | ||||
|  | ||||
|             if ($agg['privilege'] !== '{DAV:}read') continue; | ||||
|  | ||||
|             $agg['aggregates'][] = [ | ||||
|                 'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy', | ||||
|             ]; | ||||
|  | ||||
|         } | ||||
|         return $default; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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. | ||||
|      * | ||||
|      * @param array $filters | ||||
|      * @return array | ||||
|      */ | ||||
|     function calendarQuery(array $filters) { | ||||
|  | ||||
|         return $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method returns the current sync-token for this collection. | ||||
|      * This can be any string. | ||||
|      * | ||||
|      * If null is returned from this function, the plugin assumes there's no | ||||
|      * sync information available. | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getSyncToken() { | ||||
|  | ||||
|         if ( | ||||
|             $this->caldavBackend instanceof Backend\SyncSupport && | ||||
|             isset($this->calendarInfo['{DAV:}sync-token']) | ||||
|         ) { | ||||
|             return $this->calendarInfo['{DAV:}sync-token']; | ||||
|         } | ||||
|         if ( | ||||
|             $this->caldavBackend instanceof Backend\SyncSupport && | ||||
|             isset($this->calendarInfo['{http://sabredav.org/ns}sync-token']) | ||||
|         ) { | ||||
|             return $this->calendarInfo['{http://sabredav.org/ns}sync-token']; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The getChanges method returns all the changes that have happened, since | ||||
|      * the specified syncToken and the current collection. | ||||
|      * | ||||
|      * This function should return an array, such as the following: | ||||
|      * | ||||
|      * [ | ||||
|      *   'syncToken' => 'The current synctoken', | ||||
|      *   'added'   => [ | ||||
|      *      'new.txt', | ||||
|      *   ], | ||||
|      *   'modified'   => [ | ||||
|      *      'modified.txt', | ||||
|      *   ], | ||||
|      *   'deleted' => [ | ||||
|      *      'foo.php.bak', | ||||
|      *      'old.txt' | ||||
|      *   ] | ||||
|      * ]; | ||||
|      * | ||||
|      * The syncToken property should reflect the *current* syncToken of the | ||||
|      * collection, as reported getSyncToken(). This is needed here too, to | ||||
|      * ensure the operation is atomic. | ||||
|      * | ||||
|      * If the syncToken is specified as null, this is an initial sync, and all | ||||
|      * members should be reported. | ||||
|      * | ||||
|      * The modified property is an array of nodenames that have changed since | ||||
|      * the last token. | ||||
|      * | ||||
|      * The deleted property is an array with nodenames, that have been deleted | ||||
|      * from collection. | ||||
|      * | ||||
|      * The second argument is basically the 'depth' of the report. If it's 1, | ||||
|      * you only have to report changes that happened only directly in immediate | ||||
|      * descendants. If it's 2, it should also include changes from the nodes | ||||
|      * below the child collections. (grandchildren) | ||||
|      * | ||||
|      * The third (optional) argument allows a client to specify how many | ||||
|      * results should be returned at most. If the limit is not specified, it | ||||
|      * should be treated as infinite. | ||||
|      * | ||||
|      * If the limit (infinite or not) is higher than you're willing to return, | ||||
|      * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception. | ||||
|      * | ||||
|      * If the syncToken is expired (due to data cleanup) or unknown, you must | ||||
|      * return null. | ||||
|      * | ||||
|      * The limit is 'suggestive'. You are free to ignore it. | ||||
|      * | ||||
|      * @param string $syncToken | ||||
|      * @param int $syncLevel | ||||
|      * @param int $limit | ||||
|      * @return array | ||||
|      */ | ||||
|     function getChanges($syncToken, $syncLevel, $limit = null) { | ||||
|  | ||||
|         if (!$this->caldavBackend instanceof Backend\SyncSupport) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return $this->caldavBackend->getChangesForCalendar( | ||||
|             $this->calendarInfo['id'], | ||||
|             $syncToken, | ||||
|             $syncLevel, | ||||
|             $limit | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -3,16 +3,24 @@ | ||||
| namespace Sabre\CalDAV; | ||||
| 
 | ||||
| use Sabre\DAV; | ||||
| use Sabre\DAV\Exception\NotFound; | ||||
| use Sabre\DAV\MkCol; | ||||
| use Sabre\DAVACL; | ||||
| use Sabre\HTTP\URLUtil; | ||||
| 
 | ||||
| /** | ||||
|  * The UserCalenders class contains all calendars associated to one user | ||||
|  * The CalendarHome represents a node that is usually in a users' | ||||
|  * calendar-homeset. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * It contains all the users' calendars, and can optionally contain a | ||||
|  * notifications collection, calendar subscriptions, a users' inbox, and a | ||||
|  * users' outbox. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
| class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
| 
 | ||||
|     /** | ||||
|      * CalDAV backend | ||||
| @@ -34,7 +42,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * @param Backend\BackendInterface $caldavBackend | ||||
|      * @param mixed $userUri | ||||
|      */ | ||||
|     public function __construct(Backend\BackendInterface $caldavBackend, $principalInfo) { | ||||
|     function __construct(Backend\BackendInterface $caldavBackend, $principalInfo) { | ||||
| 
 | ||||
|         $this->caldavBackend = $caldavBackend; | ||||
|         $this->principalInfo = $principalInfo; | ||||
| @@ -46,9 +54,9 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getName() { | ||||
|     function getName() { | ||||
| 
 | ||||
|         list(,$name) = DAV\URLUtil::splitPath($this->principalInfo['uri']); | ||||
|         list(, $name) = URLUtil::splitPath($this->principalInfo['uri']); | ||||
|         return $name; | ||||
| 
 | ||||
|     } | ||||
| @@ -59,7 +67,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * @param string $name | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setName($name) { | ||||
|     function setName($name) { | ||||
| 
 | ||||
|         throw new DAV\Exception\Forbidden(); | ||||
| 
 | ||||
| @@ -70,7 +78,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function delete() { | ||||
|     function delete() { | ||||
| 
 | ||||
|         throw new DAV\Exception\Forbidden(); | ||||
| 
 | ||||
| @@ -81,7 +89,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getLastModified() { | ||||
|     function getLastModified() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -96,7 +104,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * @param resource $data | ||||
|      * @return void | ||||
|      */ | ||||
|     public function createFile($filename, $data=null) { | ||||
|     function createFile($filename, $data = null) { | ||||
| 
 | ||||
|         throw new DAV\Exception\MethodNotAllowed('Creating new files in this collection is not supported'); | ||||
| 
 | ||||
| @@ -110,7 +118,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * @param string $filename | ||||
|      * @return void | ||||
|      */ | ||||
|     public function createDirectory($filename) { | ||||
|     function createDirectory($filename) { | ||||
| 
 | ||||
|         throw new DAV\Exception\MethodNotAllowed('Creating new collections in this collection is not supported'); | ||||
| 
 | ||||
| @@ -120,17 +128,46 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * Returns a single calendar, by name | ||||
|      * | ||||
|      * @param string $name | ||||
|      * @todo needs optimizing | ||||
|      * @return Calendar | ||||
|      */ | ||||
|     public function getChild($name) { | ||||
|     function getChild($name) { | ||||
| 
 | ||||
|         foreach($this->getChildren() as $child) { | ||||
|             if ($name==$child->getName()) | ||||
|                 return $child; | ||||
|         // Special nodes
 | ||||
|         if ($name === 'inbox' && $this->caldavBackend instanceof Backend\SchedulingSupport) { | ||||
|             return new Schedule\Inbox($this->caldavBackend, $this->principalInfo['uri']); | ||||
|         } | ||||
|         if ($name === 'outbox' && $this->caldavBackend instanceof Backend\SchedulingSupport) { | ||||
|             return new Schedule\Outbox($this->principalInfo['uri']); | ||||
|         } | ||||
|         if ($name === 'notifications' && $this->caldavBackend instanceof Backend\NotificationSupport) { | ||||
|             return new Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']); | ||||
|         } | ||||
| 
 | ||||
|         // Calendars
 | ||||
|         foreach ($this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']) as $calendar) { | ||||
|             if ($calendar['uri'] === $name) { | ||||
|                 if ($this->caldavBackend instanceof Backend\SharingSupport) { | ||||
|                     if (isset($calendar['{http://calendarserver.org/ns/}shared-url'])) { | ||||
|                         return new SharedCalendar($this->caldavBackend, $calendar); | ||||
|                     } else { | ||||
|                         return new ShareableCalendar($this->caldavBackend, $calendar); | ||||
|                     } | ||||
|                 } else { | ||||
|                     return new Calendar($this->caldavBackend, $calendar); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if ($this->caldavBackend instanceof Backend\SubscriptionSupport) { | ||||
|             foreach ($this->caldavBackend->getSubscriptionsForUser($this->principalInfo['uri']) as $subscription) { | ||||
|                 if ($subscription['uri'] === $name) { | ||||
|                     return new Subscriptions\Subscription($this->caldavBackend, $subscription); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         throw new DAV\Exception\NotFound('Calendar with name \'' . $name . '\' could not be found'); | ||||
| 
 | ||||
|         throw new NotFound('Node with name \'' . $name . '\' could not be found'); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -138,17 +175,15 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * Checks if a calendar exists. | ||||
|      * | ||||
|      * @param string $name | ||||
|      * @todo needs optimizing | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function childExists($name) { | ||||
|     function childExists($name) { | ||||
| 
 | ||||
|         foreach($this->getChildren() as $child) { | ||||
|             if ($name==$child->getName()) | ||||
|                 return true; | ||||
| 
 | ||||
|         } | ||||
|         try { | ||||
|             return !!$this->getChild($name); | ||||
|         } catch (NotFound $e) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -157,10 +192,10 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getChildren() { | ||||
|     function getChildren() { | ||||
| 
 | ||||
|         $calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']); | ||||
|         $objs = array(); | ||||
|         $objs = []; | ||||
|         foreach ($calendars as $calendar) { | ||||
|             if ($this->caldavBackend instanceof Backend\SharingSupport) { | ||||
|                 if (isset($calendar['{http://calendarserver.org/ns/}shared-url'])) { | ||||
| @@ -172,28 +207,41 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|                 $objs[] = new Calendar($this->caldavBackend, $calendar); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if ($this->caldavBackend instanceof Backend\SchedulingSupport) { | ||||
|             $objs[] = new Schedule\Inbox($this->caldavBackend, $this->principalInfo['uri']); | ||||
|             $objs[] = new Schedule\Outbox($this->principalInfo['uri']); | ||||
|         } | ||||
| 
 | ||||
|         // We're adding a notifications node, if it's supported by the backend.
 | ||||
|         if ($this->caldavBackend instanceof Backend\NotificationSupport) { | ||||
|             $objs[] = new Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']); | ||||
|         } | ||||
| 
 | ||||
|         // If the backend supports subscriptions, we'll add those as well,
 | ||||
|         if ($this->caldavBackend instanceof Backend\SubscriptionSupport) { | ||||
|             foreach ($this->caldavBackend->getSubscriptionsForUser($this->principalInfo['uri']) as $subscription) { | ||||
|                 $objs[] = new Subscriptions\Subscription($this->caldavBackend, $subscription); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $objs; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Creates a new calendar | ||||
|      * Creates a new calendar or subscription. | ||||
|      * | ||||
|      * @param string $name | ||||
|      * @param array $resourceType | ||||
|      * @param array $properties | ||||
|      * @param MkCol $mkCol | ||||
|      * @throws DAV\Exception\InvalidResourceType | ||||
|      * @return void | ||||
|      */ | ||||
|     public function createExtendedCollection($name, array $resourceType, array $properties) { | ||||
|     function createExtendedCollection($name, MkCol $mkCol) { | ||||
| 
 | ||||
|         $isCalendar = false; | ||||
|         foreach($resourceType as $rt) { | ||||
|         $isSubscription = false; | ||||
|         foreach ($mkCol->getResourceType() as $rt) { | ||||
|             switch ($rt) { | ||||
|                 case '{DAV:}collection' : | ||||
|                 case '{http://calendarserver.org/ns/}shared-owner' : | ||||
| @@ -202,15 +250,31 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|                 case '{urn:ietf:params:xml:ns:caldav}calendar' : | ||||
|                     $isCalendar = true; | ||||
|                     break; | ||||
|                 case '{http://calendarserver.org/ns/}subscribed' : | ||||
|                     $isSubscription = true; | ||||
|                     break; | ||||
|                 default : | ||||
|                     throw new DAV\Exception\InvalidResourceType('Unknown resourceType: ' . $rt); | ||||
|             } | ||||
|         } | ||||
|         if (!$isCalendar) { | ||||
|             throw new DAV\Exception\InvalidResourceType('You can only create calendars in this collection'); | ||||
| 
 | ||||
|         $properties = $mkCol->getRemainingValues(); | ||||
|         $mkCol->setRemainingResultCode(201); | ||||
| 
 | ||||
|         if ($isSubscription) { | ||||
|             if (!$this->caldavBackend instanceof Backend\SubscriptionSupport) { | ||||
|                 throw new DAV\Exception\InvalidResourceType('This backend does not support subscriptions'); | ||||
|             } | ||||
|             $this->caldavBackend->createSubscription($this->principalInfo['uri'], $name, $properties); | ||||
| 
 | ||||
|         } elseif ($isCalendar) { | ||||
|             $this->caldavBackend->createCalendar($this->principalInfo['uri'], $name, $properties); | ||||
| 
 | ||||
|         } else { | ||||
|             throw new DAV\Exception\InvalidResourceType('You can only create calendars and subscriptions in this collection'); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -220,7 +284,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getOwner() { | ||||
|     function getOwner() { | ||||
| 
 | ||||
|         return $this->principalInfo['uri']; | ||||
| 
 | ||||
| @@ -233,7 +297,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getGroup() { | ||||
|     function getGroup() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -251,36 +315,36 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getACL() { | ||||
|     function getACL() { | ||||
| 
 | ||||
|         return array( | ||||
|             array( | ||||
|         return [ | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->principalInfo['uri'], | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->principalInfo['uri'], | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->principalInfo['uri'] . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->principalInfo['uri'] . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->principalInfo['uri'] . '/calendar-proxy-read', | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             ], | ||||
| 
 | ||||
|         ); | ||||
|         ]; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -292,7 +356,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * @param array $acl | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setACL(array $acl) { | ||||
|     function setACL(array $acl) { | ||||
| 
 | ||||
|         throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported'); | ||||
| 
 | ||||
| @@ -310,7 +374,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     public function getSupportedPrivilegeSet() { | ||||
|     function getSupportedPrivilegeSet() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -329,7 +393,7 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
|      * @param string $summary A description of the reply | ||||
|      * @return null|string | ||||
|      */ | ||||
|     public function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null) { | ||||
|     function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null) { | ||||
| 
 | ||||
|         if (!$this->caldavBackend instanceof Backend\SharingSupport) { | ||||
|             throw new DAV\Exception\NotImplemented('Sharing support is not implemented by this backend.'); | ||||
| @@ -339,4 +403,28 @@ class UserCalendars implements DAV\IExtendedCollection, DAVACL\IACL { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Searches through all of a users calendars and calendar objects to find | ||||
|      * an object with a specific UID. | ||||
|      * | ||||
|      * This method should return the path to this object, relative to the | ||||
|      * calendar home, so this path usually only contains two parts: | ||||
|      * | ||||
|      * calendarpath/objectpath.ics | ||||
|      * | ||||
|      * If the uid is not found, return null. | ||||
|      * | ||||
|      * This method should only consider * objects that the principal owns, so | ||||
|      * any calendars owned by other principals that also appear in this | ||||
|      * collection should be ignored. | ||||
|      * | ||||
|      * @param string $uid | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getCalendarObjectByUID($uid) { | ||||
| 
 | ||||
|         return $this->caldavBackend->getCalendarObjectByUID($this->principalInfo['uri'], $uid); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @@ -5,7 +5,7 @@ namespace Sabre\CalDAV; | ||||
| /** | ||||
|  * The CalendarObject represents a single VEVENT or VTODO within a Calendar. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -35,17 +35,25 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|     /** | ||||
|      * Constructor | ||||
|      * | ||||
|      * The following properties may be passed within $objectData: | ||||
|      * | ||||
|      *   * calendarid - This must refer to a calendarid from a caldavBackend | ||||
|      *   * uri - A unique uri. Only the 'basename' must be passed. | ||||
|      *   * 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. | ||||
|      * | ||||
|      * @param Backend\BackendInterface $caldavBackend | ||||
|      * @param array $calendarInfo | ||||
|      * @param array $objectData | ||||
|      */ | ||||
|     public function __construct(Backend\BackendInterface $caldavBackend,array $calendarInfo,array $objectData) { | ||||
|     function __construct(Backend\BackendInterface $caldavBackend, array $calendarInfo, array $objectData) { | ||||
| 
 | ||||
|         $this->caldavBackend = $caldavBackend; | ||||
| 
 | ||||
|         if (!isset($objectData['calendarid'])) { | ||||
|             throw new \InvalidArgumentException('The objectData argument must contain a \'calendarid\' property'); | ||||
|         } | ||||
|         if (!isset($objectData['uri'])) { | ||||
|             throw new \InvalidArgumentException('The objectData argument must contain an \'uri\' property'); | ||||
|         } | ||||
| @@ -60,7 +68,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getName() { | ||||
|     function getName() { | ||||
| 
 | ||||
|         return $this->objectData['uri']; | ||||
| 
 | ||||
| @@ -71,12 +79,12 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function get() { | ||||
|     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->getCalendarObject($this->objectData['calendarid'], $this->objectData['uri']); | ||||
|             $this->objectData = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $this->objectData['uri']); | ||||
|         } | ||||
|         return $this->objectData['calendardata']; | ||||
| 
 | ||||
| @@ -88,7 +96,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * @param string|resource $calendarData | ||||
|      * @return string | ||||
|      */ | ||||
|     public function put($calendarData) { | ||||
|     function put($calendarData) { | ||||
| 
 | ||||
|         if (is_resource($calendarData)) { | ||||
|             $calendarData = stream_get_contents($calendarData); | ||||
| @@ -106,7 +114,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function delete() { | ||||
|     function delete() { | ||||
| 
 | ||||
|         $this->caldavBackend->deleteCalendarObject($this->calendarInfo['id'], $this->objectData['uri']); | ||||
| 
 | ||||
| @@ -117,9 +125,13 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getContentType() { | ||||
|     function getContentType() { | ||||
| 
 | ||||
|         return 'text/calendar; charset=utf-8'; | ||||
|         $mime = 'text/calendar; charset=utf-8'; | ||||
|         if (isset($this->objectData['component']) && $this->objectData['component']) { | ||||
|             $mime .= '; component=' . $this->objectData['component']; | ||||
|         } | ||||
|         return $mime; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -130,7 +142,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getETag() { | ||||
|     function getETag() { | ||||
| 
 | ||||
|         if (isset($this->objectData['etag'])) { | ||||
|             return $this->objectData['etag']; | ||||
| @@ -145,7 +157,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getLastModified() { | ||||
|     function getLastModified() { | ||||
| 
 | ||||
|         return $this->objectData['lastmodified']; | ||||
| 
 | ||||
| @@ -156,7 +168,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getSize() { | ||||
|     function getSize() { | ||||
| 
 | ||||
|         if (array_key_exists('size', $this->objectData)) { | ||||
|             return $this->objectData['size']; | ||||
| @@ -173,7 +185,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getOwner() { | ||||
|     function getOwner() { | ||||
| 
 | ||||
|         return $this->calendarInfo['principaluri']; | ||||
| 
 | ||||
| @@ -186,7 +198,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getGroup() { | ||||
|     function getGroup() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -204,7 +216,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getACL() { | ||||
|     function getACL() { | ||||
| 
 | ||||
|         // An alternative acl may be specified in the object data.
 | ||||
|         if (isset($this->objectData['acl'])) { | ||||
| @@ -212,34 +224,34 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|         } | ||||
| 
 | ||||
|         // The default ACL
 | ||||
|         return array( | ||||
|             array( | ||||
|         return [ | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->calendarInfo['principaluri'], | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->calendarInfo['principaluri'], | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read', | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             ], | ||||
| 
 | ||||
|         ); | ||||
|         ]; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -251,7 +263,7 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * @param array $acl | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setACL(array $acl) { | ||||
|     function setACL(array $acl) { | ||||
| 
 | ||||
|         throw new \Sabre\DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported'); | ||||
| 
 | ||||
| @@ -269,11 +281,10 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     public function getSupportedPrivilegeSet() { | ||||
|     function getSupportedPrivilegeSet() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| @@ -14,7 +14,7 @@ use DateTime; | ||||
|  * This is used to determine which icalendar objects should be returned for a | ||||
|  * calendar-query REPORT request. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -29,7 +29,7 @@ class CalendarQueryValidator { | ||||
|      * @param array $filters | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function validate(VObject\Component $vObject,array $filters) { | ||||
|     function validate(VObject\Component\VCalendar $vObject, array $filters) { | ||||
| 
 | ||||
|         // The top level object is always a component filter.
 | ||||
|         // We'll parse it manually, as it's pretty simple.
 | ||||
| @@ -59,7 +59,7 @@ class CalendarQueryValidator { | ||||
| 
 | ||||
|         foreach ($filters as $filter) { | ||||
| 
 | ||||
|             $isDefined = isset($parent->$filter['name']); | ||||
|             $isDefined = isset($parent->{$filter['name']}); | ||||
| 
 | ||||
|             if ($filter['is-not-defined']) { | ||||
| 
 | ||||
| @@ -75,7 +75,7 @@ class CalendarQueryValidator { | ||||
|             } | ||||
| 
 | ||||
|             if ($filter['time-range']) { | ||||
|                 foreach($parent->$filter['name'] as $subComponent) { | ||||
|                 foreach ($parent->{$filter['name']} as $subComponent) { | ||||
|                     if ($this->validateTimeRange($subComponent, $filter['time-range']['start'], $filter['time-range']['end'])) { | ||||
|                         continue 2; | ||||
|                     } | ||||
| @@ -89,7 +89,7 @@ class CalendarQueryValidator { | ||||
| 
 | ||||
|             // If there are sub-filters, we need to find at least one component
 | ||||
|             // for which the subfilters hold true.
 | ||||
|             foreach($parent->$filter['name'] as $subComponent) { | ||||
|             foreach ($parent->{$filter['name']} as $subComponent) { | ||||
| 
 | ||||
|                 if ( | ||||
|                     $this->validateCompFilters($subComponent, $filter['comp-filters']) && | ||||
| @@ -128,7 +128,7 @@ class CalendarQueryValidator { | ||||
| 
 | ||||
|         foreach ($filters as $filter) { | ||||
| 
 | ||||
|             $isDefined = isset($parent->$filter['name']); | ||||
|             $isDefined = isset($parent->{$filter['name']}); | ||||
| 
 | ||||
|             if ($filter['is-not-defined']) { | ||||
| 
 | ||||
| @@ -144,7 +144,7 @@ class CalendarQueryValidator { | ||||
|             } | ||||
| 
 | ||||
|             if ($filter['time-range']) { | ||||
|                 foreach($parent->$filter['name'] as $subComponent) { | ||||
|                 foreach ($parent->{$filter['name']} as $subComponent) { | ||||
|                     if ($this->validateTimeRange($subComponent, $filter['time-range']['start'], $filter['time-range']['end'])) { | ||||
|                         continue 2; | ||||
|                     } | ||||
| @@ -158,7 +158,7 @@ class CalendarQueryValidator { | ||||
| 
 | ||||
|             // If there are sub-filters, we need to find at least one property
 | ||||
|             // for which the subfilters hold true.
 | ||||
|             foreach($parent->$filter['name'] as $subComponent) { | ||||
|             foreach ($parent->{$filter['name']} as $subComponent) { | ||||
| 
 | ||||
|                 if ( | ||||
|                     $this->validateParamFilters($subComponent, $filter['param-filters']) && | ||||
| @@ -217,34 +217,17 @@ class CalendarQueryValidator { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             if (version_compare(VObject\Version::VERSION, '3.0.0beta1', '>=')) { | ||||
| 
 | ||||
|             // If there are sub-filters, we need to find at least one parameter
 | ||||
|             // for which the subfilters hold true.
 | ||||
|                 foreach($parent[$filter['name']]->getParts() as $subParam) { | ||||
|             foreach ($parent[$filter['name']]->getParts() as $paramPart) { | ||||
| 
 | ||||
|                     if($this->validateTextMatch($subParam,$filter['text-match'])) { | ||||
|                 if ($this->validateTextMatch($paramPart, $filter['text-match'])) { | ||||
|                     // We had a match, so this param-filter succeeds
 | ||||
|                     continue 2; | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             } else { | ||||
| 
 | ||||
|                 // If there are sub-filters, we need to find at least one parameter
 | ||||
|                 // for which the subfilters hold true.
 | ||||
|                 foreach($parent[$filter['name']] as $subParam) { | ||||
| 
 | ||||
|                     if($this->validateTextMatch($subParam,$filter['text-match'])) { | ||||
|                         // We had a match, so this param-filter succeeds
 | ||||
|                         continue 2; | ||||
|                     } | ||||
| 
 | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             // If we got here it means there was a text-match filter and there
 | ||||
|             // were no matches. This means the filter needs to return false.
 | ||||
|             return false; | ||||
| @@ -270,7 +253,7 @@ class CalendarQueryValidator { | ||||
|     protected function validateTextMatch($check, array $textMatch) { | ||||
| 
 | ||||
|         if ($check instanceof VObject\Node) { | ||||
|             $check = (string)$check; | ||||
|             $check = $check->getValue(); | ||||
|         } | ||||
| 
 | ||||
|         $isMatching = \Sabre\DAV\StringUtil::textMatch($check, $textMatch['value'], $textMatch['collation']); | ||||
| @@ -318,7 +301,7 @@ class CalendarQueryValidator { | ||||
|                 if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) { | ||||
| 
 | ||||
|                     // Fire up the iterator!
 | ||||
|                     $it = new VObject\RecurrenceIterator($component->parent->parent, (string)$component->parent->UID); | ||||
|                     $it = new VObject\Recur\EventIterator($component->parent->parent, (string)$component->parent->UID); | ||||
|                     while ($it->valid()) { | ||||
|                         $expandedEvent = $it->getEventObject(); | ||||
| 
 | ||||
| @@ -10,11 +10,14 @@ use Sabre\DAVACL\PrincipalBackend; | ||||
|  * This object is responsible for generating a list of calendar-homes for each | ||||
|  * user. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * This is the top-most node for the calendars tree. In most servers this class | ||||
|  * represents the "/calendars" path. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class CalendarRootNode extends \Sabre\DAVACL\AbstractPrincipalCollection { | ||||
| class CalendarRoot extends \Sabre\DAVACL\AbstractPrincipalCollection { | ||||
| 
 | ||||
|     /** | ||||
|      * CalDAV backend | ||||
| @@ -37,7 +40,7 @@ class CalendarRootNode extends \Sabre\DAVACL\AbstractPrincipalCollection { | ||||
|      * @param Backend\BackendInterface $caldavBackend | ||||
|      * @param string $principalPrefix | ||||
|      */ | ||||
|     public function __construct(PrincipalBackend\BackendInterface $principalBackend,Backend\BackendInterface $caldavBackend, $principalPrefix = 'principals') { | ||||
|     function __construct(PrincipalBackend\BackendInterface $principalBackend, Backend\BackendInterface $caldavBackend, $principalPrefix = 'principals') { | ||||
| 
 | ||||
|         parent::__construct($principalBackend, $principalPrefix); | ||||
|         $this->caldavBackend = $caldavBackend; | ||||
| @@ -52,7 +55,7 @@ class CalendarRootNode extends \Sabre\DAVACL\AbstractPrincipalCollection { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getName() { | ||||
|     function getName() { | ||||
| 
 | ||||
|         return Plugin::CALENDAR_ROOT; | ||||
| 
 | ||||
| @@ -68,9 +71,9 @@ class CalendarRootNode extends \Sabre\DAVACL\AbstractPrincipalCollection { | ||||
|      * @param array $principal | ||||
|      * @return \Sabre\DAV\INode | ||||
|      */ | ||||
|     public function getChildForPrincipal(array $principal) { | ||||
|     function getChildForPrincipal(array $principal) { | ||||
| 
 | ||||
|         return new UserCalendars($this->caldavBackend, $principal); | ||||
|         return new CalendarHome($this->caldavBackend, $principal); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -8,7 +8,7 @@ use Sabre\CalDAV; | ||||
| /** | ||||
|  * InvalidComponentType | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -23,7 +23,7 @@ class InvalidComponentType extends DAV\Exception\Forbidden { | ||||
|      * @param \DOMElement $errorNode | ||||
|      * @return void | ||||
|      */ | ||||
|     public function serialize(DAV\Server $server, \DOMElement $errorNode) { | ||||
|     function serialize(DAV\Server $server, \DOMElement $errorNode) { | ||||
| 
 | ||||
|         $doc = $errorNode->ownerDocument; | ||||
| 
 | ||||
							
								
								
									
										366
									
								
								vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										366
									
								
								vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,366 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV; | ||||
|  | ||||
| use DateTimeZone; | ||||
| use Sabre\DAV; | ||||
| use Sabre\VObject; | ||||
| use Sabre\HTTP\RequestInterface; | ||||
| use Sabre\HTTP\ResponseInterface; | ||||
| use Sabre\DAV\Exception\BadRequest; | ||||
| use DateTime; | ||||
|  | ||||
| /** | ||||
|  * ICS Exporter | ||||
|  * | ||||
|  * This plugin adds the ability to export entire calendars as .ics files. | ||||
|  * This is useful for clients that don't support CalDAV yet. They often do | ||||
|  * support ics files. | ||||
|  * | ||||
|  * To use this, point a http client to a caldav calendar, and add ?expand to | ||||
|  * the url. | ||||
|  * | ||||
|  * Further options that can be added to the url: | ||||
|  *   start=123456789 - Only return events after the given unix timestamp | ||||
|  *   end=123245679   - Only return events from before the given unix timestamp | ||||
|  *   expand=1        - Strip timezone information and expand recurring events. | ||||
|  *                     If you'd like to expand, you _must_ also specify start | ||||
|  *                     and end. | ||||
|  * | ||||
|  * By default this plugin returns data in the text/calendar format (iCalendar | ||||
|  * 2.0). If you'd like to receive jCal data instead, you can use an Accept | ||||
|  * header: | ||||
|  * | ||||
|  * Accept: application/calendar+json | ||||
|  * | ||||
|  * Alternatively, you can also specify this in the url using | ||||
|  * accept=application/calendar+json, or accept=jcal for short. If the url | ||||
|  * parameter and Accept header is specified, the url parameter wins. | ||||
|  * | ||||
|  * Note that specifying a start or end data implies that only events will be | ||||
|  * returned. VTODO and VJOURNAL will be stripped. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class ICSExportPlugin extends DAV\ServerPlugin { | ||||
|  | ||||
|     /** | ||||
|      * Reference to Server class | ||||
|      * | ||||
|      * @var \Sabre\DAV\Server | ||||
|      */ | ||||
|     protected $server; | ||||
|  | ||||
|     /** | ||||
|      * Initializes the plugin and registers event handlers | ||||
|      * | ||||
|      * @param \Sabre\DAV\Server $server | ||||
|      * @return void | ||||
|      */ | ||||
|     function initialize(DAV\Server $server) { | ||||
|  | ||||
|         $this->server = $server; | ||||
|         $server->on('method:GET', [$this, 'httpGet'], 90); | ||||
|         $server->on('browserButtonActions', function($path, $node, &$actions) { | ||||
|             if ($node instanceof ICalendar) { | ||||
|                 $actions .= '<a href="' . htmlspecialchars($path, ENT_QUOTES, 'UTF-8') . '?export"><span class="oi" data-glyph="calendar"></span></a>'; | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Intercepts GET requests on calendar urls ending with ?export. | ||||
|      * | ||||
|      * @param RequestInterface $request | ||||
|      * @param ResponseInterface $response | ||||
|      * @return bool | ||||
|      */ | ||||
|     function httpGet(RequestInterface $request, ResponseInterface $response) { | ||||
|  | ||||
|         $queryParams = $request->getQueryParameters(); | ||||
|         if (!array_key_exists('export', $queryParams)) return; | ||||
|  | ||||
|         $path = $request->getPath(); | ||||
|  | ||||
|         $node = $this->server->getProperties($path, [ | ||||
|             '{DAV:}resourcetype', | ||||
|             '{DAV:}displayname', | ||||
|             '{http://sabredav.org/ns}sync-token', | ||||
|             '{DAV:}sync-token', | ||||
|             '{http://apple.com/ns/ical/}calendar-color', | ||||
|         ]); | ||||
|  | ||||
|         if (!isset($node['{DAV:}resourcetype']) || !$node['{DAV:}resourcetype']->is('{' . Plugin::NS_CALDAV . '}calendar')) { | ||||
|             return; | ||||
|         } | ||||
|         // Marking the transactionType, for logging purposes. | ||||
|         $this->server->transactionType = 'get-calendar-export'; | ||||
|  | ||||
|         $properties = $node; | ||||
|  | ||||
|         $start = null; | ||||
|         $end = null; | ||||
|         $expand = false; | ||||
|         $componentType = false; | ||||
|         if (isset($queryParams['start'])) { | ||||
|             if (!ctype_digit($queryParams['start'])) { | ||||
|                 throw new BadRequest('The start= parameter must contain a unix timestamp'); | ||||
|             } | ||||
|             $start = DateTime::createFromFormat('U', $queryParams['start']); | ||||
|         } | ||||
|         if (isset($queryParams['end'])) { | ||||
|             if (!ctype_digit($queryParams['end'])) { | ||||
|                 throw new BadRequest('The end= parameter must contain a unix timestamp'); | ||||
|             } | ||||
|             $end = DateTime::createFromFormat('U', $queryParams['end']); | ||||
|         } | ||||
|         if (isset($queryParams['expand']) && !!$queryParams['expand']) { | ||||
|             if (!$start || !$end) { | ||||
|                 throw new BadRequest('If you\'d like to expand recurrences, you must specify both a start= and end= parameter.'); | ||||
|             } | ||||
|             $expand = true; | ||||
|             $componentType = 'VEVENT'; | ||||
|         } | ||||
|         if (isset($queryParams['componentType'])) { | ||||
|             if (!in_array($queryParams['componentType'], ['VEVENT', 'VTODO', 'VJOURNAL'])) { | ||||
|                 throw new BadRequest('You are not allowed to search for components of type: ' . $queryParams['componentType'] . ' here'); | ||||
|             } | ||||
|             $componentType = $queryParams['componentType']; | ||||
|         } | ||||
|  | ||||
|         $format = \Sabre\HTTP\Util::Negotiate( | ||||
|             $request->getHeader('Accept'), | ||||
|             [ | ||||
|                 'text/calendar', | ||||
|                 'application/calendar+json', | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         if (isset($queryParams['accept'])) { | ||||
|             if ($queryParams['accept'] === 'application/calendar+json' || $queryParams['accept'] === 'jcal') { | ||||
|                 $format = 'application/calendar+json'; | ||||
|             } | ||||
|         } | ||||
|         if (!$format) { | ||||
|             $format = 'text/calendar'; | ||||
|         } | ||||
|  | ||||
|         $this->generateResponse($path, $start, $end, $expand, $componentType, $format, $properties, $response); | ||||
|  | ||||
|         // Returning false to break the event chain | ||||
|         return false; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is responsible for generating the actual, full response. | ||||
|      * | ||||
|      * @param string $path | ||||
|      * @param DateTime|null $start | ||||
|      * @param DateTime|null $end | ||||
|      * @param bool $expand | ||||
|      * @param string $componentType | ||||
|      * @param string $format | ||||
|      * @param array $properties | ||||
|      * @param ResponseInterface $response | ||||
|      */ | ||||
|     protected function generateResponse($path, $start, $end, $expand, $componentType, $format, $properties, ResponseInterface $response) { | ||||
|  | ||||
|         $calDataProp = '{' . Plugin::NS_CALDAV . '}calendar-data'; | ||||
|  | ||||
|         $blobs = []; | ||||
|         if ($start || $end || $componentType) { | ||||
|  | ||||
|             // If there was a start or end filter, we need to enlist | ||||
|             // calendarQuery for speed. | ||||
|             $calendarNode = $this->server->tree->getNodeForPath($path); | ||||
|             $queryResult = $calendarNode->calendarQuery([ | ||||
|                 'name'         => 'VCALENDAR', | ||||
|                 'comp-filters' => [ | ||||
|                     [ | ||||
|                         'name'           => $componentType, | ||||
|                         'comp-filters'   => [], | ||||
|                         'prop-filters'   => [], | ||||
|                         'is-not-defined' => false, | ||||
|                         'time-range'     => [ | ||||
|                             'start' => $start, | ||||
|                             'end'   => $end, | ||||
|                         ], | ||||
|                     ], | ||||
|                 ], | ||||
|                 'prop-filters'   => [], | ||||
|                 'is-not-defined' => false, | ||||
|                 'time-range'     => null, | ||||
|             ]); | ||||
|  | ||||
|             // queryResult is just a list of base urls. We need to prefix the | ||||
|             // calendar path. | ||||
|             $queryResult = array_map( | ||||
|                 function($item) use ($path) { | ||||
|                     return $path . '/' . $item; | ||||
|                 }, | ||||
|                 $queryResult | ||||
|             ); | ||||
|             $nodes = $this->server->getPropertiesForMultiplePaths($queryResult, [$calDataProp]); | ||||
|             unset($queryResult); | ||||
|  | ||||
|         } else { | ||||
|             $nodes = $this->server->getPropertiesForPath($path, [$calDataProp], 1); | ||||
|         } | ||||
|  | ||||
|         // Flattening the arrays | ||||
|         foreach ($nodes as $node) { | ||||
|             if (isset($node[200][$calDataProp])) { | ||||
|                 $blobs[$node['href']] = $node[200][$calDataProp]; | ||||
|             } | ||||
|         } | ||||
|         unset($nodes); | ||||
|  | ||||
|         $mergedCalendar = $this->mergeObjects( | ||||
|             $properties, | ||||
|             $blobs | ||||
|         ); | ||||
|  | ||||
|         if ($expand) { | ||||
|             $calendarTimeZone = null; | ||||
|             // We're expanding, and for that we need to figure out the | ||||
|             // calendar's timezone. | ||||
|             $tzProp = '{' . Plugin::NS_CALDAV . '}calendar-timezone'; | ||||
|             $tzResult = $this->server->getProperties($path, [$tzProp]); | ||||
|             if (isset($tzResult[$tzProp])) { | ||||
|                 // This property contains a VCALENDAR with a single | ||||
|                 // VTIMEZONE. | ||||
|                 $vtimezoneObj = VObject\Reader::read($tzResult[$tzProp]); | ||||
|                 $calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone(); | ||||
|                 // Destroy circular references to PHP will GC the object. | ||||
|                 $vtimezoneObj->destroy(); | ||||
|                 unset($vtimezoneObj); | ||||
|             } else { | ||||
|                 // Defaulting to UTC. | ||||
|                 $calendarTimeZone = new DateTimeZone('UTC'); | ||||
|             } | ||||
|  | ||||
|             $mergedCalendar = $mergedCalendar->expand($start, $end, $calendarTimeZone); | ||||
|         } | ||||
|  | ||||
|         $response->setHeader('Content-Type', $format); | ||||
|  | ||||
|         switch ($format) { | ||||
|             case 'text/calendar' : | ||||
|                 $mergedCalendar = $mergedCalendar->serialize(); | ||||
|                 break; | ||||
|             case 'application/calendar+json' : | ||||
|                 $mergedCalendar = json_encode($mergedCalendar->jsonSerialize()); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         $response->setStatus(200); | ||||
|         $response->setBody($mergedCalendar); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Merges all calendar objects, and builds one big iCalendar blob. | ||||
|      * | ||||
|      * @param array $properties Some CalDAV properties | ||||
|      * @param array $inputObjects | ||||
|      * @return VObject\Component\VCalendar | ||||
|      */ | ||||
|     function mergeObjects(array $properties, array $inputObjects) { | ||||
|  | ||||
|         $calendar = new VObject\Component\VCalendar(); | ||||
|         $calendar->version = '2.0'; | ||||
|         if (DAV\Server::$exposeVersion) { | ||||
|             $calendar->prodid = '-//SabreDAV//SabreDAV ' . DAV\Version::VERSION . '//EN'; | ||||
|         } else { | ||||
|             $calendar->prodid = '-//SabreDAV//SabreDAV//EN'; | ||||
|         } | ||||
|         if (isset($properties['{DAV:}displayname'])) { | ||||
|             $calendar->{'X-WR-CALNAME'} = $properties['{DAV:}displayname']; | ||||
|         } | ||||
|         if (isset($properties['{http://apple.com/ns/ical/}calendar-color'])) { | ||||
|             $calendar->{'X-APPLE-CALENDAR-COLOR'} = $properties['{http://apple.com/ns/ical/}calendar-color']; | ||||
|         } | ||||
|  | ||||
|         $collectedTimezones = []; | ||||
|  | ||||
|         $timezones = []; | ||||
|         $objects = []; | ||||
|  | ||||
|         foreach ($inputObjects as $href => $inputObject) { | ||||
|  | ||||
|             $nodeComp = VObject\Reader::read($inputObject); | ||||
|  | ||||
|             foreach ($nodeComp->children() as $child) { | ||||
|  | ||||
|                 switch ($child->name) { | ||||
|                     case 'VEVENT' : | ||||
|                     case 'VTODO' : | ||||
|                     case 'VJOURNAL' : | ||||
|                         $objects[] = clone $child; | ||||
|                         break; | ||||
|  | ||||
|                     // VTIMEZONE is special, because we need to filter out the duplicates | ||||
|                     case 'VTIMEZONE' : | ||||
|                         // Naively just checking tzid. | ||||
|                         if (in_array((string)$child->TZID, $collectedTimezones)) continue; | ||||
|  | ||||
|                         $timezones[] = clone $child; | ||||
|                         $collectedTimezones[] = $child->TZID; | ||||
|                         break; | ||||
|  | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|             // Destroy circular references to PHP will GC the object. | ||||
|             $nodeComp->destroy(); | ||||
|             unset($nodeComp); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         foreach ($timezones as $tz) $calendar->add($tz); | ||||
|         foreach ($objects as $obj) $calendar->add($obj); | ||||
|  | ||||
|         return $calendar; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a plugin name. | ||||
|      * | ||||
|      * Using this name other plugins will be able to access other plugins | ||||
|      * using \Sabre\DAV\Server::getPlugin | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     function getPluginName() { | ||||
|  | ||||
|         return 'ics-export'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     function getPluginInfo() { | ||||
|  | ||||
|         return [ | ||||
|             'name'        => $this->getPluginName(), | ||||
|             'description' => 'Adds the ability to export CalDAV calendars as a single iCalendar file.', | ||||
|             'link'        => 'http://sabre.io/dav/ics-export-plugin/', | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										18
									
								
								vendor/sabre/dav/lib/CalDAV/ICalendar.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/sabre/dav/lib/CalDAV/ICalendar.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV; | ||||
|  | ||||
| use Sabre\DAVACL; | ||||
|  | ||||
| /** | ||||
|  * Calendar interface | ||||
|  * | ||||
|  * Implement this interface to allow a node to be recognized as an calendar. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| interface ICalendar extends ICalendarObjectContainer, DAVACL\IACL { | ||||
|  | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Sabre\CalDAV; | ||||
| 
 | ||||
| use Sabre\DAV; | ||||
| 
 | ||||
| /** | ||||
| @@ -11,11 +12,10 @@ use Sabre\DAV; | ||||
|  * | ||||
|  * Calendar objects are resources such as Events, Todo's or Journals. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| interface ICalendarObject extends DAV\IFile { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| @@ -1,18 +1,21 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Sabre\CalDAV; | ||||
| use Sabre\DAV; | ||||
| 
 | ||||
| /** | ||||
|  * Calendar interface | ||||
|  * This interface represents a node that may contain calendar objects. | ||||
|  * | ||||
|  * Implement this interface to allow a node to be recognized as an calendar. | ||||
|  * This is the shared parent for both the Inbox collection and calendars | ||||
|  * resources. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * In most cases you will likely want to look at ICalendar instead of this | ||||
|  * interface. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| interface ICalendar extends DAV\ICollection { | ||||
| interface ICalendarObjectContainer extends \Sabre\DAV\ICollection { | ||||
| 
 | ||||
|     /** | ||||
|      * Performs a calendar-query on the contents of this calendar. | ||||
| @@ -31,6 +34,6 @@ interface ICalendar extends DAV\ICollection { | ||||
|      * @param array $filters | ||||
|      * @return array | ||||
|      */ | ||||
|     public function calendarQuery(array $filters); | ||||
|     function calendarQuery(array $filters); | ||||
| 
 | ||||
| } | ||||
| @@ -5,7 +5,7 @@ namespace Sabre\CalDAV; | ||||
| /** | ||||
|  * This interface represents a Calendar that can be shared with other users. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -5,7 +5,7 @@ namespace Sabre\CalDAV; | ||||
| /** | ||||
|  * This interface represents a Calendar that is shared by a different user. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -16,7 +16,7 @@ use Sabre\DAVACL; | ||||
|  * This collection should only return Sabre\CalDAV\Notifications\INode nodes as | ||||
|  * its children. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -42,7 +42,7 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { | ||||
|      * @param CalDAV\Backend\NotificationSupport $caldavBackend | ||||
|      * @param string $principalUri | ||||
|      */ | ||||
|     public function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri) { | ||||
|     function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri) { | ||||
| 
 | ||||
|         $this->caldavBackend = $caldavBackend; | ||||
|         $this->principalUri = $principalUri; | ||||
| @@ -54,9 +54,9 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getChildren() { | ||||
|     function getChildren() { | ||||
| 
 | ||||
|         $children = array(); | ||||
|         $children = []; | ||||
|         $notifications = $this->caldavBackend->getNotificationsForPrincipal($this->principalUri); | ||||
| 
 | ||||
|         foreach ($notifications as $notification) { | ||||
| @@ -77,7 +77,7 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getName() { | ||||
|     function getName() { | ||||
| 
 | ||||
|         return 'notifications'; | ||||
| 
 | ||||
| @@ -90,7 +90,7 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getOwner() { | ||||
|     function getOwner() { | ||||
| 
 | ||||
|         return $this->principalUri; | ||||
| 
 | ||||
| @@ -103,7 +103,7 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getGroup() { | ||||
|     function getGroup() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -121,20 +121,20 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getACL() { | ||||
|     function getACL() { | ||||
| 
 | ||||
|         return array( | ||||
|             array( | ||||
|         return [ | ||||
|             [ | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'protected' => true, | ||||
|             ) | ||||
|         ); | ||||
|             ] | ||||
|         ]; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -146,7 +146,7 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { | ||||
|      * @param array $acl | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setACL(array $acl) { | ||||
|     function setACL(array $acl) { | ||||
| 
 | ||||
|         throw new DAV\Exception\NotImplemented('Updating ACLs is not implemented here'); | ||||
| 
 | ||||
| @@ -164,7 +164,7 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     public function getSupportedPrivilegeSet() { | ||||
|     function getSupportedPrivilegeSet() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -14,11 +14,10 @@ use Sabre\DAV; | ||||
|  * This collection should only return Sabre\CalDAV\Notifications\INode nodes as | ||||
|  * its children. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| interface ICollection extends DAV\ICollection { | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| @@ -12,7 +12,7 @@ namespace Sabre\CalDAV\Notifications; | ||||
|  * For a complete example, check out the Notification class, which contains | ||||
|  * some helper functions. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -4,6 +4,7 @@ namespace Sabre\CalDAV\Notifications; | ||||
| 
 | ||||
| use Sabre\DAV; | ||||
| use Sabre\CalDAV; | ||||
| use Sabre\CalDAV\Xml\Notification\NotificationInterface; | ||||
| use Sabre\DAVACL; | ||||
| 
 | ||||
| /** | ||||
| @@ -12,8 +13,8 @@ use Sabre\DAVACL; | ||||
|  * The signature is mostly identical to that of Sabre\DAV\IFile, but the get() method | ||||
|  * MUST return an xml document that matches the requirements of the | ||||
|  * 'caldav-notifications.txt' spec. | ||||
| 
 | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -45,9 +46,9 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @param CalDAV\Backend\NotificationSupport $caldavBackend | ||||
|      * @param string $principalUri | ||||
|      * @param CalDAV\Notifications\INotificationType $notification | ||||
|      * @param NotificationInterface $notification | ||||
|      */ | ||||
|     public function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri, INotificationType $notification) { | ||||
|     function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri, NotificationInterface $notification) { | ||||
| 
 | ||||
|         $this->caldavBackend = $caldavBackend; | ||||
|         $this->principalUri = $principalUri; | ||||
| @@ -60,7 +61,7 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @return id | ||||
|      */ | ||||
|     public function getName() { | ||||
|     function getName() { | ||||
| 
 | ||||
|         return $this->notification->getId() . '.xml'; | ||||
| 
 | ||||
| @@ -73,7 +74,7 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getETag() { | ||||
|     function getETag() { | ||||
| 
 | ||||
|         return $this->notification->getETag(); | ||||
| 
 | ||||
| @@ -85,7 +86,7 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @return INotificationType | ||||
|      */ | ||||
|     public function getNotificationType() { | ||||
|     function getNotificationType() { | ||||
| 
 | ||||
|         return $this->notification; | ||||
| 
 | ||||
| @@ -96,7 +97,7 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function delete() { | ||||
|     function delete() { | ||||
| 
 | ||||
|         $this->caldavBackend->deleteNotification($this->getOwner(), $this->notification); | ||||
| 
 | ||||
| @@ -109,7 +110,7 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getOwner() { | ||||
|     function getOwner() { | ||||
| 
 | ||||
|         return $this->principalUri; | ||||
| 
 | ||||
| @@ -122,7 +123,7 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getGroup() { | ||||
|     function getGroup() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -140,20 +141,20 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getACL() { | ||||
|     function getACL() { | ||||
| 
 | ||||
|         return array( | ||||
|             array( | ||||
|         return [ | ||||
|             [ | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'protected' => true, | ||||
|             ) | ||||
|         ); | ||||
|             ] | ||||
|         ]; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -165,7 +166,7 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * @param array $acl | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setACL(array $acl) { | ||||
|     function setACL(array $acl) { | ||||
| 
 | ||||
|         throw new DAV\Exception\NotImplemented('Updating ACLs is not implemented here'); | ||||
| 
 | ||||
| @@ -183,7 +184,7 @@ class Node extends DAV\File implements INode, DAVACL\IACL { | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     public function getSupportedPrivilegeSet() { | ||||
|     function getSupportedPrivilegeSet() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
							
								
								
									
										180
									
								
								vendor/sabre/dav/lib/CalDAV/Notifications/Plugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								vendor/sabre/dav/lib/CalDAV/Notifications/Plugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Notifications; | ||||
|  | ||||
| use Sabre\DAV; | ||||
| use Sabre\DAV\PropFind; | ||||
| use Sabre\DAV\INode as BaseINode; | ||||
| use Sabre\DAV\ServerPlugin; | ||||
| use Sabre\DAV\Server; | ||||
| use Sabre\DAVACL; | ||||
| use Sabre\HTTP\RequestInterface; | ||||
| use Sabre\HTTP\ResponseInterface; | ||||
|  | ||||
| /** | ||||
|  * Notifications plugin | ||||
|  * | ||||
|  * This plugin implements several features required by the caldav-notification | ||||
|  * draft specification. | ||||
|  * | ||||
|  * Before version 2.1.0 this functionality was part of Sabre\CalDAV\Plugin but | ||||
|  * this has since been split up. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class Plugin extends ServerPlugin { | ||||
|  | ||||
|     /** | ||||
|      * This is the namespace for the proprietary calendarserver extensions | ||||
|      */ | ||||
|     const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; | ||||
|  | ||||
|     /** | ||||
|      * Reference to the main server object. | ||||
|      * | ||||
|      * @var Server | ||||
|      */ | ||||
|     protected $server; | ||||
|  | ||||
|     /** | ||||
|      * Returns a plugin name. | ||||
|      * | ||||
|      * Using this name other plugins will be able to access other plugins | ||||
|      * using \Sabre\DAV\Server::getPlugin | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     function getPluginName() { | ||||
|  | ||||
|         return 'notifications'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 Server $server | ||||
|      * @return void | ||||
|      */ | ||||
|     function initialize(Server $server) { | ||||
|  | ||||
|         $this->server = $server; | ||||
|         $server->on('method:GET', [$this, 'httpGet'], 90); | ||||
|         $server->on('propFind',   [$this, 'propFind']); | ||||
|  | ||||
|         $server->xml->namespaceMap[self::NS_CALENDARSERVER] = 'cs'; | ||||
|         $server->resourceTypeMapping['\\Sabre\\CalDAV\\Notifications\\ICollection'] = '{' . self::NS_CALENDARSERVER . '}notification'; | ||||
|  | ||||
|         array_push($server->protectedProperties, | ||||
|             '{' . self::NS_CALENDARSERVER . '}notification-URL', | ||||
|             '{' . self::NS_CALENDARSERVER . '}notificationtype' | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * PropFind | ||||
|      * | ||||
|      * @param PropFind $propFind | ||||
|      * @param BaseINode $node | ||||
|      * @return void | ||||
|      */ | ||||
|     function propFind(PropFind $propFind, BaseINode $node) { | ||||
|  | ||||
|         $caldavPlugin = $this->server->getPlugin('caldav'); | ||||
|  | ||||
|         if ($node instanceof DAVACL\IPrincipal) { | ||||
|  | ||||
|             $principalUrl = $node->getPrincipalUrl(); | ||||
|  | ||||
|             // notification-URL property | ||||
|             $propFind->handle('{' . self::NS_CALENDARSERVER . '}notification-URL', function() use ($principalUrl, $caldavPlugin) { | ||||
|  | ||||
|                 $notificationPath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl) . '/notifications/'; | ||||
|                 return new DAV\Xml\Property\Href($notificationPath); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         if ($node instanceof INode) { | ||||
|  | ||||
|             $propFind->handle( | ||||
|                 '{' . self::NS_CALENDARSERVER . '}notificationtype', | ||||
|                 [$node, 'getNotificationType'] | ||||
|             ); | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This event is triggered before the usual GET request handler. | ||||
|      * | ||||
|      * We use this to intercept GET calls to notification nodes, and return the | ||||
|      * proper response. | ||||
|      * | ||||
|      * @param RequestInterface $request | ||||
|      * @param ResponseInterface $response | ||||
|      * @return void | ||||
|      */ | ||||
|     function httpGet(RequestInterface $request, ResponseInterface $response) { | ||||
|  | ||||
|         $path = $request->getPath(); | ||||
|  | ||||
|         try { | ||||
|             $node = $this->server->tree->getNodeForPath($path); | ||||
|         } catch (DAV\Exception\NotFound $e) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!$node instanceof INode) | ||||
|             return; | ||||
|  | ||||
|         $writer = $this->server->xml->getWriter(); | ||||
|         $writer->contextUri = $this->server->getBaseUri(); | ||||
|         $writer->openMemory(); | ||||
|         $writer->startDocument('1.0', 'UTF-8'); | ||||
|         $writer->startElement('{http://calendarserver.org/ns/}notification'); | ||||
|         $node->getNotificationType()->xmlSerializeFull($writer); | ||||
|         $writer->endElement(); | ||||
|  | ||||
|         $response->setHeader('Content-Type', 'application/xml'); | ||||
|         $response->setHeader('ETag', $node->getETag()); | ||||
|         $response->setStatus(200); | ||||
|         $response->setBody($writer->outputMemory()); | ||||
|  | ||||
|         // Return false to break the event chain. | ||||
|         return false; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     function getPluginInfo() { | ||||
|  | ||||
|         return [ | ||||
|             'name'        => $this->getPluginName(), | ||||
|             'description' => 'Adds support for caldav-notifications, which is required to enable caldav-sharing.', | ||||
|             'link'        => 'http://sabre.io/dav/caldav-sharing/', | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										1025
									
								
								vendor/sabre/dav/lib/CalDAV/Plugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1025
									
								
								vendor/sabre/dav/lib/CalDAV/Plugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,6 +1,7 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Sabre\CalDAV\Principal; | ||||
| 
 | ||||
| use Sabre\DAVACL; | ||||
| 
 | ||||
| /** | ||||
| @@ -11,11 +12,11 @@ use Sabre\DAVACL; | ||||
|  * calendar-proxy-write sub-principals, as defined by the caldav-proxy | ||||
|  * specification. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class Collection extends DAVACL\AbstractPrincipalCollection { | ||||
| class Collection extends DAVACL\PrincipalCollection { | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a child object based on principal information | ||||
| @@ -23,7 +24,7 @@ class Collection extends DAVACL\AbstractPrincipalCollection { | ||||
|      * @param array $principalInfo | ||||
|      * @return User | ||||
|      */ | ||||
|     public function getChildForPrincipal(array $principalInfo) { | ||||
|     function getChildForPrincipal(array $principalInfo) { | ||||
| 
 | ||||
|         return new User($this->principalBackend, $principalInfo); | ||||
| 
 | ||||
| @@ -10,7 +10,7 @@ use Sabre\DAVACL; | ||||
|  * Any principal node implementing this interface will be picked up as a 'proxy | ||||
|  * principal group'. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -10,7 +10,7 @@ use Sabre\DAVACL; | ||||
|  * Any principal node implementing this interface will be picked up as a 'proxy | ||||
|  * principal group'. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -1,6 +1,7 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Sabre\CalDAV\Principal; | ||||
| 
 | ||||
| use Sabre\DAVACL; | ||||
| use Sabre\DAV; | ||||
| 
 | ||||
| @@ -11,7 +12,7 @@ use Sabre\DAV; | ||||
|  * This is needed to implement 'Calendar delegation' support. This class is | ||||
|  * instantiated by User. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -39,7 +40,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * @param DAVACL\PrincipalBackend\BackendInterface $principalBackend | ||||
|      * @param array $principalInfo | ||||
|      */ | ||||
|     public function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, array $principalInfo) { | ||||
|     function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, array $principalInfo) { | ||||
| 
 | ||||
|         $this->principalInfo = $principalInfo; | ||||
|         $this->principalBackend = $principalBackend; | ||||
| @@ -51,7 +52,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getName() { | ||||
|     function getName() { | ||||
| 
 | ||||
|         return 'calendar-proxy-read'; | ||||
| 
 | ||||
| @@ -62,7 +63,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * | ||||
|      * @return null | ||||
|      */ | ||||
|     public function getLastModified() { | ||||
|     function getLastModified() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -74,7 +75,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * @throws DAV\Exception\Forbidden | ||||
|      * @return void | ||||
|      */ | ||||
|     public function delete() { | ||||
|     function delete() { | ||||
| 
 | ||||
|         throw new DAV\Exception\Forbidden('Permission denied to delete node'); | ||||
| 
 | ||||
| @@ -87,7 +88,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * @param string $name The new name | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setName($name) { | ||||
|     function setName($name) { | ||||
| 
 | ||||
|         throw new DAV\Exception\Forbidden('Permission denied to rename file'); | ||||
| 
 | ||||
| @@ -101,9 +102,9 @@ class ProxyRead implements IProxyRead { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAlternateUriSet() { | ||||
|     function getAlternateUriSet() { | ||||
| 
 | ||||
|         return array(); | ||||
|         return []; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -112,7 +113,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getPrincipalUrl() { | ||||
|     function getPrincipalUrl() { | ||||
| 
 | ||||
|         return $this->principalInfo['uri'] . '/' . $this->getName(); | ||||
| 
 | ||||
| @@ -126,7 +127,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getGroupMemberSet() { | ||||
|     function getGroupMemberSet() { | ||||
| 
 | ||||
|         return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl()); | ||||
| 
 | ||||
| @@ -140,7 +141,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getGroupMembership() { | ||||
|     function getGroupMembership() { | ||||
| 
 | ||||
|         return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); | ||||
| 
 | ||||
| @@ -157,7 +158,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * @param array $principals | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setGroupMemberSet(array $principals) { | ||||
|     function setGroupMemberSet(array $principals) { | ||||
| 
 | ||||
|         $this->principalBackend->setGroupMemberSet($this->getPrincipalUrl(), $principals); | ||||
| 
 | ||||
| @@ -171,7 +172,7 @@ class ProxyRead implements IProxyRead { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getDisplayName() { | ||||
|     function getDisplayName() { | ||||
| 
 | ||||
|         return $this->getName(); | ||||
| 
 | ||||
| @@ -1,6 +1,7 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Sabre\CalDAV\Principal; | ||||
| 
 | ||||
| use Sabre\DAVACL; | ||||
| use Sabre\DAV; | ||||
| 
 | ||||
| @@ -11,7 +12,7 @@ use Sabre\DAV; | ||||
|  * This is needed to implement 'Calendar delegation' support. This class is | ||||
|  * instantiated by User. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -39,7 +40,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * @param DAVACL\PrincipalBackend\BackendInterface $principalBackend | ||||
|      * @param array $principalInfo | ||||
|      */ | ||||
|     public function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, array $principalInfo) { | ||||
|     function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, array $principalInfo) { | ||||
| 
 | ||||
|         $this->principalInfo = $principalInfo; | ||||
|         $this->principalBackend = $principalBackend; | ||||
| @@ -51,7 +52,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getName() { | ||||
|     function getName() { | ||||
| 
 | ||||
|         return 'calendar-proxy-write'; | ||||
| 
 | ||||
| @@ -62,7 +63,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * | ||||
|      * @return null | ||||
|      */ | ||||
|     public function getLastModified() { | ||||
|     function getLastModified() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -74,7 +75,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * @throws DAV\Exception\Forbidden | ||||
|      * @return void | ||||
|      */ | ||||
|     public function delete() { | ||||
|     function delete() { | ||||
| 
 | ||||
|         throw new DAV\Exception\Forbidden('Permission denied to delete node'); | ||||
| 
 | ||||
| @@ -87,7 +88,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * @param string $name The new name | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setName($name) { | ||||
|     function setName($name) { | ||||
| 
 | ||||
|         throw new DAV\Exception\Forbidden('Permission denied to rename file'); | ||||
| 
 | ||||
| @@ -101,9 +102,9 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAlternateUriSet() { | ||||
|     function getAlternateUriSet() { | ||||
| 
 | ||||
|         return array(); | ||||
|         return []; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -112,7 +113,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getPrincipalUrl() { | ||||
|     function getPrincipalUrl() { | ||||
| 
 | ||||
|         return $this->principalInfo['uri'] . '/' . $this->getName(); | ||||
| 
 | ||||
| @@ -126,7 +127,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getGroupMemberSet() { | ||||
|     function getGroupMemberSet() { | ||||
| 
 | ||||
|         return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl()); | ||||
| 
 | ||||
| @@ -140,7 +141,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getGroupMembership() { | ||||
|     function getGroupMembership() { | ||||
| 
 | ||||
|         return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); | ||||
| 
 | ||||
| @@ -157,7 +158,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * @param array $principals | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setGroupMemberSet(array $principals) { | ||||
|     function setGroupMemberSet(array $principals) { | ||||
| 
 | ||||
|         $this->principalBackend->setGroupMemberSet($this->getPrincipalUrl(), $principals); | ||||
| 
 | ||||
| @@ -171,7 +172,7 @@ class ProxyWrite implements IProxyWrite { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getDisplayName() { | ||||
|     function getDisplayName() { | ||||
| 
 | ||||
|         return $this->getName(); | ||||
| 
 | ||||
| @@ -1,6 +1,7 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Sabre\CalDAV\Principal; | ||||
| 
 | ||||
| use Sabre\DAV; | ||||
| use Sabre\DAVACL; | ||||
| 
 | ||||
| @@ -11,7 +12,7 @@ use Sabre\DAVACL; | ||||
|  * collection and returns the caldav-proxy-read and caldav-proxy-write child | ||||
|  * principals. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -25,7 +26,7 @@ class User extends DAVACL\Principal implements DAV\ICollection { | ||||
|      * @throws DAV\Exception\Forbidden | ||||
|      * @return void | ||||
|      */ | ||||
|     public function createFile($name, $data = null) { | ||||
|     function createFile($name, $data = null) { | ||||
| 
 | ||||
|         throw new DAV\Exception\Forbidden('Permission denied to create file (filename ' . $name . ')'); | ||||
| 
 | ||||
| @@ -38,7 +39,7 @@ class User extends DAVACL\Principal implements DAV\ICollection { | ||||
|      * @throws DAV\Exception\Forbidden | ||||
|      * @return void | ||||
|      */ | ||||
|     public function createDirectory($name) { | ||||
|     function createDirectory($name) { | ||||
| 
 | ||||
|         throw new DAV\Exception\Forbidden('Permission denied to create directory'); | ||||
| 
 | ||||
| @@ -50,7 +51,7 @@ class User extends DAVACL\Principal implements DAV\ICollection { | ||||
|      * @param string $name | ||||
|      * @return DAV\INode | ||||
|      */ | ||||
|     public function getChild($name) { | ||||
|     function getChild($name) { | ||||
| 
 | ||||
|         $principal = $this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/' . $name); | ||||
|         if (!$principal) { | ||||
| @@ -71,9 +72,9 @@ class User extends DAVACL\Principal implements DAV\ICollection { | ||||
|      * | ||||
|      * @return DAV\INode[] | ||||
|      */ | ||||
|     public function getChildren() { | ||||
|     function getChildren() { | ||||
| 
 | ||||
|         $r = array(); | ||||
|         $r = []; | ||||
|         if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-read')) { | ||||
|             $r[] = new ProxyRead($this->principalBackend, $this->principalProperties); | ||||
|         } | ||||
| @@ -91,7 +92,7 @@ class User extends DAVACL\Principal implements DAV\ICollection { | ||||
|      * @param string $name | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function childExists($name) { | ||||
|     function childExists($name) { | ||||
| 
 | ||||
|         try { | ||||
|             $this->getChild($name); | ||||
| @@ -114,19 +115,19 @@ class User extends DAVACL\Principal implements DAV\ICollection { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getACL() { | ||||
|     function getACL() { | ||||
| 
 | ||||
|         $acl = parent::getACL(); | ||||
|         $acl[] = array( | ||||
|         $acl[] = [ | ||||
|             'privilege' => '{DAV:}read', | ||||
|             'principal' => $this->principalProperties['uri'] . '/calendar-proxy-read', | ||||
|             'protected' => true, | ||||
|         ); | ||||
|         $acl[] = array( | ||||
|         ]; | ||||
|         $acl[] = [ | ||||
|             'privilege' => '{DAV:}read', | ||||
|             'principal' => $this->principalProperties['uri'] . '/calendar-proxy-write', | ||||
|             'protected' => true, | ||||
|         ); | ||||
|         ]; | ||||
|         return $acl; | ||||
| 
 | ||||
|     } | ||||
							
								
								
									
										15
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/IInbox.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/IInbox.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| <?php | ||||
|  | ||||
| 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 { | ||||
|  | ||||
| } | ||||
							
								
								
									
										190
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/IMipPlugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/IMipPlugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| <?php | ||||
|  | ||||
| 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; | ||||
|  | ||||
|     /** | ||||
|      * ITipMessage | ||||
|      * | ||||
|      * @var ITip\Message | ||||
|      */ | ||||
|     protected $itipMessage; | ||||
|  | ||||
|     /** | ||||
|      * 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. | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     function getPluginName() { | ||||
|  | ||||
|         return 'imip'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Event handler for the 'schedule' event. | ||||
|      * | ||||
|      * @param ITip\Message $iTipMessage | ||||
|      * @return void | ||||
|      */ | ||||
|     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 (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto') | ||||
|             return; | ||||
|  | ||||
|         if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto') | ||||
|             return; | ||||
|  | ||||
|         $sender = substr($iTipMessage->sender, 7); | ||||
|         $recipient = substr($iTipMessage->recipient, 7); | ||||
|  | ||||
|         if ($iTipMessage->senderName) { | ||||
|             $sender = $iTipMessage->senderName . ' <' . $sender . '>'; | ||||
|         } | ||||
|         if ($iTipMessage->recipientName) { | ||||
|             $recipient = $iTipMessage->recipientName . ' <' . $recipient . '>'; | ||||
|         } | ||||
|  | ||||
|         $subject = 'SabreDAV iTIP message'; | ||||
|         switch (strtoupper($iTipMessage->method)) { | ||||
|             case 'REPLY' : | ||||
|                 $subject = 'Re: ' . $summary; | ||||
|                 break; | ||||
|             case 'REQUEST' : | ||||
|                 $subject = $summary; | ||||
|                 break; | ||||
|             case 'CANCEL' : | ||||
|                 $subject = 'Cancelled: ' . $summary; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         $headers = [ | ||||
|             'Reply-To: ' . $sender, | ||||
|             'From: ' . $this->senderEmail, | ||||
|             '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 | ||||
|      * @return void | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     function getPluginInfo() { | ||||
|  | ||||
|         return [ | ||||
|             'name'        => $this->getPluginName(), | ||||
|             'description' => 'Email delivery (rfc6037) for CalDAV scheduling', | ||||
|             'link'        => 'http://sabre.io/dav/scheduling/', | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -6,11 +6,10 @@ namespace Sabre\CalDAV\Schedule; | ||||
|  * Implement this interface to have a node be recognized as a CalDAV scheduling | ||||
|  * outbox. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @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 { | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										13
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/ISchedulingObject.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/ISchedulingObject.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <?php | ||||
|  | ||||
| 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 { | ||||
|  | ||||
| } | ||||
							
								
								
									
										261
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,261 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Schedule; | ||||
|  | ||||
| use Sabre\DAV; | ||||
| use Sabre\CalDAV; | ||||
| use Sabre\DAVACL; | ||||
| use Sabre\CalDAV\Backend; | ||||
| 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 { | ||||
|  | ||||
|     /** | ||||
|      * CalDAV backend | ||||
|      * | ||||
|      * @var Backend\BackendInterface | ||||
|      */ | ||||
|     protected $caldavBackend; | ||||
|  | ||||
|     /** | ||||
|      * The principal Uri | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $principalUri; | ||||
|  | ||||
|     /** | ||||
|      * Constructor | ||||
|      * | ||||
|      * @param Backend\SchedulingSupport $caldavBackend | ||||
|      * @param string $principalUri | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     function getName() { | ||||
|  | ||||
|         return 'inbox'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with all the child nodes | ||||
|      * | ||||
|      * @return \Sabre\DAV\INode[] | ||||
|      */ | ||||
|     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 succesful 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 null|string | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     function getOwner() { | ||||
|  | ||||
|         return $this->principalUri; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a group principal | ||||
|      * | ||||
|      * This must be a url to a principal, or null if there's no owner | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getGroup() { | ||||
|  | ||||
|         return null; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     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-invite', | ||||
|                 'principal' => '{DAV:}authenticated', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-deliver-reply', | ||||
|                 'principal' => '{DAV:}authenticated', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Updates the ACL | ||||
|      * | ||||
|      * This method will receive a list of new ACE's. | ||||
|      * | ||||
|      * @param array $acl | ||||
|      * @return void | ||||
|      */ | ||||
|     function setACL(array $acl) { | ||||
|  | ||||
|         throw new DAV\Exception\MethodNotAllowed('You\'re not allowed to update the ACL'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the list of supported privileges for this node. | ||||
|      * | ||||
|      * The returned data structure is a list of nested privileges. | ||||
|      * See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple | ||||
|      * standard structure. | ||||
|      * | ||||
|      * If null is returned from this method, the default privilege set is used, | ||||
|      * which is fine for most common usecases. | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     function getSupportedPrivilegeSet() { | ||||
|  | ||||
|         $ns = '{' . CalDAV\Plugin::NS_CALDAV . '}'; | ||||
|  | ||||
|         $default = DAVACL\Plugin::getDefaultSupportedPrivilegeSet(); | ||||
|         $default['aggregates'][] = [ | ||||
|             'privilege'  => $ns . 'schedule-deliver', | ||||
|             'aggregates' => [ | ||||
|                ['privilege' => $ns . 'schedule-deliver-invite'], | ||||
|                ['privilege' => $ns . 'schedule-deliver-reply'], | ||||
|             ], | ||||
|         ]; | ||||
|         return $default; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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. | ||||
|      * | ||||
|      * @param array $filters | ||||
|      * @return array | ||||
|      */ | ||||
|     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; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Sabre\CalDAV\Schedule; | ||||
| 
 | ||||
| use Sabre\DAV; | ||||
| use Sabre\CalDAV; | ||||
| use Sabre\DAVACL; | ||||
| @@ -12,7 +13,7 @@ use Sabre\DAVACL; | ||||
|  * free-busy requests. This functionality is completely handled by the | ||||
|  * Scheduling plugin, so this object is actually mostly static. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -30,7 +31,7 @@ class Outbox extends DAV\Collection implements IOutbox { | ||||
|      * | ||||
|      * @param string $principalUri | ||||
|      */ | ||||
|     public function __construct($principalUri) { | ||||
|     function __construct($principalUri) { | ||||
| 
 | ||||
|         $this->principalUri = $principalUri; | ||||
| 
 | ||||
| @@ -43,7 +44,7 @@ class Outbox extends DAV\Collection implements IOutbox { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getName() { | ||||
|     function getName() { | ||||
| 
 | ||||
|         return 'outbox'; | ||||
| 
 | ||||
| @@ -54,9 +55,9 @@ class Outbox extends DAV\Collection implements IOutbox { | ||||
|      * | ||||
|      * @return \Sabre\DAV\INode[] | ||||
|      */ | ||||
|     public function getChildren() { | ||||
|     function getChildren() { | ||||
| 
 | ||||
|         return array(); | ||||
|         return []; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -67,7 +68,7 @@ class Outbox extends DAV\Collection implements IOutbox { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getOwner() { | ||||
|     function getOwner() { | ||||
| 
 | ||||
|         return $this->principalUri; | ||||
| 
 | ||||
| @@ -80,7 +81,7 @@ class Outbox extends DAV\Collection implements IOutbox { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getGroup() { | ||||
|     function getGroup() { | ||||
| 
 | ||||
|         return null; | ||||
| 
 | ||||
| @@ -98,25 +99,45 @@ class Outbox extends DAV\Collection implements IOutbox { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getACL() { | ||||
|     function getACL() { | ||||
| 
 | ||||
|         return array( | ||||
|             array( | ||||
|         return [ | ||||
|             [ | ||||
|                 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|             array( | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ), | ||||
|         ); | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent', | ||||
|                 '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, | ||||
|             ], | ||||
|         ]; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| @@ -128,7 +149,7 @@ class Outbox extends DAV\Collection implements IOutbox { | ||||
|      * @param array $acl | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setACL(array $acl) { | ||||
|     function setACL(array $acl) { | ||||
| 
 | ||||
|         throw new DAV\Exception\MethodNotAllowed('You\'re not allowed to update the ACL'); | ||||
| 
 | ||||
| @@ -146,15 +167,15 @@ class Outbox extends DAV\Collection implements IOutbox { | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     public function getSupportedPrivilegeSet() { | ||||
|     function getSupportedPrivilegeSet() { | ||||
| 
 | ||||
|         $default = DAVACL\Plugin::getDefaultSupportedPrivilegeSet(); | ||||
|         $default['aggregates'][] = array( | ||||
|         $default['aggregates'][] = [ | ||||
|             'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy', | ||||
|         ); | ||||
|         $default['aggregates'][] = array( | ||||
|         ]; | ||||
|         $default['aggregates'][] = [ | ||||
|             'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent', | ||||
|         ); | ||||
|         ]; | ||||
| 
 | ||||
|         return $default; | ||||
| 
 | ||||
							
								
								
									
										994
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										994
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,994 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Schedule; | ||||
|  | ||||
| use DateTimeZone; | ||||
| use Sabre\DAV\Server; | ||||
| use Sabre\DAV\ServerPlugin; | ||||
| use Sabre\DAV\PropFind; | ||||
| use Sabre\DAV\PropPatch; | ||||
| use Sabre\DAV\INode; | ||||
| use Sabre\DAV\Xml\Property\Href; | ||||
| use Sabre\HTTP\RequestInterface; | ||||
| use Sabre\HTTP\ResponseInterface; | ||||
| use Sabre\VObject; | ||||
| use Sabre\VObject\Reader; | ||||
| use Sabre\VObject\Component\VCalendar; | ||||
| use Sabre\VObject\ITip; | ||||
| use Sabre\VObject\ITip\Message; | ||||
| use Sabre\DAVACL; | ||||
| use Sabre\CalDAV\ICalendar; | ||||
| use Sabre\CalDAV\ICalendarObject; | ||||
| use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp; | ||||
| use Sabre\DAV\Exception\NotFound; | ||||
| use Sabre\DAV\Exception\Forbidden; | ||||
| use Sabre\DAV\Exception\BadRequest; | ||||
| use Sabre\DAV\Exception\NotImplemented; | ||||
|  | ||||
| /** | ||||
|  * CalDAV scheduling plugin. | ||||
|  * ========================= | ||||
|  * | ||||
|  * This plugin provides the functionality added by the "Scheduling Extensions | ||||
|  * to CalDAV" standard, as defined in RFC6638. | ||||
|  * | ||||
|  * calendar-auto-schedule largely works by intercepting a users request to | ||||
|  * update their local calendar. If a user creates a new event with attendees, | ||||
|  * this plugin is supposed to grab the information from that event, and notify | ||||
|  * the attendees of this. | ||||
|  * | ||||
|  * There's 3 possible transports for this: | ||||
|  * * local delivery | ||||
|  * * delivery through email (iMip) | ||||
|  * * server-to-server delivery (iSchedule) | ||||
|  * | ||||
|  * iMip is simply, because we just need to add the iTip message as an email | ||||
|  * attachment. Local delivery is harder, because we both need to add this same | ||||
|  * message to a local DAV inbox, as well as live-update the relevant events. | ||||
|  * | ||||
|  * iSchedule is something for later. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class Plugin extends ServerPlugin { | ||||
|  | ||||
|     /** | ||||
|      * This is the official CalDAV namespace | ||||
|      */ | ||||
|     const NS_CALDAV = 'urn:ietf:params:xml:ns:caldav'; | ||||
|  | ||||
|     /** | ||||
|      * Reference to main Server object. | ||||
|      * | ||||
|      * @var Server | ||||
|      */ | ||||
|     protected $server; | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of features for the DAV: HTTP header. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     function getFeatures() { | ||||
|  | ||||
|         return ['calendar-auto-schedule', 'calendar-availability']; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the name of the plugin. | ||||
|      * | ||||
|      * Using this name other plugins will be able to access other plugins | ||||
|      * using Server::getPlugin | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     function getPluginName() { | ||||
|  | ||||
|         return 'caldav-schedule'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Initializes the plugin | ||||
|      * | ||||
|      * @param Server $server | ||||
|      * @return void | ||||
|      */ | ||||
|     function initialize(Server $server) { | ||||
|  | ||||
|         $this->server = $server; | ||||
|         $server->on('method:POST',          [$this, 'httpPost']); | ||||
|         $server->on('propFind',             [$this, 'propFind']); | ||||
|         $server->on('propPatch',            [$this, 'propPatch']); | ||||
|         $server->on('calendarObjectChange', [$this, 'calendarObjectChange']); | ||||
|         $server->on('beforeUnbind',         [$this, 'beforeUnbind']); | ||||
|         $server->on('schedule',             [$this, 'scheduleLocalDelivery']); | ||||
|  | ||||
|         $ns = '{' . self::NS_CALDAV . '}'; | ||||
|  | ||||
|         /** | ||||
|          * This information ensures that the {DAV:}resourcetype property has | ||||
|          * the correct values. | ||||
|          */ | ||||
|         $server->resourceTypeMapping['\\Sabre\\CalDAV\\Schedule\\IOutbox'] = $ns . 'schedule-outbox'; | ||||
|         $server->resourceTypeMapping['\\Sabre\\CalDAV\\Schedule\\IInbox'] = $ns . 'schedule-inbox'; | ||||
|  | ||||
|         /** | ||||
|          * Properties we protect are made read-only by the server. | ||||
|          */ | ||||
|         array_push($server->protectedProperties, | ||||
|             $ns . 'schedule-inbox-URL', | ||||
|             $ns . 'schedule-outbox-URL', | ||||
|             $ns . 'calendar-user-address-set', | ||||
|             $ns . 'calendar-user-type', | ||||
|             $ns . 'schedule-default-calendar-URL' | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Use this method to tell the server this plugin defines additional | ||||
|      * HTTP methods. | ||||
|      * | ||||
|      * This method is passed a uri. It should only return HTTP methods that are | ||||
|      * available for the specified uri. | ||||
|      * | ||||
|      * @param string $uri | ||||
|      * @return array | ||||
|      */ | ||||
|     function getHTTPMethods($uri) { | ||||
|  | ||||
|         try { | ||||
|             $node = $this->server->tree->getNodeForPath($uri); | ||||
|         } catch (NotFound $e) { | ||||
|             return []; | ||||
|         } | ||||
|  | ||||
|         if ($node instanceof IOutbox) { | ||||
|             return ['POST']; | ||||
|         } | ||||
|  | ||||
|         return []; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method handles POST request for the outbox. | ||||
|      * | ||||
|      * @param RequestInterface $request | ||||
|      * @param ResponseInterface $response | ||||
|      * @return bool | ||||
|      */ | ||||
|     function httpPost(RequestInterface $request, ResponseInterface $response) { | ||||
|  | ||||
|         // Checking if this is a text/calendar content type | ||||
|         $contentType = $request->getHeader('Content-Type'); | ||||
|         if (strpos($contentType, 'text/calendar') !== 0) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $path = $request->getPath(); | ||||
|  | ||||
|         // Checking if we're talking to an outbox | ||||
|         try { | ||||
|             $node = $this->server->tree->getNodeForPath($path); | ||||
|         } catch (NotFound $e) { | ||||
|             return; | ||||
|         } | ||||
|         if (!$node instanceof IOutbox) | ||||
|             return; | ||||
|  | ||||
|         $this->server->transactionType = 'post-caldav-outbox'; | ||||
|         $this->outboxRequest($node, $request, $response); | ||||
|  | ||||
|         // Returning false breaks the event chain and tells the server we've | ||||
|         // handled the request. | ||||
|         return false; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method handler is invoked during fetching of properties. | ||||
|      * | ||||
|      * We use this event to add calendar-auto-schedule-specific properties. | ||||
|      * | ||||
|      * @param PropFind $propFind | ||||
|      * @param INode $node | ||||
|      * @return void | ||||
|      */ | ||||
|     function propFind(PropFind $propFind, INode $node) { | ||||
|  | ||||
|         if ($node instanceof DAVACL\IPrincipal) { | ||||
|  | ||||
|             $caldavPlugin = $this->server->getPlugin('caldav'); | ||||
|             $principalUrl = $node->getPrincipalUrl(); | ||||
|  | ||||
|             // schedule-outbox-URL property | ||||
|             $propFind->handle('{' . self::NS_CALDAV . '}schedule-outbox-URL', function() use ($principalUrl, $caldavPlugin) { | ||||
|  | ||||
|                 $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl); | ||||
|                 if (!$calendarHomePath) { | ||||
|                     return null; | ||||
|                 } | ||||
|                 $outboxPath = $calendarHomePath . '/outbox/'; | ||||
|  | ||||
|                 return new Href($outboxPath); | ||||
|  | ||||
|             }); | ||||
|             // schedule-inbox-URL property | ||||
|             $propFind->handle('{' . self::NS_CALDAV . '}schedule-inbox-URL', function() use ($principalUrl, $caldavPlugin) { | ||||
|  | ||||
|                 $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl); | ||||
|                 if (!$calendarHomePath) { | ||||
|                     return null; | ||||
|                 } | ||||
|                 $inboxPath = $calendarHomePath . '/inbox/'; | ||||
|  | ||||
|                 return new Href($inboxPath); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|             $propFind->handle('{' . self::NS_CALDAV . '}schedule-default-calendar-URL', function() use ($principalUrl, $caldavPlugin) { | ||||
|  | ||||
|                 // We don't support customizing this property yet, so in the | ||||
|                 // meantime we just grab the first calendar in the home-set. | ||||
|                 $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl); | ||||
|  | ||||
|                 if (!$calendarHomePath) { | ||||
|                     return null; | ||||
|                 } | ||||
|  | ||||
|                 $sccs = '{' . self::NS_CALDAV . '}supported-calendar-component-set'; | ||||
|  | ||||
|                 $result = $this->server->getPropertiesForPath($calendarHomePath, [ | ||||
|                     '{DAV:}resourcetype', | ||||
|                     $sccs, | ||||
|                 ], 1); | ||||
|  | ||||
|                 foreach ($result as $child) { | ||||
|                     if (!isset($child[200]['{DAV:}resourcetype']) || !$child[200]['{DAV:}resourcetype']->is('{' . self::NS_CALDAV . '}calendar') || $child[200]['{DAV:}resourcetype']->is('{http://calendarserver.org/ns/}shared')) { | ||||
|                         // Node is either not a calendar or a shared instance. | ||||
|                         continue; | ||||
|                     } | ||||
|                     if (!isset($child[200][$sccs]) || in_array('VEVENT', $child[200][$sccs]->getValue())) { | ||||
|                         // Either there is no supported-calendar-component-set | ||||
|                         // (which is fine) or we found one that supports VEVENT. | ||||
|                         return new Href($child['href']); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|             }); | ||||
|  | ||||
|             // The server currently reports every principal to be of type | ||||
|             // 'INDIVIDUAL' | ||||
|             $propFind->handle('{' . self::NS_CALDAV . '}calendar-user-type', function() { | ||||
|  | ||||
|                 return 'INDIVIDUAL'; | ||||
|  | ||||
|             }); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // Mapping the old property to the new property. | ||||
|         $propFind->handle('{http://calendarserver.org/ns/}calendar-availability', function() use ($propFind, $node) { | ||||
|  | ||||
|              // In case it wasn't clear, the only difference is that we map the | ||||
|             // old property to a different namespace. | ||||
|              $availProp = '{' . self::NS_CALDAV . '}calendar-availability'; | ||||
|              $subPropFind = new PropFind( | ||||
|                  $propFind->getPath(), | ||||
|                  [$availProp] | ||||
|              ); | ||||
|  | ||||
|              $this->server->getPropertiesByNode( | ||||
|                  $subPropFind, | ||||
|                  $node | ||||
|              ); | ||||
|  | ||||
|              $propFind->set( | ||||
|                  '{http://calendarserver.org/ns/}calendar-availability', | ||||
|                  $subPropFind->get($availProp), | ||||
|                  $subPropFind->getStatus($availProp) | ||||
|              ); | ||||
|  | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is called during property updates. | ||||
|      * | ||||
|      * @param string $path | ||||
|      * @param PropPatch $propPatch | ||||
|      * @return void | ||||
|      */ | ||||
|     function propPatch($path, PropPatch $propPatch) { | ||||
|  | ||||
|         // Mapping the old property to the new property. | ||||
|         $propPatch->handle('{http://calendarserver.org/ns/}calendar-availability', function($value) use ($path) { | ||||
|  | ||||
|             $availProp = '{' . self::NS_CALDAV . '}calendar-availability'; | ||||
|             $subPropPatch = new PropPatch([$availProp => $value]); | ||||
|             $this->server->emit('propPatch', [$path, $subPropPatch]); | ||||
|             $subPropPatch->commit(); | ||||
|  | ||||
|             return $subPropPatch->getResult()[$availProp]; | ||||
|  | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is triggered whenever there was a calendar object gets | ||||
|      * created or updated. | ||||
|      * | ||||
|      * @param RequestInterface $request HTTP request | ||||
|      * @param ResponseInterface $response HTTP Response | ||||
|      * @param VCalendar $vCal Parsed iCalendar object | ||||
|      * @param mixed $calendarPath Path to calendar collection | ||||
|      * @param mixed $modified The iCalendar object has been touched. | ||||
|      * @param mixed $isNew Whether this was a new item or we're updating one | ||||
|      * @return void | ||||
|      */ | ||||
|     function calendarObjectChange(RequestInterface $request, ResponseInterface $response, VCalendar $vCal, $calendarPath, &$modified, $isNew) { | ||||
|  | ||||
|         if (!$this->scheduleReply($this->server->httpRequest)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $calendarNode = $this->server->tree->getNodeForPath($calendarPath); | ||||
|  | ||||
|         $addresses = $this->getAddressesForPrincipal( | ||||
|             $calendarNode->getOwner() | ||||
|         ); | ||||
|  | ||||
|         if (!$isNew) { | ||||
|             $node = $this->server->tree->getNodeForPath($request->getPath()); | ||||
|             $oldObj = Reader::read($node->get()); | ||||
|         } else { | ||||
|             $oldObj = null; | ||||
|         } | ||||
|  | ||||
|         $this->processICalendarChange($oldObj, $vCal, $addresses, [], $modified); | ||||
|  | ||||
|         if ($oldObj) { | ||||
|             // Destroy circular references so PHP will GC the object. | ||||
|             $oldObj->destroy(); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is responsible for delivering the ITip message. | ||||
|      * | ||||
|      * @param ITip\Message $itipMessage | ||||
|      * @return void | ||||
|      */ | ||||
|     function deliver(ITip\Message $iTipMessage) { | ||||
|  | ||||
|         $this->server->emit('schedule', [$iTipMessage]); | ||||
|         if (!$iTipMessage->scheduleStatus) { | ||||
|             $iTipMessage->scheduleStatus = '5.2;There was no system capable of delivering the scheduling message'; | ||||
|         } | ||||
|         // In case the change was considered 'insignificant', we are going to | ||||
|         // remove any error statuses, if any. See ticket #525. | ||||
|         list($baseCode) = explode('.', $iTipMessage->scheduleStatus); | ||||
|         if (!$iTipMessage->significantChange && in_array($baseCode, ['3', '5'])) { | ||||
|             $iTipMessage->scheduleStatus = null; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is triggered before a file gets deleted. | ||||
|      * | ||||
|      * We use this event to make sure that when this happens, attendees get | ||||
|      * cancellations, and organizers get 'DECLINED' statuses. | ||||
|      * | ||||
|      * @param string $path | ||||
|      * @return void | ||||
|      */ | ||||
|     function beforeUnbind($path) { | ||||
|  | ||||
|         // FIXME: We shouldn't trigger this functionality when we're issuing a | ||||
|         // MOVE. This is a hack. | ||||
|         if ($this->server->httpRequest->getMethod() === 'MOVE') return; | ||||
|  | ||||
|         $node = $this->server->tree->getNodeForPath($path); | ||||
|  | ||||
|         if (!$node instanceof ICalendarObject || $node instanceof ISchedulingObject) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!$this->scheduleReply($this->server->httpRequest)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $addresses = $this->getAddressesForPrincipal( | ||||
|             $node->getOwner() | ||||
|         ); | ||||
|  | ||||
|         $broker = new ITip\Broker(); | ||||
|         $messages = $broker->parseEvent(null, $addresses, $node->get()); | ||||
|  | ||||
|         foreach ($messages as $message) { | ||||
|             $this->deliver($message); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Event handler for the 'schedule' event. | ||||
|      * | ||||
|      * This handler attempts to look at local accounts to deliver the | ||||
|      * scheduling object. | ||||
|      * | ||||
|      * @param ITip\Message $iTipMessage | ||||
|      * @return void | ||||
|      */ | ||||
|     function scheduleLocalDelivery(ITip\Message $iTipMessage) { | ||||
|  | ||||
|         $aclPlugin = $this->server->getPlugin('acl'); | ||||
|  | ||||
|         // Local delivery is not available if the ACL plugin is not loaded. | ||||
|         if (!$aclPlugin) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $caldavNS = '{' . self::NS_CALDAV . '}'; | ||||
|  | ||||
|         $principalUri = $aclPlugin->getPrincipalByUri($iTipMessage->recipient); | ||||
|         if (!$principalUri) { | ||||
|             $iTipMessage->scheduleStatus = '3.7;Could not find principal.'; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // We found a principal URL, now we need to find its inbox. | ||||
|         // Unfortunately we may not have sufficient privileges to find this, so | ||||
|         // we are temporarily turning off ACL to let this come through. | ||||
|         // | ||||
|         // Once we support PHP 5.5, this should be wrapped in a try..finally | ||||
|         // block so we can ensure that this privilege gets added again after. | ||||
|         $this->server->removeListener('propFind', [$aclPlugin, 'propFind']); | ||||
|  | ||||
|         $result = $this->server->getProperties( | ||||
|             $principalUri, | ||||
|             [ | ||||
|                 '{DAV:}principal-URL', | ||||
|                  $caldavNS . 'calendar-home-set', | ||||
|                  $caldavNS . 'schedule-inbox-URL', | ||||
|                  $caldavNS . 'schedule-default-calendar-URL', | ||||
|                 '{http://sabredav.org/ns}email-address', | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         // Re-registering the ACL event | ||||
|         $this->server->on('propFind', [$aclPlugin, 'propFind'], 20); | ||||
|  | ||||
|         if (!isset($result[$caldavNS . 'schedule-inbox-URL'])) { | ||||
|             $iTipMessage->scheduleStatus = '5.2;Could not find local inbox'; | ||||
|             return; | ||||
|         } | ||||
|         if (!isset($result[$caldavNS . 'calendar-home-set'])) { | ||||
|             $iTipMessage->scheduleStatus = '5.2;Could not locate a calendar-home-set'; | ||||
|             return; | ||||
|         } | ||||
|         if (!isset($result[$caldavNS . 'schedule-default-calendar-URL'])) { | ||||
|             $iTipMessage->scheduleStatus = '5.2;Could not find a schedule-default-calendar-URL property'; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $calendarPath = $result[$caldavNS . 'schedule-default-calendar-URL']->getHref(); | ||||
|         $homePath = $result[$caldavNS . 'calendar-home-set']->getHref(); | ||||
|         $inboxPath = $result[$caldavNS . 'schedule-inbox-URL']->getHref(); | ||||
|  | ||||
|         if ($iTipMessage->method === 'REPLY') { | ||||
|             $privilege = 'schedule-deliver-reply'; | ||||
|         } else { | ||||
|             $privilege = 'schedule-deliver-invite'; | ||||
|         } | ||||
|  | ||||
|         if (!$aclPlugin->checkPrivileges($inboxPath, $caldavNS . $privilege, DAVACL\Plugin::R_PARENT, false)) { | ||||
|             $iTipMessage->scheduleStatus = '3.8;organizer did not have the ' . $privilege . ' privilege on the attendees inbox'; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Next, we're going to find out if the item already exits in one of | ||||
|         // the users' calendars. | ||||
|         $uid = $iTipMessage->uid; | ||||
|  | ||||
|         $newFileName = 'sabredav-' . \Sabre\DAV\UUIDUtil::getUUID() . '.ics'; | ||||
|  | ||||
|         $home = $this->server->tree->getNodeForPath($homePath); | ||||
|         $inbox = $this->server->tree->getNodeForPath($inboxPath); | ||||
|  | ||||
|         $currentObject = null; | ||||
|         $objectNode = null; | ||||
|         $isNewNode = false; | ||||
|  | ||||
|         $result = $home->getCalendarObjectByUID($uid); | ||||
|         if ($result) { | ||||
|             // There was an existing object, we need to update probably. | ||||
|             $objectPath = $homePath . '/' . $result; | ||||
|             $objectNode = $this->server->tree->getNodeForPath($objectPath); | ||||
|             $oldICalendarData = $objectNode->get(); | ||||
|             $currentObject = Reader::read($oldICalendarData); | ||||
|         } else { | ||||
|             $isNewNode = true; | ||||
|         } | ||||
|  | ||||
|         $broker = new ITip\Broker(); | ||||
|         $newObject = $broker->processMessage($iTipMessage, $currentObject); | ||||
|  | ||||
|         $inbox->createFile($newFileName, $iTipMessage->message->serialize()); | ||||
|  | ||||
|         if (!$newObject) { | ||||
|             // We received an iTip message referring to a UID that we don't | ||||
|             // have in any calendars yet, and processMessage did not give us a | ||||
|             // calendarobject back. | ||||
|             // | ||||
|             // The implication is that processMessage did not understand the | ||||
|             // iTip message. | ||||
|             $iTipMessage->scheduleStatus = '5.0;iTip message was not processed by the server, likely because we didn\'t understand it.'; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Note that we are bypassing ACL on purpose by calling this directly. | ||||
|         // We may need to look a bit deeper into this later. Supporting ACL | ||||
|         // here would be nice. | ||||
|         if ($isNewNode) { | ||||
|             $calendar = $this->server->tree->getNodeForPath($calendarPath); | ||||
|             $calendar->createFile($newFileName, $newObject->serialize()); | ||||
|         } else { | ||||
|             // If the message was a reply, we may have to inform other | ||||
|             // attendees of this attendees status. Therefore we're shooting off | ||||
|             // another itipMessage. | ||||
|             if ($iTipMessage->method === 'REPLY') { | ||||
|                 $this->processICalendarChange( | ||||
|                     $oldICalendarData, | ||||
|                     $newObject, | ||||
|                     [$iTipMessage->recipient], | ||||
|                     [$iTipMessage->sender] | ||||
|                 ); | ||||
|             } | ||||
|             $objectNode->put($newObject->serialize()); | ||||
|         } | ||||
|         $iTipMessage->scheduleStatus = '1.2;Message delivered locally'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method looks at an old iCalendar object, a new iCalendar object and | ||||
|      * starts sending scheduling messages based on the changes. | ||||
|      * | ||||
|      * A list of addresses needs to be specified, so the system knows who made | ||||
|      * the update, because the behavior may be different based on if it's an | ||||
|      * attendee or an organizer. | ||||
|      * | ||||
|      * This method may update $newObject to add any status changes. | ||||
|      * | ||||
|      * @param VCalendar|string $oldObject | ||||
|      * @param VCalendar $newObject | ||||
|      * @param array $addresses | ||||
|      * @param array $ignore Any addresses to not send messages to. | ||||
|      * @param bool $modified A marker to indicate that the original object | ||||
|      *   modified by this process. | ||||
|      * @return void | ||||
|      */ | ||||
|     protected function processICalendarChange($oldObject = null, VCalendar $newObject, array $addresses, array $ignore = [], &$modified = false) { | ||||
|  | ||||
|         $broker = new ITip\Broker(); | ||||
|         $messages = $broker->parseEvent($newObject, $addresses, $oldObject); | ||||
|  | ||||
|         if ($messages) $modified = true; | ||||
|  | ||||
|         foreach ($messages as $message) { | ||||
|  | ||||
|             if (in_array($message->recipient, $ignore)) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             $this->deliver($message); | ||||
|  | ||||
|             if (isset($newObject->VEVENT->ORGANIZER) && ($newObject->VEVENT->ORGANIZER->getNormalizedValue() === $message->recipient)) { | ||||
|                 if ($message->scheduleStatus) { | ||||
|                     $newObject->VEVENT->ORGANIZER['SCHEDULE-STATUS'] = $message->getScheduleStatus(); | ||||
|                 } | ||||
|                 unset($newObject->VEVENT->ORGANIZER['SCHEDULE-FORCE-SEND']); | ||||
|  | ||||
|             } else { | ||||
|  | ||||
|                 if (isset($newObject->VEVENT->ATTENDEE)) foreach ($newObject->VEVENT->ATTENDEE as $attendee) { | ||||
|  | ||||
|                     if ($attendee->getNormalizedValue() === $message->recipient) { | ||||
|                         if ($message->scheduleStatus) { | ||||
|                             $attendee['SCHEDULE-STATUS'] = $message->getScheduleStatus(); | ||||
|                         } | ||||
|                         unset($attendee['SCHEDULE-FORCE-SEND']); | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of addresses that are associated with a principal. | ||||
|      * | ||||
|      * @param string $principal | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getAddressesForPrincipal($principal) { | ||||
|  | ||||
|         $CUAS = '{' . self::NS_CALDAV . '}calendar-user-address-set'; | ||||
|  | ||||
|         $properties = $this->server->getProperties( | ||||
|             $principal, | ||||
|             [$CUAS] | ||||
|         ); | ||||
|  | ||||
|         // If we can't find this information, we'll stop processing | ||||
|         if (!isset($properties[$CUAS])) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $addresses = $properties[$CUAS]->getHrefs(); | ||||
|         return $addresses; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method handles POST requests to the schedule-outbox. | ||||
|      * | ||||
|      * Currently, two types of requests are support: | ||||
|      *   * FREEBUSY requests from RFC 6638 | ||||
|      *   * Simple iTIP messages from draft-desruisseaux-caldav-sched-04 | ||||
|      * | ||||
|      * The latter is from an expired early draft of the CalDAV scheduling | ||||
|      * extensions, but iCal depends on a feature from that spec, so we | ||||
|      * implement it. | ||||
|      * | ||||
|      * @param IOutbox $outboxNode | ||||
|      * @param RequestInterface $request | ||||
|      * @param ResponseInterface $response | ||||
|      * @return void | ||||
|      */ | ||||
|     function outboxRequest(IOutbox $outboxNode, RequestInterface $request, ResponseInterface $response) { | ||||
|  | ||||
|         $outboxPath = $request->getPath(); | ||||
|  | ||||
|         // Parsing the request body | ||||
|         try { | ||||
|             $vObject = VObject\Reader::read($request->getBody()); | ||||
|         } catch (VObject\ParseException $e) { | ||||
|             throw new BadRequest('The request body must be a valid iCalendar object. Parse error: ' . $e->getMessage()); | ||||
|         } | ||||
|  | ||||
|         // The incoming iCalendar object must have a METHOD property, and a | ||||
|         // component. The combination of both determines what type of request | ||||
|         // this is. | ||||
|         $componentType = null; | ||||
|         foreach ($vObject->getComponents() as $component) { | ||||
|             if ($component->name !== 'VTIMEZONE') { | ||||
|                 $componentType = $component->name; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         if (is_null($componentType)) { | ||||
|             throw new BadRequest('We expected at least one VTODO, VJOURNAL, VFREEBUSY or VEVENT component'); | ||||
|         } | ||||
|  | ||||
|         // Validating the METHOD | ||||
|         $method = strtoupper((string)$vObject->METHOD); | ||||
|         if (!$method) { | ||||
|             throw new BadRequest('A METHOD property must be specified in iTIP messages'); | ||||
|         } | ||||
|  | ||||
|         // So we support one type of request: | ||||
|         // | ||||
|         // REQUEST with a VFREEBUSY component | ||||
|  | ||||
|         $acl = $this->server->getPlugin('acl'); | ||||
|  | ||||
|         if ($componentType === 'VFREEBUSY' && $method === 'REQUEST') { | ||||
|  | ||||
|             $acl && $acl->checkPrivileges($outboxPath, '{' . self::NS_CALDAV . '}schedule-query-freebusy'); | ||||
|             $this->handleFreeBusyRequest($outboxNode, $vObject, $request, $response); | ||||
|  | ||||
|             // Destroy circular references so PHP can GC the object. | ||||
|             $vObject->destroy(); | ||||
|             unset($vObject); | ||||
|  | ||||
|         } else { | ||||
|  | ||||
|             throw new NotImplemented('We only support VFREEBUSY (REQUEST) on this endpoint'); | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is responsible for parsing a free-busy query request and | ||||
|      * returning it's result. | ||||
|      * | ||||
|      * @param IOutbox $outbox | ||||
|      * @param VObject\Component $vObject | ||||
|      * @param RequestInterface $request | ||||
|      * @param ResponseInterface $response | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function handleFreeBusyRequest(IOutbox $outbox, VObject\Component $vObject, RequestInterface $request, ResponseInterface $response) { | ||||
|  | ||||
|         $vFreeBusy = $vObject->VFREEBUSY; | ||||
|         $organizer = $vFreeBusy->organizer; | ||||
|  | ||||
|         $organizer = (string)$organizer; | ||||
|  | ||||
|         // Validating if the organizer matches the owner of the inbox. | ||||
|         $owner = $outbox->getOwner(); | ||||
|  | ||||
|         $caldavNS = '{' . self::NS_CALDAV . '}'; | ||||
|  | ||||
|         $uas = $caldavNS . 'calendar-user-address-set'; | ||||
|         $props = $this->server->getProperties($owner, [$uas]); | ||||
|  | ||||
|         if (empty($props[$uas]) || !in_array($organizer, $props[$uas]->getHrefs())) { | ||||
|             throw new Forbidden('The organizer in the request did not match any of the addresses for the owner of this inbox'); | ||||
|         } | ||||
|  | ||||
|         if (!isset($vFreeBusy->ATTENDEE)) { | ||||
|             throw new BadRequest('You must at least specify 1 attendee'); | ||||
|         } | ||||
|  | ||||
|         $attendees = []; | ||||
|         foreach ($vFreeBusy->ATTENDEE as $attendee) { | ||||
|             $attendees[] = (string)$attendee; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         if (!isset($vFreeBusy->DTSTART) || !isset($vFreeBusy->DTEND)) { | ||||
|             throw new BadRequest('DTSTART and DTEND must both be specified'); | ||||
|         } | ||||
|  | ||||
|         $startRange = $vFreeBusy->DTSTART->getDateTime(); | ||||
|         $endRange = $vFreeBusy->DTEND->getDateTime(); | ||||
|  | ||||
|         $results = []; | ||||
|         foreach ($attendees as $attendee) { | ||||
|             $results[] = $this->getFreeBusyForEmail($attendee, $startRange, $endRange, $vObject); | ||||
|         } | ||||
|  | ||||
|         $dom = new \DOMDocument('1.0', 'utf-8'); | ||||
|         $dom->formatOutput = true; | ||||
|         $scheduleResponse = $dom->createElement('cal:schedule-response'); | ||||
|         foreach ($this->server->xml->namespaceMap as $namespace => $prefix) { | ||||
|  | ||||
|             $scheduleResponse->setAttribute('xmlns:' . $prefix, $namespace); | ||||
|  | ||||
|         } | ||||
|         $dom->appendChild($scheduleResponse); | ||||
|  | ||||
|         foreach ($results as $result) { | ||||
|             $xresponse = $dom->createElement('cal:response'); | ||||
|  | ||||
|             $recipient = $dom->createElement('cal:recipient'); | ||||
|             $recipientHref = $dom->createElement('d:href'); | ||||
|  | ||||
|             $recipientHref->appendChild($dom->createTextNode($result['href'])); | ||||
|             $recipient->appendChild($recipientHref); | ||||
|             $xresponse->appendChild($recipient); | ||||
|  | ||||
|             $reqStatus = $dom->createElement('cal:request-status'); | ||||
|             $reqStatus->appendChild($dom->createTextNode($result['request-status'])); | ||||
|             $xresponse->appendChild($reqStatus); | ||||
|  | ||||
|             if (isset($result['calendar-data'])) { | ||||
|  | ||||
|                 $calendardata = $dom->createElement('cal:calendar-data'); | ||||
|                 $calendardata->appendChild($dom->createTextNode(str_replace("\r\n", "\n", $result['calendar-data']->serialize()))); | ||||
|                 $xresponse->appendChild($calendardata); | ||||
|  | ||||
|             } | ||||
|             $scheduleResponse->appendChild($xresponse); | ||||
|         } | ||||
|  | ||||
|         $response->setStatus(200); | ||||
|         $response->setHeader('Content-Type', 'application/xml'); | ||||
|         $response->setBody($dom->saveXML()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns free-busy information for a specific address. The returned | ||||
|      * data is an array containing the following properties: | ||||
|      * | ||||
|      * calendar-data : A VFREEBUSY VObject | ||||
|      * request-status : an iTip status code. | ||||
|      * href: The principal's email address, as requested | ||||
|      * | ||||
|      * The following request status codes may be returned: | ||||
|      *   * 2.0;description | ||||
|      *   * 3.7;description | ||||
|      * | ||||
|      * @param string $email address | ||||
|      * @param DateTimeInterface $start | ||||
|      * @param DateTimeInterface $end | ||||
|      * @param VObject\Component $request | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getFreeBusyForEmail($email, \DateTimeInterface $start, \DateTimeInterface $end, VObject\Component $request) { | ||||
|  | ||||
|         $caldavNS = '{' . self::NS_CALDAV . '}'; | ||||
|  | ||||
|         $aclPlugin = $this->server->getPlugin('acl'); | ||||
|         if (substr($email, 0, 7) === 'mailto:') $email = substr($email, 7); | ||||
|  | ||||
|         $result = $aclPlugin->principalSearch( | ||||
|             ['{http://sabredav.org/ns}email-address' => $email], | ||||
|             [ | ||||
|                 '{DAV:}principal-URL', | ||||
|                 $caldavNS . 'calendar-home-set', | ||||
|                 $caldavNS . 'schedule-inbox-URL', | ||||
|                 '{http://sabredav.org/ns}email-address', | ||||
|  | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         if (!count($result)) { | ||||
|             return [ | ||||
|                 'request-status' => '3.7;Could not find principal', | ||||
|                 'href'           => 'mailto:' . $email, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         if (!isset($result[0][200][$caldavNS . 'calendar-home-set'])) { | ||||
|             return [ | ||||
|                 'request-status' => '3.7;No calendar-home-set property found', | ||||
|                 'href'           => 'mailto:' . $email, | ||||
|             ]; | ||||
|         } | ||||
|         if (!isset($result[0][200][$caldavNS . 'schedule-inbox-URL'])) { | ||||
|             return [ | ||||
|                 'request-status' => '3.7;No schedule-inbox-URL property found', | ||||
|                 'href'           => 'mailto:' . $email, | ||||
|             ]; | ||||
|         } | ||||
|         $homeSet = $result[0][200][$caldavNS . 'calendar-home-set']->getHref(); | ||||
|         $inboxUrl = $result[0][200][$caldavNS . 'schedule-inbox-URL']->getHref(); | ||||
|  | ||||
|         // Grabbing the calendar list | ||||
|         $objects = []; | ||||
|         $calendarTimeZone = new DateTimeZone('UTC'); | ||||
|  | ||||
|         foreach ($this->server->tree->getNodeForPath($homeSet)->getChildren() as $node) { | ||||
|             if (!$node instanceof ICalendar) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             $sct = $caldavNS . 'schedule-calendar-transp'; | ||||
|             $ctz = $caldavNS . 'calendar-timezone'; | ||||
|             $props = $node->getProperties([$sct, $ctz]); | ||||
|  | ||||
|             if (isset($props[$sct]) && $props[$sct]->getValue() == ScheduleCalendarTransp::TRANSPARENT) { | ||||
|                 // If a calendar is marked as 'transparent', it means we must | ||||
|                 // ignore it for free-busy purposes. | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             $aclPlugin->checkPrivileges($homeSet . $node->getName(), $caldavNS . 'read-free-busy'); | ||||
|  | ||||
|             if (isset($props[$ctz])) { | ||||
|                 $vtimezoneObj = VObject\Reader::read($props[$ctz]); | ||||
|                 $calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone(); | ||||
|  | ||||
|                 // Destroy circular references so PHP can garbage collect the object. | ||||
|                 $vtimezoneObj->destroy(); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             // Getting the list of object uris within the time-range | ||||
|             $urls = $node->calendarQuery([ | ||||
|                 'name'         => 'VCALENDAR', | ||||
|                 'comp-filters' => [ | ||||
|                     [ | ||||
|                         'name'           => 'VEVENT', | ||||
|                         'comp-filters'   => [], | ||||
|                         'prop-filters'   => [], | ||||
|                         'is-not-defined' => false, | ||||
|                         'time-range'     => [ | ||||
|                             'start' => $start, | ||||
|                             'end'   => $end, | ||||
|                         ], | ||||
|                     ], | ||||
|                 ], | ||||
|                 'prop-filters'   => [], | ||||
|                 'is-not-defined' => false, | ||||
|                 'time-range'     => null, | ||||
|             ]); | ||||
|  | ||||
|             $calObjects = array_map(function($url) use ($node) { | ||||
|                 $obj = $node->getChild($url)->get(); | ||||
|                 return $obj; | ||||
|             }, $urls); | ||||
|  | ||||
|             $objects = array_merge($objects, $calObjects); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         $inboxProps = $this->server->getProperties( | ||||
|             $inboxUrl, | ||||
|             $caldavNS . 'calendar-availability' | ||||
|         ); | ||||
|  | ||||
|         $vcalendar = new VObject\Component\VCalendar(); | ||||
|         $vcalendar->METHOD = 'REPLY'; | ||||
|  | ||||
|         $generator = new VObject\FreeBusyGenerator(); | ||||
|         $generator->setObjects($objects); | ||||
|         $generator->setTimeRange($start, $end); | ||||
|         $generator->setBaseObject($vcalendar); | ||||
|         $generator->setTimeZone($calendarTimeZone); | ||||
|  | ||||
|         if ($inboxProps) { | ||||
|             $generator->setVAvailability( | ||||
|                 VObject\Reader::read( | ||||
|                     $inboxProps[$caldavNS . 'calendar-availability'] | ||||
|                 ) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $result = $generator->getResult(); | ||||
|  | ||||
|         $vcalendar->VFREEBUSY->ATTENDEE = 'mailto:' . $email; | ||||
|         $vcalendar->VFREEBUSY->UID = (string)$request->VFREEBUSY->UID; | ||||
|         $vcalendar->VFREEBUSY->ORGANIZER = clone $request->VFREEBUSY->ORGANIZER; | ||||
|  | ||||
|         return [ | ||||
|             'calendar-data'  => $result, | ||||
|             'request-status' => '2.0;Success', | ||||
|             'href'           => 'mailto:' . $email, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method checks the 'Schedule-Reply' header | ||||
|      * and returns false if it's 'F', otherwise true. | ||||
|      * | ||||
|      * @param RequestInterface $request | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function scheduleReply(RequestInterface $request) { | ||||
|  | ||||
|         $scheduleReply = $request->getHeader('Schedule-Reply'); | ||||
|         return $scheduleReply !== 'F'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     function getPluginInfo() { | ||||
|  | ||||
|         return [ | ||||
|             'name'        => $this->getPluginName(), | ||||
|             'description' => 'Adds calendar-auto-schedule, as defined in rf6868', | ||||
|             'link'        => 'http://sabre.io/dav/scheduling/', | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										165
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/SchedulingObject.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								vendor/sabre/dav/lib/CalDAV/Schedule/SchedulingObject.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| <?php | ||||
|  | ||||
| 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 { | ||||
|  | ||||
|     /** | ||||
|      /* The CalDAV backend | ||||
|      * | ||||
|      * @var Backend\SchedulingSupport | ||||
|      */ | ||||
|     protected $caldavBackend; | ||||
|  | ||||
|     /** | ||||
|      * Array with information about this SchedulingObject | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $objectData; | ||||
|  | ||||
|     /** | ||||
|      * 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. | ||||
|      * | ||||
|      * @param Backend\BackendInterface $caldavBackend | ||||
|      * @param array $objectData | ||||
|      */ | ||||
|     function __construct(Backend\SchedulingSupport $caldavBackend, array $objectData) { | ||||
|  | ||||
|         $this->caldavBackend = $caldavBackend; | ||||
|  | ||||
|         if (!isset($objectData['uri'])) { | ||||
|             throw new \InvalidArgumentException('The objectData argument must contain an \'uri\' property'); | ||||
|         } | ||||
|  | ||||
|         $this->objectData = $objectData; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the ICalendar-formatted object | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     function put($calendarData) { | ||||
|  | ||||
|         throw new MethodNotAllowed('Updating scheduling objects is not supported'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Deletes the scheduling message | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     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:}read', | ||||
|                 'principal' => $this->objectData['principaluri'], | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->objectData['principaluri'], | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->objectData['principaluri'] . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->objectData['principaluri'] . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->objectData['principaluri'] . '/calendar-proxy-read', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -6,7 +6,7 @@ namespace Sabre\CalDAV; | ||||
|  * This object represents a CalDAV calendar that can be shared with other | ||||
|  * users. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -30,7 +30,7 @@ class ShareableCalendar extends Calendar implements IShareableCalendar { | ||||
|      * @param array $remove | ||||
|      * @return void | ||||
|      */ | ||||
|     public function updateShares(array $add, array $remove) { | ||||
|     function updateShares(array $add, array $remove) { | ||||
| 
 | ||||
|         $this->caldavBackend->updateShares($this->calendarInfo['id'], $add, $remove); | ||||
| 
 | ||||
| @@ -48,7 +48,7 @@ class ShareableCalendar extends Calendar implements IShareableCalendar { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getShares() { | ||||
|     function getShares() { | ||||
| 
 | ||||
|         return $this->caldavBackend->getShares($this->calendarInfo['id']); | ||||
| 
 | ||||
| @@ -63,7 +63,7 @@ class ShareableCalendar extends Calendar implements IShareableCalendar { | ||||
|      * @param bool $value | ||||
|      * @return void | ||||
|      */ | ||||
|     public function setPublishStatus($value) { | ||||
|     function setPublishStatus($value) { | ||||
| 
 | ||||
|         $this->caldavBackend->setPublishStatus($this->calendarInfo['id'], $value); | ||||
| 
 | ||||
| @@ -2,12 +2,10 @@ | ||||
| 
 | ||||
| namespace Sabre\CalDAV; | ||||
| 
 | ||||
| use Sabre\DAVACL; | ||||
| 
 | ||||
| /** | ||||
|  * This object represents a CalDAV calendar that is shared by a different user. | ||||
|  * | ||||
|  * @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/). | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| @@ -19,13 +17,13 @@ class SharedCalendar extends Calendar implements ISharedCalendar { | ||||
|      * @param Backend\BackendInterface $caldavBackend | ||||
|      * @param array $calendarInfo | ||||
|      */ | ||||
|     public function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo) { | ||||
|     function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo) { | ||||
| 
 | ||||
|         $required = array( | ||||
|         $required = [ | ||||
|             '{http://calendarserver.org/ns/}shared-url', | ||||
|             '{http://sabredav.org/ns}owner-principal', | ||||
|             '{http://sabredav.org/ns}read-only', | ||||
|         ); | ||||
|         ]; | ||||
|         foreach ($required as $r) { | ||||
|             if (!isset($calendarInfo[$r])) { | ||||
|                 throw new \InvalidArgumentException('The ' . $r . ' property must be specified for SharedCalendar(s)'); | ||||
| @@ -42,7 +40,7 @@ class SharedCalendar extends Calendar implements ISharedCalendar { | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getSharedUrl() { | ||||
|     function getSharedUrl() { | ||||
| 
 | ||||
|         return $this->calendarInfo['{http://calendarserver.org/ns/}shared-url']; | ||||
| 
 | ||||
| @@ -55,7 +53,7 @@ class SharedCalendar extends Calendar implements ISharedCalendar { | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getOwner() { | ||||
|     function getOwner() { | ||||
| 
 | ||||
|         return $this->calendarInfo['{http://sabredav.org/ns}owner-principal']; | ||||
| 
 | ||||
| @@ -73,28 +71,62 @@ class SharedCalendar extends Calendar implements ISharedCalendar { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getACL() { | ||||
|     function getACL() { | ||||
| 
 | ||||
|         // The top-level ACL only contains access information for the true
 | ||||
|         // owner of the calendar, so we need to add the information for the
 | ||||
|         // sharee.
 | ||||
|         $acl = parent::getACL(); | ||||
|         $acl[] = array( | ||||
|         $acl[] = [ | ||||
|             'privilege' => '{DAV:}read', | ||||
|             'principal' => $this->calendarInfo['principaluri'], | ||||
|             'protected' => true, | ||||
|         ); | ||||
|         if (!$this->calendarInfo['{http://sabredav.org/ns}read-only']) { | ||||
|             $acl[] = array( | ||||
|         ]; | ||||
|         if ($this->calendarInfo['{http://sabredav.org/ns}read-only']) { | ||||
|             $acl[] = [ | ||||
|                 'privilege' => '{DAV:}write-properties', | ||||
|                 'principal' => $this->calendarInfo['principaluri'], | ||||
|                 'protected' => true, | ||||
|             ]; | ||||
|         } else { | ||||
|             $acl[] = [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->calendarInfo['principaluri'], | ||||
|                 'protected' => true, | ||||
|             ); | ||||
|             ]; | ||||
|         } | ||||
|         return $acl; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method returns the ACL's for calendar objects in this calendar. | ||||
|      * The result of this method automatically gets passed to the | ||||
|      * calendar-object nodes in the calendar. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     function getChildACL() { | ||||
| 
 | ||||
|         $acl = parent::getChildACL(); | ||||
|         $acl[] = [ | ||||
|             'privilege' => '{DAV:}read', | ||||
|             'principal' => $this->calendarInfo['principaluri'], | ||||
|             'protected' => true, | ||||
|         ]; | ||||
| 
 | ||||
|         if (!$this->calendarInfo['{http://sabredav.org/ns}read-only']) { | ||||
|             $acl[] = [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->calendarInfo['principaluri'], | ||||
|                 'protected' => true, | ||||
|             ]; | ||||
|         } | ||||
|         return $acl; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the list of people whom this calendar is shared with. | ||||
|      * | ||||
| @@ -107,7 +139,7 @@ class SharedCalendar extends Calendar implements ISharedCalendar { | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getShares() { | ||||
|     function getShares() { | ||||
| 
 | ||||
|         return $this->caldavBackend->getShares($this->calendarInfo['id']); | ||||
| 
 | ||||
							
								
								
									
										426
									
								
								vendor/sabre/dav/lib/CalDAV/SharingPlugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										426
									
								
								vendor/sabre/dav/lib/CalDAV/SharingPlugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,426 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV; | ||||
|  | ||||
| use Sabre\DAV; | ||||
| use Sabre\DAV\Xml\Property\Href; | ||||
| use Sabre\HTTP\RequestInterface; | ||||
| use Sabre\HTTP\ResponseInterface; | ||||
|  | ||||
| /** | ||||
|  * This plugin implements support for caldav sharing. | ||||
|  * | ||||
|  * This spec is defined at: | ||||
|  * http://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt | ||||
|  * | ||||
|  * See: | ||||
|  * Sabre\CalDAV\Backend\SharingSupport for all the documentation. | ||||
|  * | ||||
|  * Note: This feature is experimental, and may change in between different | ||||
|  * SabreDAV versions. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class SharingPlugin extends DAV\ServerPlugin { | ||||
|  | ||||
|     /** | ||||
|      * These are the various status constants used by sharing-messages. | ||||
|      */ | ||||
|     const STATUS_ACCEPTED = 1; | ||||
|     const STATUS_DECLINED = 2; | ||||
|     const STATUS_DELETED = 3; | ||||
|     const STATUS_NORESPONSE = 4; | ||||
|     const STATUS_INVALID = 5; | ||||
|  | ||||
|     /** | ||||
|      * Reference to SabreDAV server object. | ||||
|      * | ||||
|      * @var Sabre\DAV\Server | ||||
|      */ | ||||
|     protected $server; | ||||
|  | ||||
|     /** | ||||
|      * This method should return a list of server-features. | ||||
|      * | ||||
|      * This is for example 'versioning' and is added to the DAV: header | ||||
|      * in an OPTIONS response. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     function getFeatures() { | ||||
|  | ||||
|         return ['calendarserver-sharing']; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a plugin name. | ||||
|      * | ||||
|      * Using this name other plugins will be able to access other plugins | ||||
|      * using Sabre\DAV\Server::getPlugin | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     function getPluginName() { | ||||
|  | ||||
|         return 'caldav-sharing'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     function initialize(DAV\Server $server) { | ||||
|  | ||||
|         $this->server = $server; | ||||
|         $server->resourceTypeMapping['Sabre\\CalDAV\\ISharedCalendar'] = '{' . Plugin::NS_CALENDARSERVER . '}shared'; | ||||
|  | ||||
|         array_push( | ||||
|             $this->server->protectedProperties, | ||||
|             '{' . Plugin::NS_CALENDARSERVER . '}invite', | ||||
|             '{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', | ||||
|             '{' . Plugin::NS_CALENDARSERVER . '}shared-url' | ||||
|         ); | ||||
|  | ||||
|         $this->server->xml->elementMap['{' . Plugin::NS_CALENDARSERVER . '}share'] = 'Sabre\\CalDAV\\Xml\\Request\\Share'; | ||||
|         $this->server->xml->elementMap['{' . Plugin::NS_CALENDARSERVER . '}invite-reply'] = 'Sabre\\CalDAV\\Xml\\Request\\InviteReply'; | ||||
|  | ||||
|         $this->server->on('propFind',     [$this, 'propFindEarly']); | ||||
|         $this->server->on('propFind',     [$this, 'propFindLate'], 150); | ||||
|         $this->server->on('propPatch',    [$this, 'propPatch'], 40); | ||||
|         $this->server->on('method:POST',  [$this, 'httpPost']); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This event is triggered when properties are requested for a certain | ||||
|      * node. | ||||
|      * | ||||
|      * This allows us to inject any properties early. | ||||
|      * | ||||
|      * @param DAV\PropFind $propFind | ||||
|      * @param DAV\INode $node | ||||
|      * @return void | ||||
|      */ | ||||
|     function propFindEarly(DAV\PropFind $propFind, DAV\INode $node) { | ||||
|  | ||||
|         if ($node instanceof IShareableCalendar) { | ||||
|  | ||||
|             $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}invite', function() use ($node) { | ||||
|                 return new Xml\Property\Invite( | ||||
|                     $node->getShares() | ||||
|                 ); | ||||
|             }); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         if ($node instanceof ISharedCalendar) { | ||||
|  | ||||
|             $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}shared-url', function() use ($node) { | ||||
|                 return new Href( | ||||
|                     $node->getSharedUrl() | ||||
|                 ); | ||||
|             }); | ||||
|  | ||||
|             $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}invite', function() use ($node) { | ||||
|  | ||||
|                 // Fetching owner information | ||||
|                 $props = $this->server->getPropertiesForPath($node->getOwner(), [ | ||||
|                     '{http://sabredav.org/ns}email-address', | ||||
|                     '{DAV:}displayname', | ||||
|                 ], 0); | ||||
|  | ||||
|                 $ownerInfo = [ | ||||
|                     'href' => $node->getOwner(), | ||||
|                 ]; | ||||
|  | ||||
|                 if (isset($props[0][200])) { | ||||
|  | ||||
|                     // We're mapping the internal webdav properties to the | ||||
|                     // elements caldav-sharing expects. | ||||
|                     if (isset($props[0][200]['{http://sabredav.org/ns}email-address'])) { | ||||
|                         $ownerInfo['href'] = 'mailto:' . $props[0][200]['{http://sabredav.org/ns}email-address']; | ||||
|                     } | ||||
|                     if (isset($props[0][200]['{DAV:}displayname'])) { | ||||
|                         $ownerInfo['commonName'] = $props[0][200]['{DAV:}displayname']; | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|  | ||||
|                 return new Xml\Property\Invite( | ||||
|                     $node->getShares(), | ||||
|                     $ownerInfo | ||||
|                 ); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is triggered *after* all properties have been retrieved. | ||||
|      * This allows us to inject the correct resourcetype for calendars that | ||||
|      * have been shared. | ||||
|      * | ||||
|      * @param DAV\PropFind $propFind | ||||
|      * @param DAV\INode $node | ||||
|      * @return void | ||||
|      */ | ||||
|     function propFindLate(DAV\PropFind $propFind, DAV\INode $node) { | ||||
|  | ||||
|         if ($node instanceof IShareableCalendar) { | ||||
|             if ($rt = $propFind->get('{DAV:}resourcetype')) { | ||||
|                 if (count($node->getShares()) > 0) { | ||||
|                     $rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner'); | ||||
|                 } | ||||
|             } | ||||
|             $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', function() { | ||||
|                 return new Xml\Property\AllowedSharingModes(true, false); | ||||
|             }); | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method is trigged when a user attempts to update a node's | ||||
|      * properties. | ||||
|      * | ||||
|      * A previous draft of the sharing spec stated that it was possible to use | ||||
|      * PROPPATCH to remove 'shared-owner' from the resourcetype, thus unsharing | ||||
|      * the calendar. | ||||
|      * | ||||
|      * Even though this is no longer in the current spec, we keep this around | ||||
|      * because OS X 10.7 may still make use of this feature. | ||||
|      * | ||||
|      * @param string $path | ||||
|      * @param DAV\PropPatch $propPatch | ||||
|      * @return void | ||||
|      */ | ||||
|     function propPatch($path, DAV\PropPatch $propPatch) { | ||||
|  | ||||
|         $node = $this->server->tree->getNodeForPath($path); | ||||
|         if (!$node instanceof IShareableCalendar) | ||||
|             return; | ||||
|  | ||||
|         $propPatch->handle('{DAV:}resourcetype', function($value) use ($node) { | ||||
|             if ($value->is('{' . Plugin::NS_CALENDARSERVER . '}shared-owner')) return false; | ||||
|             $shares = $node->getShares(); | ||||
|             $remove = []; | ||||
|             foreach ($shares as $share) { | ||||
|                 $remove[] = $share['href']; | ||||
|             } | ||||
|             $node->updateShares([], $remove); | ||||
|  | ||||
|             return true; | ||||
|  | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * We intercept this to handle POST requests on calendars. | ||||
|      * | ||||
|      * @param RequestInterface $request | ||||
|      * @param ResponseInterface $response | ||||
|      * @return null|bool | ||||
|      */ | ||||
|     function httpPost(RequestInterface $request, ResponseInterface $response) { | ||||
|  | ||||
|         $path = $request->getPath(); | ||||
|  | ||||
|         // Only handling xml | ||||
|         $contentType = $request->getHeader('Content-Type'); | ||||
|         if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) | ||||
|             return; | ||||
|  | ||||
|         // Making sure the node exists | ||||
|         try { | ||||
|             $node = $this->server->tree->getNodeForPath($path); | ||||
|         } catch (DAV\Exception\NotFound $e) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $requestBody = $request->getBodyAsString(); | ||||
|  | ||||
|         // If this request handler could not deal with this POST request, it | ||||
|         // will return 'null' and other plugins get a chance to handle the | ||||
|         // request. | ||||
|         // | ||||
|         // However, we already requested the full body. This is a problem, | ||||
|         // because a body can only be read once. This is why we preemptively | ||||
|         // re-populated the request body with the existing data. | ||||
|         $request->setBody($requestBody); | ||||
|  | ||||
|         $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType); | ||||
|  | ||||
|         switch ($documentType) { | ||||
|  | ||||
|             // Dealing with the 'share' document, which modified invitees on a | ||||
|             // calendar. | ||||
|             case '{' . Plugin::NS_CALENDARSERVER . '}share' : | ||||
|  | ||||
|                 // We can only deal with IShareableCalendar objects | ||||
|                 if (!$node instanceof IShareableCalendar) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 $this->server->transactionType = 'post-calendar-share'; | ||||
|  | ||||
|                 // Getting ACL info | ||||
|                 $acl = $this->server->getPlugin('acl'); | ||||
|  | ||||
|                 // If there's no ACL support, we allow everything | ||||
|                 if ($acl) { | ||||
|                     $acl->checkPrivileges($path, '{DAV:}write'); | ||||
|                 } | ||||
|  | ||||
|                 $node->updateShares($message->set, $message->remove); | ||||
|  | ||||
|                 $response->setStatus(200); | ||||
|                 // Adding this because sending a response body may cause issues, | ||||
|                 // and I wanted some type of indicator the response was handled. | ||||
|                 $response->setHeader('X-Sabre-Status', 'everything-went-well'); | ||||
|  | ||||
|                 // Breaking the event chain | ||||
|                 return false; | ||||
|  | ||||
|             // The invite-reply document is sent when the user replies to an | ||||
|             // invitation of a calendar share. | ||||
|             case '{' . Plugin::NS_CALENDARSERVER . '}invite-reply' : | ||||
|  | ||||
|                 // This only works on the calendar-home-root node. | ||||
|                 if (!$node instanceof CalendarHome) { | ||||
|                     return; | ||||
|                 } | ||||
|                 $this->server->transactionType = 'post-invite-reply'; | ||||
|  | ||||
|                 // Getting ACL info | ||||
|                 $acl = $this->server->getPlugin('acl'); | ||||
|  | ||||
|                 // If there's no ACL support, we allow everything | ||||
|                 if ($acl) { | ||||
|                     $acl->checkPrivileges($path, '{DAV:}write'); | ||||
|                 } | ||||
|  | ||||
|                 $url = $node->shareReply( | ||||
|                     $message->href, | ||||
|                     $message->status, | ||||
|                     $message->calendarUri, | ||||
|                     $message->inReplyTo, | ||||
|                     $message->summary | ||||
|                 ); | ||||
|  | ||||
|                 $response->setStatus(200); | ||||
|                 // Adding this because sending a response body may cause issues, | ||||
|                 // and I wanted some type of indicator the response was handled. | ||||
|                 $response->setHeader('X-Sabre-Status', 'everything-went-well'); | ||||
|  | ||||
|                 if ($url) { | ||||
|                     $writer = $this->server->xml->getWriter($this->server->getBaseUri()); | ||||
|                     $writer->openMemory(); | ||||
|                     $writer->startDocument(); | ||||
|                     $writer->startElement('{' . Plugin::NS_CALENDARSERVER . '}shared-as'); | ||||
|                     $writer->write(new Href($url)); | ||||
|                     $writer->endElement(); | ||||
|                     $response->setHeader('Content-Type', 'application/xml'); | ||||
|                     $response->setBody($writer->outputMemory()); | ||||
|  | ||||
|                 } | ||||
|  | ||||
|                 // Breaking the event chain | ||||
|                 return false; | ||||
|  | ||||
|             case '{' . Plugin::NS_CALENDARSERVER . '}publish-calendar' : | ||||
|  | ||||
|                 // We can only deal with IShareableCalendar objects | ||||
|                 if (!$node instanceof IShareableCalendar) { | ||||
|                     return; | ||||
|                 } | ||||
|                 $this->server->transactionType = 'post-publish-calendar'; | ||||
|  | ||||
|                 // Getting ACL info | ||||
|                 $acl = $this->server->getPlugin('acl'); | ||||
|  | ||||
|                 // If there's no ACL support, we allow everything | ||||
|                 if ($acl) { | ||||
|                     $acl->checkPrivileges($path, '{DAV:}write'); | ||||
|                 } | ||||
|  | ||||
|                 $node->setPublishStatus(true); | ||||
|  | ||||
|                 // iCloud sends back the 202, so we will too. | ||||
|                 $response->setStatus(202); | ||||
|  | ||||
|                 // Adding this because sending a response body may cause issues, | ||||
|                 // and I wanted some type of indicator the response was handled. | ||||
|                 $response->setHeader('X-Sabre-Status', 'everything-went-well'); | ||||
|  | ||||
|                 // Breaking the event chain | ||||
|                 return false; | ||||
|  | ||||
|             case '{' . Plugin::NS_CALENDARSERVER . '}unpublish-calendar' : | ||||
|  | ||||
|                 // We can only deal with IShareableCalendar objects | ||||
|                 if (!$node instanceof IShareableCalendar) { | ||||
|                     return; | ||||
|                 } | ||||
|                 $this->server->transactionType = 'post-unpublish-calendar'; | ||||
|  | ||||
|                 // Getting ACL info | ||||
|                 $acl = $this->server->getPlugin('acl'); | ||||
|  | ||||
|                 // If there's no ACL support, we allow everything | ||||
|                 if ($acl) { | ||||
|                     $acl->checkPrivileges($path, '{DAV:}write'); | ||||
|                 } | ||||
|  | ||||
|                 $node->setPublishStatus(false); | ||||
|  | ||||
|                 $response->setStatus(200); | ||||
|  | ||||
|                 // Adding this because sending a response body may cause issues, | ||||
|                 // and I wanted some type of indicator the response was handled. | ||||
|                 $response->setHeader('X-Sabre-Status', 'everything-went-well'); | ||||
|  | ||||
|                 // Breaking the event chain | ||||
|                 return false; | ||||
|  | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     function getPluginInfo() { | ||||
|  | ||||
|         return [ | ||||
|             'name'        => $this->getPluginName(), | ||||
|             'description' => 'Adds support for caldav-sharing.', | ||||
|             'link'        => 'http://sabre.io/dav/caldav-sharing/', | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								vendor/sabre/dav/lib/CalDAV/Subscriptions/ISubscription.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								vendor/sabre/dav/lib/CalDAV/Subscriptions/ISubscription.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Subscriptions; | ||||
|  | ||||
| use Sabre\DAV\ICollection; | ||||
| use Sabre\DAV\IProperties; | ||||
|  | ||||
| /** | ||||
|  * ISubscription | ||||
|  * | ||||
|  * Nodes implementing this interface represent calendar subscriptions. | ||||
|  * | ||||
|  * The subscription node doesn't do much, other than returning and updating | ||||
|  * subscription-related properties. | ||||
|  * | ||||
|  * The following properties should be supported: | ||||
|  * | ||||
|  * 1. {DAV:}displayname | ||||
|  * 2. {http://apple.com/ns/ical/}refreshrate | ||||
|  * 3. {http://calendarserver.org/ns/}subscribed-strip-todos (omit if todos | ||||
|  *    should not be stripped). | ||||
|  * 4. {http://calendarserver.org/ns/}subscribed-strip-alarms (omit if alarms | ||||
|  *    should not be stripped). | ||||
|  * 5. {http://calendarserver.org/ns/}subscribed-strip-attachments (omit if | ||||
|  *    attachments should not be stripped). | ||||
|  * 6. {http://calendarserver.org/ns/}source (Must be a | ||||
|  *     Sabre\DAV\Property\Href). | ||||
|  * 7. {http://apple.com/ns/ical/}calendar-color | ||||
|  * 8. {http://apple.com/ns/ical/}calendar-order | ||||
|  * | ||||
|  * It is recommended to support every property. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| interface ISubscription extends ICollection, IProperties { | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										120
									
								
								vendor/sabre/dav/lib/CalDAV/Subscriptions/Plugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								vendor/sabre/dav/lib/CalDAV/Subscriptions/Plugin.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Subscriptions; | ||||
|  | ||||
| use Sabre\DAV\INode; | ||||
| use Sabre\DAV\PropFind; | ||||
| use Sabre\DAV\ServerPlugin; | ||||
| use Sabre\DAV\Server; | ||||
|  | ||||
| /** | ||||
|  * This plugin adds calendar-subscription support to your CalDAV server. | ||||
|  * | ||||
|  * Some clients support 'managed subscriptions' server-side. This is basically | ||||
|  * a list of subscription urls a user is using. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class Plugin extends ServerPlugin { | ||||
|  | ||||
|     /** | ||||
|      * 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 Server $server | ||||
|      * @return void | ||||
|      */ | ||||
|     function initialize(Server $server) { | ||||
|  | ||||
|         $server->resourceTypeMapping['Sabre\\CalDAV\\Subscriptions\\ISubscription'] = | ||||
|             '{http://calendarserver.org/ns/}subscribed'; | ||||
|  | ||||
|         $server->xml->elementMap['{http://calendarserver.org/ns/}source'] = | ||||
|             'Sabre\\DAV\\Xml\\Property\\Href'; | ||||
|  | ||||
|         $server->on('propFind', [$this, 'propFind'], 150); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method should return a list of server-features. | ||||
|      * | ||||
|      * This is for example 'versioning' and is added to the DAV: header | ||||
|      * in an OPTIONS response. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     function getFeatures() { | ||||
|  | ||||
|         return ['calendarserver-subscribed']; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Triggered after properties have been fetched. | ||||
|      * | ||||
|      * @param PropFind $propFind | ||||
|      * @param INode $node | ||||
|      * @return void | ||||
|      */ | ||||
|     function propFind(PropFind $propFind, INode $node) { | ||||
|  | ||||
|         // There's a bunch of properties that must appear as a self-closing | ||||
|         // xml-element. This event handler ensures that this will be the case. | ||||
|         $props = [ | ||||
|             '{http://calendarserver.org/ns/}subscribed-strip-alarms', | ||||
|             '{http://calendarserver.org/ns/}subscribed-strip-attachments', | ||||
|             '{http://calendarserver.org/ns/}subscribed-strip-todos', | ||||
|         ]; | ||||
|  | ||||
|         foreach ($props as $prop) { | ||||
|  | ||||
|             if ($propFind->getStatus($prop) === 200) { | ||||
|                 $propFind->set($prop, '', 200); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a plugin name. | ||||
|      * | ||||
|      * Using this name other plugins will be able to access other plugins | ||||
|      * using \Sabre\DAV\Server::getPlugin | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     function getPluginName() { | ||||
|  | ||||
|         return 'subscriptions'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     function getPluginInfo() { | ||||
|  | ||||
|         return [ | ||||
|             'name'        => $this->getPluginName(), | ||||
|             'description' => 'This plugin allows users to store iCalendar subscriptions in their calendar-home.', | ||||
|             'link'        => null, | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										274
									
								
								vendor/sabre/dav/lib/CalDAV/Subscriptions/Subscription.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								vendor/sabre/dav/lib/CalDAV/Subscriptions/Subscription.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,274 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Subscriptions; | ||||
|  | ||||
| use Sabre\DAV\Collection; | ||||
| use Sabre\DAV\Xml\Property\Href; | ||||
| use Sabre\DAV\PropPatch; | ||||
| use Sabre\DAV\Exception\MethodNotAllowed; | ||||
| use Sabre\DAVACL\IACL; | ||||
| use Sabre\CalDAV\Backend\SubscriptionSupport; | ||||
|  | ||||
| /** | ||||
|  * Subscription Node | ||||
|  * | ||||
|  * This node represents a subscription. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://evertpot.com/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class Subscription extends Collection implements ISubscription, IACL { | ||||
|  | ||||
|     /** | ||||
|      * caldavBackend | ||||
|      * | ||||
|      * @var SupportsSubscriptions | ||||
|      */ | ||||
|     protected $caldavBackend; | ||||
|  | ||||
|     /** | ||||
|      * subscriptionInfo | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $subscriptionInfo; | ||||
|  | ||||
|     /** | ||||
|      * Constructor | ||||
|      * | ||||
|      * @param SubscriptionSupport $caldavBackend | ||||
|      * @param array $calendarInfo | ||||
|      */ | ||||
|     function __construct(SubscriptionSupport $caldavBackend, array $subscriptionInfo) { | ||||
|  | ||||
|         $this->caldavBackend = $caldavBackend; | ||||
|         $this->subscriptionInfo = $subscriptionInfo; | ||||
|  | ||||
|         $required = [ | ||||
|             'id', | ||||
|             'uri', | ||||
|             'principaluri', | ||||
|             'source', | ||||
|             ]; | ||||
|  | ||||
|         foreach ($required as $r) { | ||||
|             if (!isset($subscriptionInfo[$r])) { | ||||
|                 throw new \InvalidArgumentException('The ' . $r . ' field is required when creating a subscription node'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the name of the node. | ||||
|      * | ||||
|      * This is used to generate the url. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     function getName() { | ||||
|  | ||||
|         return $this->subscriptionInfo['uri']; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the last modification time | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     function getLastModified() { | ||||
|  | ||||
|         if (isset($this->subscriptionInfo['lastmodified'])) { | ||||
|             return $this->subscriptionInfo['lastmodified']; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Deletes the current node | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     function delete() { | ||||
|  | ||||
|         $this->caldavBackend->deleteSubscription( | ||||
|             $this->subscriptionInfo['id'] | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with all the child nodes | ||||
|      * | ||||
|      * @return DAV\INode[] | ||||
|      */ | ||||
|     function getChildren() { | ||||
|  | ||||
|         return []; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Updates properties on this node. | ||||
|      * | ||||
|      * This method received a PropPatch object, which contains all the | ||||
|      * information about the update. | ||||
|      * | ||||
|      * To update specific properties, call the 'handle' method on this object. | ||||
|      * Read the PropPatch documentation for more information. | ||||
|      * | ||||
|      * @param PropPatch $propPatch | ||||
|      * @return void | ||||
|      */ | ||||
|     function propPatch(PropPatch $propPatch) { | ||||
|  | ||||
|         return $this->caldavBackend->updateSubscription( | ||||
|             $this->subscriptionInfo['id'], | ||||
|             $propPatch | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of properties for this nodes. | ||||
|      * | ||||
|      * The properties list is a list of propertynames the client requested, | ||||
|      * encoded in clark-notation {xmlnamespace}tagname. | ||||
|      * | ||||
|      * If the array is empty, it means 'all properties' were requested. | ||||
|      * | ||||
|      * Note that it's fine to liberally give properties back, instead of | ||||
|      * conforming to the list of requested properties. | ||||
|      * The Server class will filter out the extra. | ||||
|      * | ||||
|      * @param array $properties | ||||
|      * @return void | ||||
|      */ | ||||
|     function getProperties($properties) { | ||||
|  | ||||
|         $r = []; | ||||
|  | ||||
|         foreach ($properties as $prop) { | ||||
|  | ||||
|             switch ($prop) { | ||||
|                 case '{http://calendarserver.org/ns/}source' : | ||||
|                     $r[$prop] = new Href($this->subscriptionInfo['source'], false); | ||||
|                     break; | ||||
|                 default : | ||||
|                     if (array_key_exists($prop, $this->subscriptionInfo)) { | ||||
|                         $r[$prop] = $this->subscriptionInfo[$prop]; | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $r; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the owner principal. | ||||
|      * | ||||
|      * This must be a url to a principal, or null if there's no owner | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getOwner() { | ||||
|  | ||||
|         return $this->subscriptionInfo['principaluri']; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a group principal. | ||||
|      * | ||||
|      * This must be a url to a principal, or null if there's no owner | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     function getGroup() { | ||||
|  | ||||
|         return null; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     function getACL() { | ||||
|  | ||||
|         return [ | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->getOwner(), | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}write', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-write', | ||||
|                 'protected' => true, | ||||
|             ], | ||||
|             [ | ||||
|                 'privilege' => '{DAV:}read', | ||||
|                 'principal' => $this->getOwner() . '/calendar-proxy-read', | ||||
|                 'protected' => true, | ||||
|             ] | ||||
|         ]; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Updates the ACL. | ||||
|      * | ||||
|      * This method will receive a list of new ACE's. | ||||
|      * | ||||
|      * @param array $acl | ||||
|      * @return void | ||||
|      */ | ||||
|     function setACL(array $acl) { | ||||
|  | ||||
|         throw new MethodNotAllowed('Changing ACL is not yet supported'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the list of supported privileges for this node. | ||||
|      * | ||||
|      * The returned data structure is a list of nested privileges. | ||||
|      * See \Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple | ||||
|      * standard structure. | ||||
|      * | ||||
|      * If null is returned from this method, the default privilege set is used, | ||||
|      * which is fine for most common usecases. | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     function getSupportedPrivilegeSet() { | ||||
|  | ||||
|         return null; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										84
									
								
								vendor/sabre/dav/lib/CalDAV/Xml/Filter/CalendarData.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/sabre/dav/lib/CalDAV/Xml/Filter/CalendarData.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Xml\Filter; | ||||
|  | ||||
| use Sabre\Xml\Reader; | ||||
| use Sabre\Xml\XmlDeserializable; | ||||
| use Sabre\DAV\Exception\BadRequest; | ||||
| use Sabre\CalDAV\Plugin; | ||||
| use Sabre\VObject\DateTimeParser; | ||||
|  | ||||
| /** | ||||
|  * CalendarData parser. | ||||
|  * | ||||
|  * This class parses the {urn:ietf:params:xml:ns:caldav}calendar-data XML | ||||
|  * element, as defined in: | ||||
|  * | ||||
|  * https://tools.ietf.org/html/rfc4791#section-9.6 | ||||
|  * | ||||
|  * This element is used in three distinct places in the caldav spec, but in | ||||
|  * this case, this element class only implements the calendar-data element as | ||||
|  * it appears in a DAV:prop element, in a calendar-query or calendar-multiget | ||||
|  * REPORT request. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://www.rooftopsolutions.nl/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class CalendarData implements XmlDeserializable { | ||||
|  | ||||
|     /** | ||||
|      * The deserialize method is called during xml parsing. | ||||
|      * | ||||
|      * This method is called statictly, this is because in theory this method | ||||
|      * may be used as a type of constructor, or factory method. | ||||
|      * | ||||
|      * Often you want to return an instance of the current class, but you are | ||||
|      * free to return other data as well. | ||||
|      * | ||||
|      * You are responsible for advancing the reader to the next element. Not | ||||
|      * doing anything will result in a never-ending loop. | ||||
|      * | ||||
|      * If you just want to skip parsing for this element altogether, you can | ||||
|      * just call $reader->next(); | ||||
|      * | ||||
|      * $reader->parseInnerTree() will parse the entire sub-tree, and advance to | ||||
|      * the next element. | ||||
|      * | ||||
|      * @param Reader $reader | ||||
|      * @return mixed | ||||
|      */ | ||||
|     static function xmlDeserialize(Reader $reader) { | ||||
|  | ||||
|         $result = [ | ||||
|             'contentType' => $reader->getAttribute('content-type') ?: 'text/calendar', | ||||
|             'version'     => $reader->getAttribute('version') ?: '2.0', | ||||
|         ]; | ||||
|  | ||||
|         $elems = (array)$reader->parseInnerTree(); | ||||
|         foreach ($elems as $elem) { | ||||
|  | ||||
|             switch ($elem['name']) { | ||||
|                 case '{' . Plugin::NS_CALDAV . '}expand' : | ||||
|  | ||||
|                     $result['expand'] = [ | ||||
|                         'start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null, | ||||
|                         'end'   => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null, | ||||
|                     ]; | ||||
|  | ||||
|                     if (!$result['expand']['start'] || !$result['expand']['end']) { | ||||
|                         throw new BadRequest('The "start" and "end" attributes are required when expanding calendar-data'); | ||||
|                     } | ||||
|                     if ($result['expand']['end'] <= $result['expand']['start']) { | ||||
|                         throw new BadRequest('The end-date must be larger than the start-date when expanding calendar-data'); | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										97
									
								
								vendor/sabre/dav/lib/CalDAV/Xml/Filter/CompFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/sabre/dav/lib/CalDAV/Xml/Filter/CompFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Xml\Filter; | ||||
|  | ||||
| use Sabre\Xml\Reader; | ||||
| use Sabre\Xml\XmlDeserializable; | ||||
| use Sabre\DAV\Exception\BadRequest; | ||||
| use Sabre\CalDAV\Plugin; | ||||
| use Sabre\VObject\DateTimeParser; | ||||
|  | ||||
| /** | ||||
|  * CompFilter parser. | ||||
|  * | ||||
|  * This class parses the {urn:ietf:params:xml:ns:caldav}comp-filter XML | ||||
|  * element, as defined in: | ||||
|  * | ||||
|  * https://tools.ietf.org/html/rfc4791#section-9.6 | ||||
|  * | ||||
|  * The result will be spit out as an array. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://www.rooftopsolutions.nl/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class CompFilter implements XmlDeserializable { | ||||
|  | ||||
|     /** | ||||
|      * The deserialize method is called during xml parsing. | ||||
|      * | ||||
|      * This method is called statictly, this is because in theory this method | ||||
|      * may be used as a type of constructor, or factory method. | ||||
|      * | ||||
|      * Often you want to return an instance of the current class, but you are | ||||
|      * free to return other data as well. | ||||
|      * | ||||
|      * You are responsible for advancing the reader to the next element. Not | ||||
|      * doing anything will result in a never-ending loop. | ||||
|      * | ||||
|      * If you just want to skip parsing for this element altogether, you can | ||||
|      * just call $reader->next(); | ||||
|      * | ||||
|      * $reader->parseInnerTree() will parse the entire sub-tree, and advance to | ||||
|      * the next element. | ||||
|      * | ||||
|      * @param Reader $reader | ||||
|      * @return mixed | ||||
|      */ | ||||
|     static function xmlDeserialize(Reader $reader) { | ||||
|  | ||||
|         $result = [ | ||||
|             'name'           => null, | ||||
|             'is-not-defined' => false, | ||||
|             'comp-filters'   => [], | ||||
|             'prop-filters'   => [], | ||||
|             'time-range'     => false, | ||||
|         ]; | ||||
|  | ||||
|         $att = $reader->parseAttributes(); | ||||
|         $result['name'] = $att['name']; | ||||
|  | ||||
|         $elems = $reader->parseInnerTree(); | ||||
|  | ||||
|         if (is_array($elems)) foreach ($elems as $elem) { | ||||
|  | ||||
|             switch ($elem['name']) { | ||||
|  | ||||
|                 case '{' . Plugin::NS_CALDAV . '}comp-filter' : | ||||
|                     $result['comp-filters'][] = $elem['value']; | ||||
|                     break; | ||||
|                 case '{' . Plugin::NS_CALDAV . '}prop-filter' : | ||||
|                     $result['prop-filters'][] = $elem['value']; | ||||
|                     break; | ||||
|                 case '{' . Plugin::NS_CALDAV . '}is-not-defined' : | ||||
|                     $result['is-not-defined'] = true; | ||||
|                     break; | ||||
|                 case '{' . Plugin::NS_CALDAV . '}time-range' : | ||||
|                     if ($result['name'] === 'VCALENDAR') { | ||||
|                         throw new BadRequest('You cannot add time-range filters on the VCALENDAR component'); | ||||
|                     } | ||||
|                     $result['time-range'] = [ | ||||
|                         'start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null, | ||||
|                         'end'   => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null, | ||||
|                     ]; | ||||
|                     if ($result['time-range']['start'] && $result['time-range']['end'] && $result['time-range']['end'] <= $result['time-range']['start']) { | ||||
|                         throw new BadRequest('The end-date must be larger than the start-date'); | ||||
|                     } | ||||
|                     break; | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										82
									
								
								vendor/sabre/dav/lib/CalDAV/Xml/Filter/ParamFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								vendor/sabre/dav/lib/CalDAV/Xml/Filter/ParamFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Xml\Filter; | ||||
|  | ||||
| use Sabre\Xml\Reader; | ||||
| use Sabre\Xml\XmlDeserializable; | ||||
| use Sabre\CalDAV\Plugin; | ||||
|  | ||||
| /** | ||||
|  * PropFilter parser. | ||||
|  * | ||||
|  * This class parses the {urn:ietf:params:xml:ns:caldav}param-filter XML | ||||
|  * element, as defined in: | ||||
|  * | ||||
|  * https://tools.ietf.org/html/rfc4791#section-9.7.3 | ||||
|  * | ||||
|  * The result will be spit out as an array. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://www.rooftopsolutions.nl/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class ParamFilter implements XmlDeserializable { | ||||
|  | ||||
|     /** | ||||
|      * The deserialize method is called during xml parsing. | ||||
|      * | ||||
|      * This method is called statictly, this is because in theory this method | ||||
|      * may be used as a type of constructor, or factory method. | ||||
|      * | ||||
|      * Often you want to return an instance of the current class, but you are | ||||
|      * free to return other data as well. | ||||
|      * | ||||
|      * Important note 2: You are responsible for advancing the reader to the | ||||
|      * next element. Not doing anything will result in a never-ending loop. | ||||
|      * | ||||
|      * If you just want to skip parsing for this element altogether, you can | ||||
|      * just call $reader->next(); | ||||
|      * | ||||
|      * $reader->parseInnerTree() will parse the entire sub-tree, and advance to | ||||
|      * the next element. | ||||
|      * | ||||
|      * @param Reader $reader | ||||
|      * @return mixed | ||||
|      */ | ||||
|     static function xmlDeserialize(Reader $reader) { | ||||
|  | ||||
|         $result = [ | ||||
|             'name'           => null, | ||||
|             'is-not-defined' => false, | ||||
|             'text-match'     => null, | ||||
|         ]; | ||||
|  | ||||
|         $att = $reader->parseAttributes(); | ||||
|         $result['name'] = $att['name']; | ||||
|  | ||||
|         $elems = $reader->parseInnerTree(); | ||||
|  | ||||
|         if (is_array($elems)) foreach ($elems as $elem) { | ||||
|  | ||||
|             switch ($elem['name']) { | ||||
|  | ||||
|                 case '{' . Plugin::NS_CALDAV . '}is-not-defined' : | ||||
|                     $result['is-not-defined'] = true; | ||||
|                     break; | ||||
|                 case '{' . Plugin::NS_CALDAV . '}text-match' : | ||||
|                     $result['text-match'] = [ | ||||
|                         'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes', | ||||
|                         'collation'        => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;ascii-casemap', | ||||
|                         'value'            => $elem['value'], | ||||
|                     ]; | ||||
|                     break; | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										98
									
								
								vendor/sabre/dav/lib/CalDAV/Xml/Filter/PropFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								vendor/sabre/dav/lib/CalDAV/Xml/Filter/PropFilter.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Sabre\CalDAV\Xml\Filter; | ||||
|  | ||||
| use Sabre\Xml\Reader; | ||||
| use Sabre\Xml\XmlDeserializable; | ||||
| use Sabre\DAV\Exception\BadRequest; | ||||
| use Sabre\CalDAV\Plugin; | ||||
| use Sabre\VObject\DateTimeParser; | ||||
|  | ||||
| /** | ||||
|  * PropFilter parser. | ||||
|  * | ||||
|  * This class parses the {urn:ietf:params:xml:ns:caldav}prop-filter XML | ||||
|  * element, as defined in: | ||||
|  * | ||||
|  * https://tools.ietf.org/html/rfc4791#section-9.7.2 | ||||
|  * | ||||
|  * The result will be spit out as an array. | ||||
|  * | ||||
|  * @copyright Copyright (C) fruux GmbH (https://fruux.com/) | ||||
|  * @author Evert Pot (http://www.rooftopsolutions.nl/) | ||||
|  * @license http://sabre.io/license/ Modified BSD License | ||||
|  */ | ||||
| class PropFilter implements XmlDeserializable { | ||||
|  | ||||
|     /** | ||||
|      * The deserialize method is called during xml parsing. | ||||
|      * | ||||
|      * This method is called statictly, this is because in theory this method | ||||
|      * may be used as a type of constructor, or factory method. | ||||
|      * | ||||
|      * Often you want to return an instance of the current class, but you are | ||||
|      * free to return other data as well. | ||||
|      * | ||||
|      * You are responsible for advancing the reader to the next element. Not | ||||
|      * doing anything will result in a never-ending loop. | ||||
|      * | ||||
|      * If you just want to skip parsing for this element altogether, you can | ||||
|      * just call $reader->next(); | ||||
|      * | ||||
|      * $reader->parseInnerTree() will parse the entire sub-tree, and advance to | ||||
|      * the next element. | ||||
|      * | ||||
|      * @param Reader $reader | ||||
|      * @return mixed | ||||
|      */ | ||||
|     static function xmlDeserialize(Reader $reader) { | ||||
|  | ||||
|         $result = [ | ||||
|             'name'           => null, | ||||
|             'is-not-defined' => false, | ||||
|             'param-filters'  => [], | ||||
|             'text-match'     => null, | ||||
|             'time-range'     => false, | ||||
|         ]; | ||||
|  | ||||
|         $att = $reader->parseAttributes(); | ||||
|         $result['name'] = $att['name']; | ||||
|  | ||||
|         $elems = $reader->parseInnerTree(); | ||||
|  | ||||
|         if (is_array($elems)) foreach ($elems as $elem) { | ||||
|  | ||||
|             switch ($elem['name']) { | ||||
|  | ||||
|                 case '{' . Plugin::NS_CALDAV . '}param-filter' : | ||||
|                     $result['param-filters'][] = $elem['value']; | ||||
|                     break; | ||||
|                 case '{' . Plugin::NS_CALDAV . '}is-not-defined' : | ||||
|                     $result['is-not-defined'] = true; | ||||
|                     break; | ||||
|                 case '{' . Plugin::NS_CALDAV . '}time-range' : | ||||
|                     $result['time-range'] = [ | ||||
|                         'start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null, | ||||
|                         'end'   => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null, | ||||
|                     ]; | ||||
|                     if ($result['time-range']['start'] && $result['time-range']['end'] && $result['time-range']['end'] <= $result['time-range']['start']) { | ||||
|                         throw new BadRequest('The end-date must be larger than the start-date'); | ||||
|                     } | ||||
|                     break; | ||||
|                 case '{' . Plugin::NS_CALDAV . '}text-match' : | ||||
|                     $result['text-match'] = [ | ||||
|                         'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes', | ||||
|                         'collation'        => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;ascii-casemap', | ||||
|                         'value'            => $elem['value'], | ||||
|                     ]; | ||||
|                     break; | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user