From 66effbfe0827fc61fff6d248797a894213ad20d6 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 28 May 2016 17:46:24 +0200 Subject: upgrade to sabre32 --- Zotlabs/Storage/Browser.php | 4 +- vendor/autoload.php | 2 +- vendor/bin/generate_vcards | 242 ++- vendor/bin/naturalselection | 141 +- vendor/bin/sabredav | 3 +- vendor/bin/vobject | 28 +- vendor/composer/autoload_namespaces.php | 1 + vendor/composer/autoload_real.php | 45 +- vendor/composer/autoload_static.php | 81 - vendor/composer/installed.json | 72 +- vendor/psr/log/.gitignore | 1 + vendor/psr/log/LICENSE | 19 + vendor/psr/log/Psr/Log/AbstractLogger.php | 120 ++ .../psr/log/Psr/Log/InvalidArgumentException.php | 7 + vendor/psr/log/Psr/Log/LogLevel.php | 18 + vendor/psr/log/Psr/Log/LoggerAwareInterface.php | 17 + vendor/psr/log/Psr/Log/LoggerAwareTrait.php | 22 + vendor/psr/log/Psr/Log/LoggerInterface.php | 114 + vendor/psr/log/Psr/Log/LoggerTrait.php | 131 ++ vendor/psr/log/Psr/Log/NullLogger.php | 27 + .../psr/log/Psr/Log/Test/LoggerInterfaceTest.php | 116 + vendor/psr/log/README.md | 45 + vendor/sabre/dav/.travis.yml | 24 +- vendor/sabre/dav/CHANGELOG.md | 2242 -------------------- vendor/sabre/dav/LICENSE | 27 - vendor/sabre/dav/README.md | 29 - vendor/sabre/dav/bin/build.php | 2 +- vendor/sabre/dav/bin/migrateto17.php | 52 +- vendor/sabre/dav/bin/migrateto21.php | 4 - vendor/sabre/dav/bin/migrateto32.php | 268 +++ vendor/sabre/dav/bin/naturalselection | 2 +- .../sabre/dav/examples/sql/mysql.addressbook.sql | 6 +- vendor/sabre/dav/examples/sql/mysql.calendars.sql | 20 +- vendor/sabre/dav/examples/sql/pgsql.calendars.sql | 70 +- vendor/sabre/dav/examples/sql/pgsql.principals.sql | 8 - vendor/sabre/dav/examples/sql/sqlite.calendars.sql | 20 +- .../dav/lib/CalDAV/Backend/BackendInterface.php | 6 +- .../dav/lib/CalDAV/Backend/NotificationSupport.php | 15 + vendor/sabre/dav/lib/CalDAV/Backend/PDO.php | 381 +++- .../dav/lib/CalDAV/Backend/SharingSupport.php | 225 +- vendor/sabre/dav/lib/CalDAV/Backend/SimplePDO.php | 296 +++ vendor/sabre/dav/lib/CalDAV/Calendar.php | 63 +- vendor/sabre/dav/lib/CalDAV/CalendarHome.php | 64 +- vendor/sabre/dav/lib/CalDAV/CalendarObject.php | 61 +- vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php | 22 +- vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php | 2 +- vendor/sabre/dav/lib/CalDAV/ISharedCalendar.php | 28 +- .../dav/lib/CalDAV/Notifications/Collection.php | 76 +- vendor/sabre/dav/lib/CalDAV/Notifications/Node.php | 76 +- vendor/sabre/dav/lib/CalDAV/Plugin.php | 113 +- vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php | 64 +- vendor/sabre/dav/lib/CalDAV/Schedule/Outbox.php | 69 +- vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php | 107 +- .../dav/lib/CalDAV/Schedule/SchedulingObject.php | 16 +- vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php | 2 +- vendor/sabre/dav/lib/CalDAV/SharedCalendar.php | 237 ++- vendor/sabre/dav/lib/CalDAV/SharingPlugin.php | 106 +- .../dav/lib/CalDAV/Subscriptions/Subscription.php | 67 +- .../dav/lib/CalDAV/Xml/Notification/Invite.php | 11 +- .../lib/CalDAV/Xml/Notification/InviteReply.php | 5 +- .../sabre/dav/lib/CalDAV/Xml/Property/Invite.php | 209 +- .../dav/lib/CalDAV/Xml/Request/InviteReply.php | 11 +- vendor/sabre/dav/lib/CalDAV/Xml/Request/Share.php | 63 +- vendor/sabre/dav/lib/CardDAV/AddressBook.php | 82 +- vendor/sabre/dav/lib/CardDAV/AddressBookHome.php | 76 +- .../dav/lib/CardDAV/Backend/BackendInterface.php | 7 +- vendor/sabre/dav/lib/CardDAV/Backend/PDO.php | 9 +- vendor/sabre/dav/lib/CardDAV/Card.php | 53 +- vendor/sabre/dav/lib/CardDAV/Plugin.php | 122 +- vendor/sabre/dav/lib/CardDAV/VCFExportPlugin.php | 28 +- .../dav/lib/DAV/Auth/Backend/AbstractDigest.php | 6 + vendor/sabre/dav/lib/DAV/Auth/Plugin.php | 126 +- vendor/sabre/dav/lib/DAV/Browser/Plugin.php | 13 +- .../sabre/dav/lib/DAV/Browser/assets/sabredav.css | 6 +- vendor/sabre/dav/lib/DAV/Client.php | 19 +- vendor/sabre/dav/lib/DAV/CorePlugin.php | 40 +- vendor/sabre/dav/lib/DAV/FS/Directory.php | 6 +- vendor/sabre/dav/lib/DAV/File.php | 20 +- vendor/sabre/dav/lib/DAV/ICollection.php | 4 +- vendor/sabre/dav/lib/DAV/IFile.php | 2 +- vendor/sabre/dav/lib/DAV/INode.php | 5 +- .../dav/lib/DAV/PropertyStorage/Backend/PDO.php | 33 +- vendor/sabre/dav/lib/DAV/Server.php | 39 +- vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php | 69 + vendor/sabre/dav/lib/DAV/Sharing/Plugin.php | 342 +++ vendor/sabre/dav/lib/DAV/Tree.php | 2 +- vendor/sabre/dav/lib/DAV/Version.php | 2 +- vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php | 199 ++ vendor/sabre/dav/lib/DAV/Xml/Property/Href.php | 17 +- vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php | 70 + .../sabre/dav/lib/DAV/Xml/Property/LocalHref.php | 48 + .../sabre/dav/lib/DAV/Xml/Property/ShareAccess.php | 143 ++ .../dav/lib/DAV/Xml/Request/ShareResource.php | 81 + vendor/sabre/dav/lib/DAVACL/ACLTrait.php | 100 + .../dav/lib/DAVACL/AbstractPrincipalCollection.php | 2 +- vendor/sabre/dav/lib/DAVACL/FS/Collection.php | 52 +- vendor/sabre/dav/lib/DAVACL/FS/File.php | 49 +- vendor/sabre/dav/lib/DAVACL/FS/HomeCollection.php | 72 +- vendor/sabre/dav/lib/DAVACL/IACL.php | 1 - vendor/sabre/dav/lib/DAVACL/Plugin.php | 614 ++++-- vendor/sabre/dav/lib/DAVACL/Principal.php | 71 +- .../sabre/dav/lib/DAVACL/PrincipalBackend/PDO.php | 2 +- .../sabre/dav/lib/DAVACL/PrincipalCollection.php | 57 +- .../DAVACL/Xml/Property/SupportedPrivilegeSet.php | 20 +- .../Xml/Request/AclPrincipalPropSetReport.php | 67 + .../DAVACL/Xml/Request/PrincipalMatchReport.php | 107 + .../tests/Sabre/CalDAV/Backend/AbstractPDOTest.php | 624 +++++- .../sabre/dav/tests/Sabre/CalDAV/Backend/Mock.php | 53 +- .../tests/Sabre/CalDAV/Backend/PDOMySQLTest.php | 32 +- .../tests/Sabre/CalDAV/Backend/PDOSqliteTest.php | 30 +- .../dav/tests/Sabre/CalDAV/CalendarObjectTest.php | 166 +- .../tests/Sabre/CalDAV/CalendarQueryVAlarmTest.php | 88 +- .../Sabre/CalDAV/CalendarQueryValidatorTest.php | 518 ++--- .../sabre/dav/tests/Sabre/CalDAV/CalendarTest.php | 97 +- .../Sabre/CalDAV/ExpandEventsDoubleEventsTest.php | 37 +- .../dav/tests/Sabre/CalDAV/FreeBusyReportTest.php | 40 +- .../Sabre/CalDAV/GetEventsByTimerangeTest.php | 2 +- .../dav/tests/Sabre/CalDAV/ICSExportPluginTest.php | 747 ++----- .../sabre/dav/tests/Sabre/CalDAV/Issue166Test.php | 32 +- .../sabre/dav/tests/Sabre/CalDAV/Issue172Test.php | 86 +- .../sabre/dav/tests/Sabre/CalDAV/Issue205Test.php | 39 +- .../sabre/dav/tests/Sabre/CalDAV/Issue211Test.php | 38 +- .../sabre/dav/tests/Sabre/CalDAV/Issue220Test.php | 36 +- .../sabre/dav/tests/Sabre/CalDAV/Issue228Test.php | 37 +- .../Sabre/CalDAV/Notifications/CollectionTest.php | 35 +- .../tests/Sabre/CalDAV/Notifications/NodeTest.php | 25 +- vendor/sabre/dav/tests/Sabre/CalDAV/PluginTest.php | 13 +- .../Sabre/CalDAV/Principal/CollectionTest.php | 5 +- .../tests/Sabre/CalDAV/Principal/ProxyReadTest.php | 19 +- .../Sabre/CalDAV/Principal/ProxyWriteTest.php | 5 +- .../dav/tests/Sabre/CalDAV/Principal/UserTest.php | 37 +- .../dav/tests/Sabre/CalDAV/Schedule/OutboxTest.php | 73 +- .../dav/tests/Sabre/CalDAV/SharedCalendarTest.php | 239 +-- .../dav/tests/Sabre/CalDAV/SharingPluginTest.php | 215 +- vendor/sabre/dav/tests/Sabre/CalDAV/TestUtil.php | 65 +- .../dav/tests/Sabre/CalDAV/ValidateICalTest.php | 291 ++- .../dav/tests/Sabre/CardDAV/AbstractPluginTest.php | 6 +- .../tests/Sabre/CardDAV/AddressBookQueryTest.php | 126 +- .../dav/tests/Sabre/CardDAV/AddressBookTest.php | 92 +- .../Sabre/CardDAV/Backend/AbstractPDOTest.php | 275 +-- .../sabre/dav/tests/Sabre/CardDAV/Backend/Mock.php | 167 +- .../tests/Sabre/CardDAV/Backend/PDOMySQLTest.php | 29 +- .../tests/Sabre/CardDAV/Backend/PDOSqliteTest.php | 47 +- vendor/sabre/dav/tests/Sabre/CardDAV/CardTest.php | 123 +- .../dav/tests/Sabre/CardDAV/IDirectoryTest.php | 6 +- .../sabre/dav/tests/Sabre/CardDAV/MultiGetTest.php | 46 +- .../sabre/dav/tests/Sabre/CardDAV/PluginTest.php | 17 +- .../Sabre/CardDAV/SogoStripContentTypeTest.php | 40 +- vendor/sabre/dav/tests/Sabre/CardDAV/TestUtil.php | 14 +- .../dav/tests/Sabre/CardDAV/VCFExportTest.php | 73 +- .../dav/tests/Sabre/CardDAV/ValidateFilterTest.php | 128 +- .../dav/tests/Sabre/CardDAV/ValidateVCardTest.php | 253 ++- .../sabre/dav/tests/Sabre/DAV/AbstractServer.php | 12 +- .../Sabre/DAV/Auth/Backend/AbstractBasicTest.php | 13 +- .../Sabre/DAV/Auth/Backend/AbstractDigestTest.php | 11 +- .../Sabre/DAV/Auth/Backend/AbstractPDOTest.php | 20 +- .../tests/Sabre/DAV/Auth/Backend/ApacheTest.php | 1 - .../dav/tests/Sabre/DAV/Auth/Backend/FileTest.php | 12 +- .../dav/tests/Sabre/DAV/Auth/Backend/Mock.php | 6 +- .../tests/Sabre/DAV/Auth/Backend/PDOMySQLTest.php | 26 +- .../tests/Sabre/DAV/Auth/Backend/PDOSqliteTest.php | 23 +- .../sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php | 30 +- vendor/sabre/dav/tests/Sabre/DAV/BasicNodeTest.php | 64 +- .../Sabre/DAV/Browser/GuessContentTypeTest.php | 44 +- .../Sabre/DAV/Browser/MapGetToPropFindTest.php | 16 +- .../dav/tests/Sabre/DAV/Browser/PluginTest.php | 54 +- vendor/sabre/dav/tests/Sabre/DAV/ClientMock.php | 4 +- .../dav/tests/Sabre/DAV/Exception/LockedTest.php | 9 +- vendor/sabre/dav/tests/Sabre/DAV/ExceptionTest.php | 8 +- .../sabre/dav/tests/Sabre/DAV/FSExt/FileTest.php | 18 +- .../sabre/dav/tests/Sabre/DAV/FSExt/ServerTest.php | 64 +- .../sabre/dav/tests/Sabre/DAV/HttpDeleteTest.php | 20 +- vendor/sabre/dav/tests/Sabre/DAV/HttpPutTest.php | 26 +- vendor/sabre/dav/tests/Sabre/DAV/Issue33Test.php | 28 +- .../tests/Sabre/DAV/Locks/Backend/AbstractTest.php | 40 +- .../tests/Sabre/DAV/Locks/Backend/PDOMySQLTest.php | 27 +- .../dav/tests/Sabre/DAV/Locks/Backend/PDOTest.php | 21 +- .../sabre/dav/tests/Sabre/DAV/Locks/MSWordTest.php | 14 +- .../sabre/dav/tests/Sabre/DAV/Locks/PluginTest.php | 312 +-- .../sabre/dav/tests/Sabre/DAV/Mount/PluginTest.php | 16 +- .../sabre/dav/tests/Sabre/DAV/ObjectTreeTest.php | 48 +- .../dav/tests/Sabre/DAV/PartialUpdate/FileMock.php | 5 +- .../Sabre/DAV/PartialUpdate/SpecificationTest.php | 44 +- .../sabre/dav/tests/Sabre/DAV/ServerMKCOLTest.php | 192 +- .../sabre/dav/tests/Sabre/DAV/ServerPluginTest.php | 29 +- .../dav/tests/Sabre/DAV/ServerPreconditionTest.php | 112 +- .../sabre/dav/tests/Sabre/DAV/ServerSimpleTest.php | 2 +- .../tests/Sabre/DAV/ServerUpdatePropertiesTest.php | 63 +- .../sabre/dav/tests/Sabre/DAV/SimpleFileTest.php | 2 +- .../sabre/dav/tests/Sabre/DAV/StringUtilTest.php | 106 +- .../tests/Sabre/DAV/TemporaryFileFilterTest.php | 70 +- vendor/sabre/dav/tests/Sabre/DAV/TestPlugin.php | 7 +- vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php | 24 +- .../sabre/dav/tests/Sabre/DAVACL/ACLMethodTest.php | 157 +- .../dav/tests/Sabre/DAVACL/AllowAccessTest.php | 31 +- .../dav/tests/Sabre/DAVACL/BlockAccessTest.php | 19 +- .../Sabre/DAVACL/Exception/AceConflictTest.php | 14 +- .../Exception/NeedPrivilegesExceptionTest.php | 30 +- .../Sabre/DAVACL/Exception/NoAbstractTest.php | 14 +- .../Exception/NotRecognizedPrincipalTest.php | 14 +- .../DAVACL/Exception/NotSupportedPrivilegeTest.php | 14 +- .../tests/Sabre/DAVACL/ExpandPropertiesTest.php | 206 +- .../sabre/dav/tests/Sabre/DAVACL/MockACLNode.php | 3 +- .../sabre/dav/tests/Sabre/DAVACL/MockPrincipal.php | 10 +- .../dav/tests/Sabre/DAVACL/PluginAdminTest.php | 27 +- .../tests/Sabre/DAVACL/PluginPropertiesTest.php | 90 +- .../Sabre/DAVACL/PluginUpdatePropertiesTest.php | 67 +- .../DAVACL/PrincipalBackend/AbstractPDOTest.php | 117 +- .../Sabre/DAVACL/PrincipalBackend/PDOMySQLTest.php | 43 +- .../DAVACL/PrincipalBackend/PDOSqliteTest.php | 40 +- .../tests/Sabre/DAVACL/PrincipalCollectionTest.php | 16 +- .../Sabre/DAVACL/PrincipalPropertySearchTest.php | 159 +- .../DAVACL/PrincipalSearchPropertySetTest.php | 53 +- .../sabre/dav/tests/Sabre/DAVACL/PrincipalTest.php | 150 +- .../dav/tests/Sabre/DAVACL/SimplePluginTest.php | 286 ++- vendor/sabre/dav/tests/Sabre/DAVServerTest.php | 84 +- vendor/sabre/dav/tests/Sabre/TestUtil.php | 31 +- vendor/sabre/dav/tests/bootstrap.php | 18 +- vendor/sabre/dav/tests/phpunit.xml | 13 +- vendor/sabre/vobject/ChangeLog.md | 563 +++++ vendor/sabre/vobject/lib/Property/Float.php | 104 + vendor/sabre/vobject/lib/Property/Integer.php | 72 + vendor/sabre/vobject/lib/RecurrenceIterator.php | 21 + vendor/sabre/xml/.travis.yml | 9 +- vendor/sabre/xml/CHANGELOG.md | 11 + vendor/sabre/xml/lib/Deserializer/functions.php | 7 +- vendor/sabre/xml/lib/Reader.php | 20 +- vendor/sabre/xml/lib/Service.php | 8 +- 228 files changed, 10075 insertions(+), 8563 deletions(-) mode change 120000 => 100755 vendor/bin/generate_vcards mode change 120000 => 100755 vendor/bin/naturalselection mode change 120000 => 100755 vendor/bin/sabredav mode change 120000 => 100755 vendor/bin/vobject delete mode 100644 vendor/composer/autoload_static.php create mode 100644 vendor/psr/log/.gitignore create mode 100644 vendor/psr/log/LICENSE create mode 100644 vendor/psr/log/Psr/Log/AbstractLogger.php create mode 100644 vendor/psr/log/Psr/Log/InvalidArgumentException.php create mode 100644 vendor/psr/log/Psr/Log/LogLevel.php create mode 100644 vendor/psr/log/Psr/Log/LoggerAwareInterface.php create mode 100644 vendor/psr/log/Psr/Log/LoggerAwareTrait.php create mode 100644 vendor/psr/log/Psr/Log/LoggerInterface.php create mode 100644 vendor/psr/log/Psr/Log/LoggerTrait.php create mode 100644 vendor/psr/log/Psr/Log/NullLogger.php create mode 100644 vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php create mode 100644 vendor/psr/log/README.md delete mode 100644 vendor/sabre/dav/CHANGELOG.md delete mode 100644 vendor/sabre/dav/LICENSE delete mode 100644 vendor/sabre/dav/README.md create mode 100755 vendor/sabre/dav/bin/migrateto32.php create mode 100644 vendor/sabre/dav/lib/CalDAV/Backend/SimplePDO.php create mode 100644 vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php create mode 100644 vendor/sabre/dav/lib/DAV/Sharing/Plugin.php create mode 100644 vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php create mode 100644 vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php create mode 100644 vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php create mode 100644 vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php create mode 100644 vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php create mode 100644 vendor/sabre/dav/lib/DAVACL/ACLTrait.php create mode 100644 vendor/sabre/dav/lib/DAVACL/Xml/Request/AclPrincipalPropSetReport.php create mode 100644 vendor/sabre/dav/lib/DAVACL/Xml/Request/PrincipalMatchReport.php create mode 100644 vendor/sabre/vobject/ChangeLog.md create mode 100644 vendor/sabre/vobject/lib/Property/Float.php create mode 100644 vendor/sabre/vobject/lib/Property/Integer.php create mode 100644 vendor/sabre/vobject/lib/RecurrenceIterator.php diff --git a/Zotlabs/Storage/Browser.php b/Zotlabs/Storage/Browser.php index f875cbf33..713d75108 100644 --- a/Zotlabs/Storage/Browser.php +++ b/Zotlabs/Storage/Browser.php @@ -219,7 +219,7 @@ class Browser extends DAV\Browser\Plugin { $output = ''; if ($this->enablePost) { - $this->server->emit('onHTMLActionsPanel', array($parent, &$output)); + $this->server->emit('onHTMLActionsPanel', array($parent, &$output, $path)); } $html .= replace_macros(get_markup_template('cloud.tpl'), array( @@ -266,7 +266,7 @@ class Browser extends DAV\Browser\Plugin { * @param \Sabre\DAV\INode $node * @param string &$output */ - public function htmlActionsPanel(DAV\INode $node, &$output) { + public function htmlActionsPanel(DAV\INode $node, &$output, $path) { if (! $node instanceof DAV\ICollection) return; diff --git a/vendor/autoload.php b/vendor/autoload.php index 568834318..3ba315118 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785::getLoader(); +return ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261::getLoader(); diff --git a/vendor/bin/generate_vcards b/vendor/bin/generate_vcards deleted file mode 120000 index cb76da13a..000000000 --- a/vendor/bin/generate_vcards +++ /dev/null @@ -1 +0,0 @@ -../sabre/vobject/bin/generate_vcards \ No newline at end of file diff --git a/vendor/bin/generate_vcards b/vendor/bin/generate_vcards new file mode 100755 index 000000000..4663c3c16 --- /dev/null +++ b/vendor/bin/generate_vcards @@ -0,0 +1,241 @@ +#!/usr/bin/env php + testdata.vcf + +HI; + + fwrite(STDERR, $help); + exit(2); +} + +$count = (int)$argv[1]; +if ($count < 1) { + fwrite(STDERR, "Count must be at least 1\n"); + exit(2); +} + +fwrite(STDERR, "sabre/vobject " . Version::VERSION . "\n"); +fwrite(STDERR, "Generating " . $count . " vcards in vCard 4.0 format\n"); + +/** + * The following list is just some random data we compiled from various + * sources online. + * + * Very little thought went into compiling this list, and certainly nothing + * political or ethical. + * + * We would _love_ more additions to this to add more variation to this list. + * + * Send us PR's and don't be shy adding your own first and last name for fun. + */ + +$sets = array( + "nl" => array( + "country" => "Netherlands", + "boys" => array( + "Anno", + "Bram", + "Daan", + "Evert", + "Finn", + "Jayden", + "Jens", + "Jesse", + "Levi", + "Lucas", + "Luuk", + "Milan", + "René", + "Sem", + "Sibrand", + "Willem", + ), + "girls" => array( + "Celia", + "Emma", + "Fenna", + "Geke", + "Inge", + "Julia", + "Lisa", + "Lotte", + "Mila", + "Sara", + "Sophie", + "Tess", + "Zoë", + ), + "last" => array( + "Bakker", + "Bos", + "De Boer", + "De Groot", + "De Jong", + "De Vries", + "Jansen", + "Janssen", + "Meyer", + "Mulder", + "Peters", + "Smit", + "Van Dijk", + "Van den Berg", + "Visser", + "Vos", + ), + ), + "us" => array( + "country" => "United States", + "boys" => array( + "Aiden", + "Alexander", + "Charles", + "David", + "Ethan", + "Jacob", + "James", + "Jayden", + "John", + "Joseph", + "Liam", + "Mason", + "Michael", + "Noah", + "Richard", + "Robert", + "Thomas", + "William", + ), + "girls" => array( + "Ava", + "Barbara", + "Chloe", + "Dorothy", + "Elizabeth", + "Emily", + "Emma", + "Isabella", + "Jennifer", + "Lily", + "Linda", + "Margaret", + "Maria", + "Mary", + "Mia", + "Olivia", + "Patricia", + "Roxy", + "Sophia", + "Susan", + "Zoe", + ), + "last" => array( + "Smith", + "Johnson", + "Williams", + "Jones", + "Brown", + "Davis", + "Miller", + "Wilson", + "Moore", + "Taylor", + "Anderson", + "Thomas", + "Jackson", + "White", + "Harris", + "Martin", + "Thompson", + "Garcia", + "Martinez", + "Robinson", + ), + ), +); + +$current = 0; + +$r = function($arr) { + + return $arr[mt_rand(0,count($arr)-1)]; + +}; + +$bdayStart = strtotime('-85 years'); +$bdayEnd = strtotime('-20 years'); + +while($current < $count) { + + $current++; + fwrite(STDERR, "\033[100D$current/$count"); + + $country = array_rand($sets); + $gender = mt_rand(0,1)?'girls':'boys'; + + $vcard = new Component\VCard(array( + 'VERSION' => '4.0', + 'FN' => $r($sets[$country][$gender]) . ' ' . $r($sets[$country]['last']), + 'UID' => UUIDUtil::getUUID(), + )); + + $bdayRatio = mt_rand(0,9); + + if($bdayRatio < 2) { + // 20% has a birthday property with a full date + $dt = new \DateTime('@' . mt_rand($bdayStart, $bdayEnd)); + $vcard->add('BDAY', $dt->format('Ymd')); + + } elseif ($bdayRatio < 3) { + // 10% we only know the month and date of + $dt = new \DateTime('@' . mt_rand($bdayStart, $bdayEnd)); + $vcard->add('BDAY', '--' . $dt->format('md')); + } + if ($result = $vcard->validate()) { + ob_start(); + echo "\nWe produced an invalid vcard somehow!\n"; + foreach($result as $message) { + echo " " . $message['message'] . "\n"; + } + fwrite(STDERR, ob_get_clean()); + } + echo $vcard->serialize(); + +} + +fwrite(STDERR,"\nDone.\n"); diff --git a/vendor/bin/naturalselection b/vendor/bin/naturalselection deleted file mode 120000 index e6f1b3a2a..000000000 --- a/vendor/bin/naturalselection +++ /dev/null @@ -1 +0,0 @@ -../sabre/dav/bin/naturalselection \ No newline at end of file diff --git a/vendor/bin/naturalselection b/vendor/bin/naturalselection new file mode 100755 index 000000000..7e20439c1 --- /dev/null +++ b/vendor/bin/naturalselection @@ -0,0 +1,140 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2009-2010 Evert Pot +# All rights reserved. +# http://www.rooftopsolutions.nl/ +# +# This utility is distributed along with SabreDAV +# license: http://sabre.io/license/ Modified BSD License + +import os +from optparse import OptionParser +import time + +def getfreespace(path): + stat = os.statvfs(path) + return stat.f_frsize * stat.f_bavail + +def getbytesleft(path,threshold): + return getfreespace(path)-threshold + +def run(cacheDir, threshold, sleep=5, simulate=False, min_erase = 0): + + bytes = getbytesleft(cacheDir,threshold) + if (bytes>0): + print "Bytes to go before we hit threshold:", bytes + else: + print "Threshold exceeded with:", -bytes, "bytes" + dir = os.listdir(cacheDir) + dir2 = [] + for file in dir: + path = cacheDir + '/' + file + dir2.append({ + "path" : path, + "atime": os.stat(path).st_atime, + "size" : os.stat(path).st_size + }) + + dir2.sort(lambda x,y: int(x["atime"]-y["atime"])) + + filesunlinked = 0 + gainedspace = 0 + + # Left is the amount of bytes that need to be freed up + # The default is the 'min_erase setting' + left = min_erase + + # If the min_erase setting is lower than the amount of bytes over + # the threshold, we use that number instead. + if left < -bytes : + left = -bytes + + print "Need to delete at least:", left; + + for file in dir2: + + # Only deleting files if we're not simulating + if not simulate: os.unlink(file["path"]) + left = int(left - file["size"]) + gainedspace = gainedspace + file["size"] + filesunlinked = filesunlinked + 1 + + if(left<0): + break + + print "%d files deleted (%d bytes)" % (filesunlinked, gainedspace) + + + time.sleep(sleep) + + + +def main(): + parser = OptionParser( + 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", + ) + parser.add_option( + '-s', + dest="simulate", + action="store_true", + help="Don't actually make changes, but just simulate the behaviour", + ) + parser.add_option( + '-r','--runs', + help="How many times to check before exiting. -1 is infinite, which is the default", + type="int", + dest="runs", + default=-1 + ) + parser.add_option( + '-n','--interval', + help="Sleep time in seconds (default = 5)", + type="int", + dest="sleep", + default=5 + ) + parser.add_option( + '-l','--threshold', + help="Threshold in bytes (default = 10737418240, which is 10GB)", + type="int", + dest="threshold", + default=10737418240 + ) + parser.add_option( + '-m', '--min-erase', + help="Minimum number of bytes to erase when the threshold is reached. " + + "Setting this option higher will reduce the number of times the cache directory will need to be scanned. " + + "(the default is 1073741824, which is 1GB.)", + type="int", + dest="min_erase", + default=1073741824 + ) + + options,args = parser.parse_args() + if len(args)<1: + parser.error("This utility requires at least 1 argument") + cacheDir = args[0] + + print "Natural Selection" + print "Cache directory:", cacheDir + free = getfreespace(cacheDir); + print "Current free disk space:", free + + runs = options.runs; + while runs!=0 : + run( + cacheDir, + sleep=options.sleep, + simulate=options.simulate, + threshold=options.threshold, + min_erase=options.min_erase + ) + if runs>0: + runs = runs - 1 + +if __name__ == '__main__' : + main() diff --git a/vendor/bin/sabredav b/vendor/bin/sabredav deleted file mode 120000 index 3b5e4511d..000000000 --- a/vendor/bin/sabredav +++ /dev/null @@ -1 +0,0 @@ -../sabre/dav/bin/sabredav \ No newline at end of file diff --git a/vendor/bin/sabredav b/vendor/bin/sabredav new file mode 100755 index 000000000..032371ba8 --- /dev/null +++ b/vendor/bin/sabredav @@ -0,0 +1,2 @@ +#!/bin/sh +php -S 0.0.0.0:8080 `dirname $0`/sabredav.php diff --git a/vendor/bin/vobject b/vendor/bin/vobject deleted file mode 120000 index f5b111eac..000000000 --- a/vendor/bin/vobject +++ /dev/null @@ -1 +0,0 @@ -../sabre/vobject/bin/vobject \ No newline at end of file diff --git a/vendor/bin/vobject b/vendor/bin/vobject new file mode 100755 index 000000000..2aca7e729 --- /dev/null +++ b/vendor/bin/vobject @@ -0,0 +1,27 @@ +#!/usr/bin/env php +main($argv)); + diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index b7fc0125d..10c9b8207 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'Psr\\Log\\' => array($vendorDir . '/psr/log'), ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index f2df43375..aaf70ce6f 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785 +class ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261 { private static $loader; @@ -19,48 +19,37 @@ class ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261', '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); - } + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); } $loader->register(true); - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } + $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $fileIdentifier => $file) { - composerRequire85a1cefa95be2f464cf7f947cbc4c785($fileIdentifier, $file); + composerRequiree7c34560857712ac82f3f77ff9c61261($fileIdentifier, $file); } return $loader; } } -function composerRequire85a1cefa95be2f464cf7f947cbc4c785($fileIdentifier, $file) +function composerRequiree7c34560857712ac82f3f77ff9c61261($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { require $file; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php deleted file mode 100644 index 04dd83351..000000000 --- a/vendor/composer/autoload_static.php +++ /dev/null @@ -1,81 +0,0 @@ - __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); - } -} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 5714e1c19..4c5a019d8 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,4 +1,44 @@ [ + { + "name": "psr/log", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "time": "2012-12-21 11:40:51", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ] + }, { "name": "sabre/uri", "version": "1.1.0", @@ -170,17 +210,17 @@ }, { "name": "sabre/xml", - "version": "1.4.1", - "version_normalized": "1.4.1.0", + "version": "1.4.2", + "version_normalized": "1.4.2.0", "source": { "type": "git", "url": "https://github.com/fruux/sabre-xml.git", - "reference": "59998046db252634259a878baf1af18159f508f3" + "reference": "f48d98c22a4a4bef76cabb5968ffaddbb2bb593e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruux/sabre-xml/zipball/59998046db252634259a878baf1af18159f508f3", - "reference": "59998046db252634259a878baf1af18159f508f3", + "url": "https://api.github.com/repos/fruux/sabre-xml/zipball/f48d98c22a4a4bef76cabb5968ffaddbb2bb593e", + "reference": "f48d98c22a4a4bef76cabb5968ffaddbb2bb593e", "shasum": "" }, "require": { @@ -195,7 +235,7 @@ "phpunit/phpunit": "*", "sabre/cs": "~0.0.2" }, - "time": "2016-03-12 22:23:16", + "time": "2016-05-19 21:56:49", "type": "library", "installation-source": "dist", "autoload": { @@ -332,17 +372,17 @@ }, { "name": "sabre/dav", - "version": "3.1.3", - "version_normalized": "3.1.3.0", + "version": "3.2.0-beta1", + "version_normalized": "3.2.0.0-beta1", "source": { "type": "git", "url": "https://github.com/fruux/sabre-dav.git", - "reference": "8a266c7b5e140da79529414b9cde2a2d058b536b" + "reference": "32524c79a5890056123aa64499719e7c061bfde8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruux/sabre-dav/zipball/8a266c7b5e140da79529414b9cde2a2d058b536b", - "reference": "8a266c7b5e140da79529414b9cde2a2d058b536b", + "url": "https://api.github.com/repos/fruux/sabre-dav/zipball/32524c79a5890056123aa64499719e7c061bfde8", + "reference": "32524c79a5890056123aa64499719e7c061bfde8", "shasum": "" }, "require": { @@ -356,14 +396,16 @@ "ext-spl": "*", "lib-libxml": ">=2.7.0", "php": ">=5.5.0", + "psr/log": "^1.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" + "sabre/uri": "^1.0.1", + "sabre/vobject": "^4.1.0", + "sabre/xml": "^1.4.0" }, "require-dev": { "evert/phpdoc-md": "~0.1.0", + "monolog/monolog": "^1.18", "phpunit/phpunit": "> 4.8, <=6.0.0", "sabre/cs": "~0.0.5" }, @@ -371,7 +413,7 @@ "ext-curl": "*", "ext-pdo": "*" }, - "time": "2016-04-07 01:02:57", + "time": "2016-05-21 03:49:31", "bin": [ "bin/sabredav", "bin/naturalselection" diff --git a/vendor/psr/log/.gitignore b/vendor/psr/log/.gitignore new file mode 100644 index 000000000..22d0d82f8 --- /dev/null +++ b/vendor/psr/log/.gitignore @@ -0,0 +1 @@ +vendor diff --git a/vendor/psr/log/LICENSE b/vendor/psr/log/LICENSE new file mode 100644 index 000000000..474c952b4 --- /dev/null +++ b/vendor/psr/log/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 PHP Framework Interoperability Group + +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. diff --git a/vendor/psr/log/Psr/Log/AbstractLogger.php b/vendor/psr/log/Psr/Log/AbstractLogger.php new file mode 100644 index 000000000..00f903452 --- /dev/null +++ b/vendor/psr/log/Psr/Log/AbstractLogger.php @@ -0,0 +1,120 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } +} diff --git a/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/vendor/psr/log/Psr/Log/InvalidArgumentException.php new file mode 100644 index 000000000..67f852d1d --- /dev/null +++ b/vendor/psr/log/Psr/Log/InvalidArgumentException.php @@ -0,0 +1,7 @@ +logger = $logger; + } +} diff --git a/vendor/psr/log/Psr/Log/LoggerInterface.php b/vendor/psr/log/Psr/Log/LoggerInterface.php new file mode 100644 index 000000000..476bb962a --- /dev/null +++ b/vendor/psr/log/Psr/Log/LoggerInterface.php @@ -0,0 +1,114 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + abstract public function log($level, $message, array $context = array()); +} diff --git a/vendor/psr/log/Psr/Log/NullLogger.php b/vendor/psr/log/Psr/Log/NullLogger.php new file mode 100644 index 000000000..553a3c593 --- /dev/null +++ b/vendor/psr/log/Psr/Log/NullLogger.php @@ -0,0 +1,27 @@ +logger) { }` + * blocks. + */ +class NullLogger extends AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()) + { + // noop + } +} diff --git a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php new file mode 100644 index 000000000..a93281511 --- /dev/null +++ b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php @@ -0,0 +1,116 @@ + " + * + * Example ->error('Foo') would yield "error Foo" + * + * @return string[] + */ + abstract function getLogs(); + + public function testImplements() + { + $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $logger = $this->getLogger(); + $logger->{$level}($message, array('user' => 'Bob')); + $logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + $level.' message of level '.$level.' with context: Bob', + $level.' message of level '.$level.' with context: Bob', + ); + $this->assertEquals($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + /** + * @expectedException Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $logger = $this->getLogger(); + $logger->log('invalid level', 'Foo'); + } + + public function testContextReplacement() + { + $logger = $this->getLogger(); + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('info {Message {nothing} Bob Bar a}'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString')); + $dummy->expects($this->once()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->getLogger()->warning($dummy); + } + + public function testContextCanContainAnything() + { + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest), + 'object' => new \DateTime, + 'resource' => fopen('php://memory', 'r'), + ); + + $this->getLogger()->warning('Crazy context data', $context); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $this->getLogger()->warning('Random message', array('exception' => 'oops')); + $this->getLogger()->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + } +} + +class DummyTest +{ +} \ No newline at end of file diff --git a/vendor/psr/log/README.md b/vendor/psr/log/README.md new file mode 100644 index 000000000..574bc1cb2 --- /dev/null +++ b/vendor/psr/log/README.md @@ -0,0 +1,45 @@ +PSR Log +======= + +This repository holds all interfaces/classes/traits related to +[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). + +Note that this is not a logger of its own. It is merely an interface that +describes a logger. See the specification for more details. + +Usage +----- + +If you need a logger, you can use the interface like this: + +```php +logger = $logger; + } + + public function doSomething() + { + if ($this->logger) { + $this->logger->info('Doing work'); + } + + // do something useful + } +} +``` + +You can then pick one of the implementations of the interface to get a logger. + +If you want to implement the interface, you can require this package and +implement `Psr\Log\LoggerInterface` in your code. Please read the +[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +for details. diff --git a/vendor/sabre/dav/.travis.yml b/vendor/sabre/dav/.travis.yml index 48c88b169..a9189c981 100644 --- a/vendor/sabre/dav/.travis.yml +++ b/vendor/sabre/dav/.travis.yml @@ -3,12 +3,6 @@ php: - 5.5 - 5.6 - 7 - - hhvm - -matrix: - fast_finish: true - allow_failures: - - php: hhvm env: matrix: @@ -17,17 +11,25 @@ env: services: - mysql + - postgresql sudo: false -cache: vendor - before_script: - - mysql -e 'create database sabredav' + - mysql -e 'create database sabredav_test' + - psql -c "create database sabredav_test" -U postgres + - psql -c "create user sabredav with PASSWORD 'sabredav';GRANT ALL PRIVILEGES ON DATABASE sabredav_test TO sabredav" -U postgres + - phpenv config-rm xdebug.ini; true # - composer self-update - - composer update --prefer-source $LOWEST_DEPS + - composer update --prefer-dist $LOWEST_DEPS + +# addons: +# postgresql: "9.5" script: - - ./bin/phpunit --configuration tests/phpunit.xml $TEST_DEPS + - ./bin/phpunit --configuration tests/phpunit.xml.dist $TEST_DEPS - ./bin/sabre-cs-fixer fix lib/ --dry-run --diff +cache: + directories: + - $HOME/.composer/cache diff --git a/vendor/sabre/dav/CHANGELOG.md b/vendor/sabre/dav/CHANGELOG.md deleted file mode 100644 index f719c8e1a..000000000 --- a/vendor/sabre/dav/CHANGELOG.md +++ /dev/null @@ -1,2242 +0,0 @@ -ChangeLog -========= - -3.1.3 (2016-04-06) ------------------- - -* Set minimum libxml version to 2.7.0 in `composer.json`. -* #805: It wasn't possible to create calendars that hold events, journals and - todos using MySQL, because the `components` column was 1 byte too small. -* The zip release ships with [sabre/vobject 4.1.0][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.1.2 (2016-03-12) ------------------- - -* #784: Sync logs for address books were not correctly cleaned up after - deleting them. -* #787: Cannot use non-seekable stream-wrappers with range requests. -* Faster XML parsing and generating due to sabre/xml update. -* #793: The Sqlite schema is now more strict and more similar to the MySQL - schema. This solves a problem within Baikal. -* The zip release ships with [sabre/vobject 4.0.3][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.1.1 (2016-01-25) ------------------- - -* #755: The brower plugin and some operations would break when scheduling and - delegation would both be enabled. -* #757: A bunch of unittest improvements (@jakobsack). -* The zip release ships with [sabre/vobject 4.0.2][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. - - -3.1.0 (2016-01-06) ------------------- - -* Better error message when the browser plugin is not enabled. -* Added a super minimal server example. -* #730: Switched all mysql tables to `utf8mb4` character set, allowing you to - use emoji in some tables where you couldn't before. -* #710: Provide an Auth backend that acts as a helper for people implementing - OAuth2 Bearer token. (@fkooman). -* #729: Not all calls to `Sabre\DAV\Tree::getChildren()` were properly cached. -* #727: Added another workaround to make CalDAV work for Windows 10 clients. -* #742: Fixes to make sure that vobject 4 is correctly supported. -* #726: Better error reporting in `Client::propPatch`. We're now throwing - exceptions. -* #608: When a HTTP error is triggered during `Client:propFind`, we're now - throwing `Sabre\HTTP\ClientHttpException` instead of `Sabre\DAV\Exception`. - This new exception contains a LOT more information about the problem. -* #721: Events are now handled in the correct order for `COPY` requests. - Before this subtle bugs could appear that could cause data-loss. -* #747: Now throwing exceptions and setting the HTTP status to 500 in subtle - cases where no other plugin set a correct HTTP status. -* #686: Corrected PDO principal backend's findByURI for email addresses that - don't match the exact capitalization. -* #512: The client now has it's own `User-Agent`. -* #720: Some browser improvements. -* The zip release ships with [sabre/vobject 4.0.1][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. - - -3.1.0-alpha2 (2015-09-05) -------------------------- - -* Massive calendars and addressbooks should see a big drop in peak memory - usage. -* Fixed a privilege bug in the availability system. -* #697: Added a "tableName" member to the PropertyStorage PDO backend. (@Frzk). -* #699: PostgreSQL fix for the Locks PDO backend. (@TCKnet) -* Removed the `simplefsserver.php` example file. It's not simple enough. -* #703: PropPatch in client is not correctly encoded. -* #709: Throw exception when running into empty - `supported-calendar-component-set`. -* #711: Don't trigger deserializers for empty elements in `{DAV:}prop`. This - fixes issues when using sabre/dav as a client. -* The zip release ships with [sabre/vobject 4.0.0-alpha2][vobj], - [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. - - -3.1.0-alpha1 (2015-07-19) -------------------------- - -* Now requires PHP 5.5 -* Upgraded to vobject 4, which is a lot faster. -* Support for PHP 7. -* #690: Support for `calendar-availability`, draft 05. - [reference][calendar-availability]. -* #691: Workaround for broken Windows Phone client. -* The zip release ships with [sabre/vobject 4.0.0-alpha1][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. - - -3.0.9 (2016-04-06) ------------------- - -* Set minimum libxml version to 2.7.0 in `composer.json`. -* #727: Added another workaround to make CalDAV work for Windows 10 clients. -* #805: It wasn't possible to create calendars that hold events, journals and - todos using MySQL, because the `components` column was 1 byte too small. -* The zip release ships with [sabre/vobject 3.5.1][vobj], - [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.0.8 (2016-03-12) ------------------- - -* #784: Sync logs for address books were not correctly cleaned up after - deleting them. -* #787: Cannot use non-seekable stream-wrappers with range requests. -* Faster XML parsing and generating due to sabre/xml update. -* The zip release ships with [sabre/vobject 3.5.0][vobj], - [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.0.7 (2016-01-12) ------------------- - -* #752: PHP 7 support for 3.0 branch. (@DeepDiver1975) -* The zip release ships with [sabre/vobject 3.5.0][vobj], - [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. - - -3.0.6 (2016-01-04) ------------------- - -* #730: Switched all mysql tables to `utf8mb4` character set, allowing you to - use emoji in some tables where you couldn't before. -* #729: Not all calls to `Sabre\DAV\Tree::getChildren()` were properly cached. -* #734: Return `418 I'm a Teapot` when generating a multistatus response that - has resources with no returned properties. -* #740: Bugs in `migrate20.php` script. -* The zip release ships with [sabre/vobject 3.4.8][vobj], - [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. - - -3.0.5 (2015-09-15) ------------------- - -* #704: Fixed broken uri encoding in multistatus responses. This affected - at least CyberDuck, but probably also others. -* The zip release ships with [sabre/vobject 3.4.7][vobj], -* The zip release ships with [sabre/vobject 3.4.7][vobj], - [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. - - -3.0.4 (2015-09-06) ------------------- - -* #703: PropPatch in client is not correctly encoded. -* #709: Throw exception when running into empty - `supported-calendar-component-set`. -* #711: Don't trigger deserializers for empty elements in `{DAV:}prop`. This - fixes issues when using sabre/dav as a client. -* #705: A `MOVE` request that gets prevented from deleting the source resource - will still remove the target resource. Now all events are triggered before - any destructive operations. -* The zip release ships with [sabre/vobject 3.4.7][vobj], - [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. - - -3.0.3 (2015-08-06) ------------------- - -* #700: Digest Auth fails on `HEAD` requests. -* Fixed example files to no longer use now-deprecated realm argument. -* The zip release ships with [sabre/vobject 3.4.6][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. - - -3.0.2 (2015-07-21) ------------------- - -* #657: Migration script would break when coming a cross an iCalendar object - with no UID. -* #691: Workaround for broken Windows Phone client. -* Fixed a whole bunch of incorrect php docblocks. -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. - - -3.0.1 (2015-07-02) ------------------- - -* #674: Postgres sql file fixes. (@davesouthey) -* #677: Resources with the name '0' would not get retrieved when using - `Depth: infinity` in a `PROPFIND` request. -* #680: Fix 'autoprefixing' of dead `{DAV:}href` properties. -* #675: NTLM support in DAV\Client. (@k42b3) -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. - - -3.0.0 (2015-06-02) ------------------- - -* No changes since last beta. -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. - - -3.0.0-beta3 (2015-05-29) ------------------------- - -* Fixed deserializing href properties with no value. -* Fixed deserializing `{DAV:}propstat` without a `{DAV:}prop`. -* #668: More information about vcf-export-plugin in browser plugin. -* #669: Add export button to browser plugin for address books. (@mgee) -* #670: multiget report hrefs were not decoded. -* The zip release ships with [sabre/vobject 3.4.4][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. - - -3.0.0-beta2 (2015-05-27) ------------------------- - -* A node's properties should not overwrite properties that were already set. -* Some uris were not correctly encoded in notifications. -* The zip release ships with [sabre/vobject 3.4.4][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. - - -3.0.0-beta1 (2015-05-25) ------------------------- - -* `migrate22.php` is now called `migrate30.php`. -* Using php-cs-fixer for automated coding standards enforcement and fixing. -* #660: principals could break html output. -* #662: Fixed several bugs in the `share` request parser. -* #665: Fix a bug in serialization of complex properties in the proppatch - request in the client. -* #666: expand-property report did not correctly prepend the base uri when - generating uris, this caused delegation to break. -* #659: Don't throw errors when when etag-related checks are done on - collections. -* Fully supporting the updated `Prefer` header syntax, as defined in - [rfc7240][rfc7240]. -* The zip release ships with [sabre/vobject 3.4.3][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. - - -3.0.0-alpha1 (2015-05-19) -------------------------- - -* It's now possible to get all property information from files using the - browser plugin. -* Browser plugin will now show a 'calendar export' button when the - ics-export plugin is enabled. -* Some nodes that by default showed the current time as their last - modification time, now no longer has a last modification time. -* CardDAV namespace was missing from default namespaceMap. -* #646: Properties can now control their own HTML output in the browser plugin. -* #646: Nicer HTML output for the `{DAV:}acl` property. -* Browser plugin no longer shows a few properties that take up a lot of space, - but are likely not really interesting for most users. -* #654: Added a collection, `Sabre\DAVACL\FS\HomeCollection` for automatically - creating a private home collection per-user. -* Changed all MySQL columns from `VARCHAR` to `VARBINARY` where possible. -* Improved older migration scripts a bit to allow easier testing. -* The zip release ships with [sabre/vobject 3.4.3][vobj], - [sabre/http 4.0.0-alpha3][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 0.4.3][xml]. - - -2.2.0-alpha4 (2015-04-13) -------------------------- - -* Complete rewrite of the XML system. We now use our own [sabre/xml][xml], - which has a much smarter XML Reader and Writer. -* BC Break: It's no longer possible to instantiate the Locks plugin without - a locks backend. I'm not sure why this ever made sense. -* Simplified the Locking system and fixed a bug related to if tokens checking - locks unrelated to the current request. -* `FSExt` Directory and File no longer do custom property storage. This - functionality is already covered pretty well by the `PropertyStorage` plugin, - so please switch. -* Renamed `Sabre\CardDAV\UserAddressBooks` to `Sabre\CardDAV\AddressBookHome` - to be more consistent with `CalendarHome` as well as the CardDAV - specification. -* `Sabre\DAV\IExtendedCollection` now receives a `Sabre\DAV\MkCol` object as - its second argument, and no longer receives seperate properties and - resourcetype arguments. -* `MKCOL` now integrates better with propertystorage plugins. -* #623: Remove need of temporary files when working with Range requests. - (@dratini0) -* The zip release ships with [sabre/vobject 3.4.2][vobj], - [sabre/http 4.0.0-alpha1][http], [sabre/event 2.0.1][evnt], - [sabre/uri 1.0.0][uri] and [sabre/xml 0.4.3][xml]. - - -2.2.0-alpha3 (2015-02-25) -------------------------- - -* Contains all the changes introduced between 2.1.2 and 2.1.3. -* The zip release ships with [sabre/vobject 3.4.2][vobj], - [sabre/http 4.0.0-alpha1][http], [sabre/event 2.0.1][evnt] and - [sabre/uri 1.0.0][uri]. - - -2.2.0-alpha2 (2015-01-09) -------------------------- - -* Renamed `Sabre\DAV\Auth\Backend\BackendInterface::requireAuth` to - `challenge`, which is a more correct and better sounding name. -* The zip release ships with [sabre/vobject 3.3.5][vobj], - [sabre/http 3.0.4][http], [sabre/event 2.0.1][evnt]. - - -2.2.0-alpha1 (2014-12-10) -------------------------- - -* The browser plugin now has a new page with information about your sabredav - server, and shows information about every plugin that's loaded in the - system. -* #191: The Authentication system can now support multiple authentication - backends. -* Removed: all `$tableName` arguments from every PDO backend. This was already - deprecated, but has now been fully removed. All of these have been replaced - with public properties. -* Deleted several classes that were already deprecated much earlier: - * `Sabre\CalDAV\CalendarRootNode` - * `Sabre\CalDAV\UserCalendars` - * `Sabre\DAV\Exception\FileNotFound` - * `Sabre\DAV\Locks\Backend\FS` - * `Sabre\DAV\PartialUpdate\IFile` - * `Sabre\DAV\URLUtil` -* Removed: `Sabre\DAV\Client::addTrustedCertificates` and - `Sabre\DAV\Client::setVerifyPeer`. -* Removed: `Sabre\DAV\Plugin::getPlugin()` can now no longer return plugins - based on its class name. -* Removed: `Sabre\DAVACL\Plugin::getPrincipalByEmail()`. -* #560: GuessContentType plugin will now set content-type to - `application/octet-stream` if a better content-type could not be determined. -* #568: Added a `componentType` argument to `ICSExportPlugin`, allowing you to - specifically fetch `VEVENT`, `VTODO` or `VJOURNAL`. -* #582: Authentication backend interface changed to be stateless. If you - implemented your own authentication backend, make sure you upgrade your class - to the latest API! -* #582: `Sabre\DAV\Auth\Plugin::getCurrentUser()` is now deprecated. Use - `Sabre\DAV\Auth\Plugin::getCurrentPrincipal()` instead. -* #193: Fix `Sabre\DAV\FSExt\Directory::getQuotaInfo()` on windows. - - -2.1.11 (2016-??-??) -------------------- - -* #805: It wasn't possible to create calendars that hold events, journals and - todos using MySQL, because the `components` column was 1 byte too small. - - -2.1.10 (2016-03-10) -------------------- - -* #784: Sync logs for address books were not correctly cleaned up after - deleting them. - - -2.1.9 (2016-01-25) ------------------- - -* #674: PHP7 support (@DeepDiver1975). -* The zip release ships with [sabre/vobject 3.5.0][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.8 (2016-01-04) ------------------- - -* #729: Fixed a caching problem in the Tree object. -* #740: Bugs in `migrate20.php` script. -* The zip release ships with [sabre/vobject 3.4.8][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.7 (2015-09-05) ------------------- - -* #705: A `MOVE` request that gets prevented from deleting the source resource - will still remove the target resource. Now all events are triggered before - any destructive operations. -* The zip release ships with [sabre/vobject 3.4.7][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.6 (2015-07-21) ------------------- - -* #657: Migration script would break when coming a cross an iCalendar object - with no UID. -* #691: Workaround for broken Windows Phone client. -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.5 (2015-07-11) ------------------- - -* #677: Resources with the name '0' would not get retrieved when using - `Depth: infinity` in a `PROPFIND` request. -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.4 (2015-05-25) ------------------- - -* #651: Double-encoded path in the browser plugin. Should fix a few broken - links in some setups. -* #650: Correctly cleaning up change info after deleting calendars (@ErrOrnAmE). -* #658: Updating `schedule-calendar-default-URL` does not work well, so we're - disabling it until there's a better fix. -* The zip release ships with [sabre/vobject 3.4.3][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.3 (2015-02-25) ------------------- - -* #586: `SCHEDULE-STATUS` should not contain a reason-phrase. -* #539: Fixed a bug related to scheduling in shared calendars. -* #595: Support for calendar-timezone in iCalendar exports. -* #581: findByUri would send empty prefixes to the principal backend (@soydeedo) -* #611: Escaping a bit more HTML output in the browser plugin. (@LukasReschke) -* #610: Don't allow discovery of arbitrary files using `..` in the browser - plugin (@LukasReschke). -* Browser plugin now shows quota properties. -* #612: PropertyStorage didn't delete properties from nodes when a node's - parents get deleted. -* #581: Fixed problems related to finding attendee information during - scheduling. -* The zip release ships with [sabre/vobject 3.4.2][vobj], - [sabre/http 3.0.4][http], and [sabre/event 2.0.1][evnt]. - - -2.1.2 (2014-12-10) ------------------- - -* #566: Another issue related to the migration script, which would cause - scheduling to not work well for events that were already added before the - migration. -* #567: Doing freebusy requests on accounts that had 0 calendars would throw - a `E_NOTICE`. -* #572: `HEAD` requests trigger a PHP warning. -* #579: Browser plugin can throw exception for a few resourcetypes that didn't - have an icon defined. -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 3.0.4][http], and [sabre/event 2.0.1][evnt]. - - -2.1.1 (2014-11-22) ------------------- - -* #561: IMip Plugin didn't strip mailto: from email addresses. -* #566: Migration process had 2 problems related to adding the `uid` field - to the `calendarobjects` table. -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. - - -2.1.0 (2014-11-19) ------------------- - -* #541: CalDAV PDO backend didn't respect overridden PDO table names. -* #550: Scheduling invites are no longer delivered into shared calendars. -* #554: `calendar-multiget` `REPORT` did not work on inbox items. -* #555: The `calendar-timezone` property is now respected for floating times - and all-day events in the `calendar-query`, `calendar-multiget` and - `free-busy-query` REPORTs. -* #555: The `calendar-timezone` property is also respected for scheduling - free-busy requests. -* #547: CalDAV system too aggressively 'corrects' incoming iCalendar data, and - as a result doesn't return an etag for common cases. -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. - - -2.1.0-alpha2 (2014-10-23) -------------------------- - -* Added: calendar-user-address-set to default principal search properties - list. This should fix iOS attendee autocomplete support. -* Changed: Moved all 'notifications' functionality from `Sabre\CalDAV\Plugin` - to a new plugin: `Sabre\CalDAV\Notifications\Plugin`. If you want to use - notifications-related functionality, just add this plugin. -* Changed: Accessing the caldav inbox, outbox or notification collection no - longer triggers getCalendarsForUser() on backends. -* #533: New invites are no longer delivered to taks-only calendars. -* #538: Added `calendarObjectChange` event. -* Scheduling speedups. -* #539: added `afterResponse` event. (@joserobleda) -* Deprecated: All the "tableName" constructor arguments for all the PDO - backends are now deprecated. They still work, but will be removed in the - next major sabredav version. Every argument that is now deprecated can now - be accessed as a public property on the respective backends. -* #529: Added getCalendarObjectByUID to PDO backend, speeding up scheduling - operations on large calendars. -* The zip release ships with [sabre/vobject 3.3.3][vobj], - [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. - - -2.1.0-alpha1 (2014-09-23) -------------------------- - -* Added: Support for [rfc6638][rfc6638], also known as CalDAV Scheduling. -* Added: Automatically converting between vCard 3, 4 and jCard using the - `Accept:` header, in CardDAV reports, and automatically converting from - jCard to vCard upon `PUT`. It's important to note that your backends _may_ - now recieve both vCard 3.0 and 4.0. -* Added: #444. Collections can now opt-in to support high-speed `MOVE`. -* Changed: PropertyStorage backends now have a `move` method. -* Added: `beforeMove`, and `afterMove` events. -* Changed: A few database changes for the CalDAV PDO backend. Make sure you - run `bin/migrate21.php` to upgrade your database schema. -* Changed: CalDAV backends have a new method: `getCalendarObjectByUID`. This - method MUST be implemented by all backends, but the `AbstractBackend` has a - simple default implementation for this. -* Changed: `Sabre\CalDAV\UserCalendars` has been renamed to - `Sabre\CalDAV\CalendarHome`. -* Changed: `Sabre\CalDAV\CalendarRootNode` has been renamed to - `Sabre\CalDAV\CalendarRoot`. -* Changed: The IMipHandler has been completely removed. With CalDAV scheduling - support, it is no longer needed. It's functionality has been replaced by - `Sabre\CalDAV\Schedule\IMipPlugin`, which can now send emails for clients - other than iCal. -* Removed: `Sabre\DAV\ObjectTree` and `Sabre\DAV\Tree\FileSystem`. All this - functionality has been merged into `Sabre\DAV\Tree`. -* Changed: PrincipalBackend now has a findByUri method. -* Changed: `PrincipalBackend::searchPrincipals` has a new optional `test` - argument. -* Added: Support for the `{http://calendarserver.org/ns/}email-address-set` - property. -* #460: PropertyStorage must move properties during `MOVE` requests. -* Changed: Restructured the zip distribution to be a little bit more lean - and consistent. -* #524: Full support for the `test="anyof"` attribute in principal-search - `REPORT`. -* #472: Always returning lock tokens in the lockdiscovery property. -* Directory entries in the Browser plugin are sorted by type and name. - (@aklomp) -* #486: It's now possible to return additional properties when an 'allprop' - PROPFIND request is being done. (@aklomp) -* Changed: Now return HTTP errors when an addressbook-query REPORT is done - on a uri that's not a vcard. This should help with debugging this common - mistake. -* Changed: `PUT` requests with a `Content-Range` header now emit a 400 status - instead of 501, as per RFC7231. -* Added: Browser plugin can now display the contents of the - `{DAV:}supported-privilege-set` property. -* Added: Now reporting `CALDAV:max-resource-size`, but we're not actively - restricting it yet. -* Changed: CalDAV plugin is now responsible for reporting - `CALDAV:supported-collation-set` and `CALDAV:supported-calendar-data` - properties. -* Added: Now reporting `CARDDAV:max-resource-size`, but we're not actively - restricting it yet. -* Added: Support for `CARDDAV:supported-collation-set`. -* Changed: CardDAV plugin is now responsible for reporting - `CARDDAV:supported-address-data`. This functionality has been removed from - the CardDAV PDO backend. -* When a REPORT is not supported, we now emit HTTP error 415, instead of 403. -* #348: `HEAD` requests now work wherever `GET` also works. -* Changed: Lower priority for the iMip plugins `schedule` event listener. -* Added: #523 Custom CalDAV backends can now mark any calendar as read-only. -* The zip release ships with [sabre/vobject 3.3.3][vobj], - [sabre/http 3.0.0][http], and [sabre/event 2.0.0][evnt]. - - -2.0.9 (2015-09-04) ------------------- - -* #705: A `MOVE` request that gets prevented from deleting the source resource - will still remove the target resource. Now all events are triggered before - any destructive operations. -* The zip release ships with [sabre/vobject 3.4.6][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - - -2.0.8 (2015-07-11) ------------------- - -* #677: Resources with the name '0' would not get retrieved when using - `Depth: infinity` in a `PROPFIND` request. -* The zip release ships with [sabre/vobject 3.3.5][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.7 (2015-05-25) ------------------- - -* #650: Correctly cleaning up change info after deleting calendars (@ErrOrnAmE). -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.6 (2014-12-10) ------------------- - -* Added `Sabre\CalDAV\CalendarRoot` as an alias for - `Sabre\CalDAV\CalendarRootNode`. The latter is going to be deprecated in 2.1, - so this makes it slightly easier to write code that works in both branches. -* #497: Making sure we're initializing the sync-token field with a value after - migration. -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.5 (2014-10-14) ------------------- - -* #514: CalDAV PDO backend didn't work when overriding the 'calendar changes' - database table name. -* #515: 304 status code was not being sent when checking preconditions. -* The zip release ships with [sabre/vobject 3.3.3][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.4 (2014-08-27) ------------------- - -* #483: typo in calendars creation for PostgreSQL. -* #487: Locks are now automatically removed after a node has been deleted. -* #496: Improve CalDAV and CardDAV sync when there is no webdav-sync support. -* Added: Automatically mapping internal sync-tokens to getctag. -* The zip release ships with [sabre/vobject 3.3.1][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.3 (2014-07-14) ------------------- - -* #474: Fixed PropertyStorage `pathFilter()`. -* #476: CSP policy incorrect, causing stylesheets to not load in the browser - plugin. -* #475: Href properties in the browser plugin sometimes included a backslash. -* #478: `TooMuchMatches` exception never worked. This was fixed, and we also - took this opportunity to rename it to `TooManyMatches`. -* The zip release ships with [sabre/vobject 3.2.4][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.2 (2014-06-12) ------------------- - -* #470: Fixed compatibility with PHP < 5.4.14. -* #467: Fixed a problem in `examples/calendarserver.php`. -* #466: All the postgresql sample files have been updated. -* Fixed: An error would be thrown if a client did a propfind on a node the - user didn't have access to. -* Removed: Old and broken example code from the `examples/` directory. -* The zip release ships with [sabre/vobject 3.2.3][vobj], - [sabre/http 2.0.3][http], and [sabre/event 1.0.1][evnt]. - - -2.0.1 (2014-05-28) ------------------- - -* #459: PROPFIND requests on Files with no Depth header would return a fatal - error. -* #464: A PROPFIND allprops request should not return properties with status - 404. -* The zip release ships with [sabre/vobject 3.2.2][vobj], - [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. - - -2.0.0 (2014-05-22) ------------------- - -* The zip release ships with [sabre/vobject 3.2.2][vobj], - [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. -* Fixed: #456: Issue in sqlite migration script. -* Updated: MySQL database schema optimized by using more efficient column types. -* Cleaned up browser design. - - -2.0.0-beta1 (2014-05-15) -------------------------- - -* The zip release ships with [sabre/vobject 3.2.2][vobj], - [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. -* BC Break: Property updating and fetching got refactored. Read the [migration - document][mi20] for more information. This allows for creation of a generic - property storage, and other property-related functionality that was not - possible before. -* BC Break: Removed `propertyUpdate`, `beforeGetProperties` and - `afterGetProperties` events. -* Fixed: #413: Memory optimizations for the CardDAV PDO backend. -* Updated: Brand new browser plugin with more debugging features and a design - that is slightly less painful. -* Added: Support for the `{DAV:}supported-method-set` property server-wide. -* Making it easier for implementors to override how the CardDAV addressbook - home is located. -* Fixed: Issue #422 Preconditions were not being set on PUT on non-existant - files. Not really a chance for data-loss, but incorrect nevertheless. -* Fixed: Issue #428: Etag check with `If:` fails if the target is a collection. -* Fixed: Issues #430, #431, #433: Locks plugin didn't not properly release - filesystem based locks. -* Fixed: #443. Support for creating new calendar subscriptions for OS X 10.9.2 - and up. -* Removed: `Sabre\DAV\Server::NODE_*` constants. -* Moved all precondition checking into a central place, instead of having to - think about it on a per-method basis. -* jCal transformation for calendar-query REPORT now works again. -* Switched to PSR-4 -* Fixed: #175. Returning ETag header upon a failed `If-Match` or - `If-None-Match` check. -* Removed: `lib/Sabre/autoload.php`. Use `vendor/autoload.php` instead. -* Removed: all the rfc documentation from the sabre/dav source. This made the - package needlessly larger. -* Updated: Issue #439. Lots of updates in PATCH support. The - Sabre_DAV_PartialUpdate_IFile interface is now deprecated and will be - removed in a future version. -* Added: `Sabre\DAV\Exception\LengthRequired`. - -1.9.0-alpha2 (2014-01-14) -------------------------- - -* The zip release ships with sabre/vobject 3.1.3, sabre/http 2.0.1, and - sabre/event 1.0.0. -* Added: Browser can now inspect any node, if ?sabreaction=browser is appended. -* Fixed: Issue #178. Support for multiple items in the Timeout header. -* Fixed: Issue #382. Stricter checking if calendar-query is allowed to run. -* Added: Depth: Infinity support for PROPFIND request. Thanks Thomas Müller and - Markus Goetz. - - -1.9.0-alpha1 (2013-11-07) -------------------------- - -* The zip release ships with sabre/vobject 3.1.3, sabre/http 2.0.0alpha5, and - sabre/event 1.0.0. -* BC Break: The CardDAV and CalDAV BackendInterface each have a new method: - getMultipleCards and getMultipleCalendarObjects. The Abstract and PDO backends - have default implementations, but if you implement that interface directly, - this method is now required. -* BC Break: XML property classes now receive an extra argument in their - unserialize method ($propertyMap). This allows for recursively parsing - properties, if needed. -* BC Break: Now using sabre/event for event emitting/subscription. For plugin - authors this means Server::subscribeEvent is now Server::on, and - Server::broadcastEvent is now Server::emit. -* BC Break: Almost all core functionality moved into a CorePlugin. -* BC Break: Most events triggered by the server got an overhaul. -* Changed: Sabre\HTTP now moved into a dedicated sabre/http package. -* Added: Support for WebDAV-sync (rfc6578). -* Added: Support for caldav-subscriptions, which is an easy way for caldav - clients to manage a list of subscriptions on the server. -* Added: Support for emitting and receiving jCal instead of iCalendar for - CalDAV. -* Added: BasicCallback authenticaton backend, for creating simple authentication - systems without having to define any classes. -* Added: A $transactionType property on the server class. This can be used for - logging and performance measuring purposes. -* Fixed: If event handlers modify the request body from a PUT request, an ETag - is no longer sent back. -* Added: Sabre\DAV\IMultiGet to optimize requests that retrieve information - about lists of resources. -* Added: MultiGet support to default CalDAV and CardDAV backends, speeding up - the multiget and sync reports quite a bit! -* Added: ICSExportPlugin can now generate jCal, filter on time-ranges and expand - recurrences. -* Fixed: Read-only access to calendars still allows the sharee to modify basic - calendar properties, such as the displayname and color. -* Changed: The default supportedPrivilegeSet has changed. Most privileges are no - longer marked as abstract. -* Changed: More elegant ACL management for CalendarObject and Card nodes. -* Added: Browser plugin now marks a carddav directory as type Directory, and a - shared calendar as 'Shared'. -* Added: When debugExceptions is turned on, all previous exceptions are also - traversed. -* Removed: Got rid of the Version classes for CalDAV, CardDAV, HTTP, and DAVACL. - Now that there's no separate packages anymore, this makes a bit more sense. -* Added: Generalized the multistatus response parser a bit more, for better - re-use. -* Added: Sabre\DAV\Client now has support for complex properties for PROPPATCH. - (Issue #299). -* Added: Sabre\DAV\Client has support for gzip and deflate encoding. -* Added: Sabre\DAV\Client now has support for sending objects as streams. -* Added: Deserializer for {DAV:}current-user-privilege-set. -* Added: Addressbooks or backends can now specify custom acl rules when creating - cards. -* Added: The ability for plugins to validate custom tokens in If: headers. -* Changed: Completely refactored the Lock plugin to deal with the new If: header - system. -* Added: Checking preconditions for MOVE, COPY, DELETE and PROPPATCH methods. -* Added: has() method on DAV\Property\SupportedReportSet. -* Added: If header now gets checked (with ETag) all the time. Before the dealing - with the If-header was a responsibility of the Locking plugin. -* Fixed: Outbox access for delegates. -* Added: Issue 333: It's now possible to override the calendar-home in the - CalDAV plugin. -* Added: A negotiateContentType to HTTP\Request. A convenience method. -* Fixed: Issue 349: Denying copying or moving a resource into it's own subtree. -* Fixed: SabreDAV catches every exception again. -* Added: Issue #358, adding a component=vevent parameter to the content-types - for calendar objects, if the caldav backend provides this info. - - -1.8.12-stable (2015-01-21) --------------------------- - -* The zip release ships with sabre/vobject 2.1.7. -* #568: Support empty usernames and passwords in basic auth. - - -1.8.11 (2014-12-10) -------------------- - -* The zip release ships with sabre/vobject 2.1.6. -* Updated: MySQL database schema optimized by using more efficient column types. -* #516: The DAV client will now only redirect to HTTP and HTTPS urls. - - -1.8.10 (2014-05-15) -------------------- - -* The zip release ships with sabre/vobject 2.1.4. -* includes changes from version 1.7.12. - - -1.8.9 (2014-02-26) ------------------- - -* The zip release ships with sabre/vobject 2.1.3. -* includes changes from version 1.7.11. - - -1.8.8 (2014-02-09) ------------------- - -* includes changes from version 1.7.10. -* The zip release ships with sabre/vobject 2.1.3. - -1.8.7 (2013-10-02) ------------------- - -* the zip release ships with sabre/vobject 2.1.3. -* includes changes from version 1.7.9. - - -1.8.6 (2013-06-18) ------------------- - -* The zip release ships with sabre/vobject 2.1.0. -* Includes changes from version 1.7.8. - - -1.8.5 (2013-04-11) ------------------- - -* The zip release ships with sabre/vobject 2.0.7. -* Includes changes from version 1.7.7. - - -1.8.4 (2013-04-08) ------------------- - -* The zip release ships with sabre/vobject 2.0.7. -* Includes changes from version 1.7.6. - - -1.8.3 (2013-03-01) ------------------- - -* The zip release ships with sabre/vobject 2.0.6. -* Includes changes from version 1.7.5. -* Fixed: organizer email-address for shared calendars is now prefixed with - mailto:, as it should. - - -1.8.2 (2013-01-19) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Includes changes from version 1.7.4. - - -1.8.1 (2012-12-01) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Includes changes from version 1.7.3. -* Fixed: Typo in 1.7 migration script caused it to fail. - - -1.8.0 (2012-11-08) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* BC Break: Moved the entire codebase to PHP namespaces. -* BC Break: Every backend package (CalDAV, CardDAV, Auth, Locks, Principals) now - has consistent naming conventions. There's a BackendInterface, and an - AbstractBackend class. -* BC Break: Changed a bunch of constructor signatures in the CalDAV package, to - reduce dependencies on the ACL package. -* BC Break: Sabre_CalDAV_ISharedCalendar now also has a getShares method, so - sharees can figure out who is also on a shared calendar. -* Added: Sabre_DAVACL_IPrincipalCollection interface, to advertise support for - principal-property-search on any node. -* Added: Simple console script to fire up a fileserver in the current directory - using PHP 5.4's built-in webserver. -* Added: Sharee's can now also read out the list of invites for a shared - calendar. -* Added: The Proxy principal classes now both implement an interface, for - greater flexiblity. - - -1.7.13 (2014-07-28) -------------------- - -* The zip release ships with sabre/vobject 2.1.4. -* Changed: Removed phing and went with a custom build script for now. - - -1.7.12 (2014-05-15) -------------------- - -* The zip release ships with sabre/vobject 2.1.4. -* Updated: Issue #439. Lots of updates in PATCH support. The - Sabre_DAV_PartialUpdate_IFile interface is now deprecated and will be removed - in a future version. -* Fixed: Restoring old setting after changing libxml_disable_entity_loader. -* Fixed: Issue #422: Preconditions were not being set on PUT on non-existant - files. Not really a chance for data-loss, but incorrect nevertheless. -* Fixed: Issue #427: Now checking preconditions on DELETE requests. -* Fixed: Issue #428: Etag check with If: fails if the target is a collection. -* Fixed: Issue #393: PATCH request with missing end-range was handled - incorrectly. -* Added: Sabre_DAV_Exception_LengthRequired to omit 411 errors. - - -1.7.11 (2014-02-26) -------------------- - -* The zip release ships with sabre/vobject 2.1.3. -* Fixed: Issue #407: large downloads failed. -* Fixed: Issue #414: XXE security problem on older PHP versions. - - -1.7.10 (2014-02-09) -------------------- - -* Fixed: Issue #374: Don't urlescape colon (:) when it's not required. -* Fixed: Potential security vulnerability in the http client. - - -1.7.9 (2013-10-02) ------------------- - -* The zip release ships with sabre/vobject 2.1.3. -* Fixed: Issue #365. Incorrect output when principal urls have spaces in them. -* Added: Issue #367: Automatically adding a UID to vcards that don't have them. - - -1.7.8 (2013-06-17) ------------------- - -* The zip release ships with sabre/vobject 2.1.0. -* Changed: Sabre\DAV\Client::verifyPeer is now a protected property (instead of - private). -* Fixed: Text was incorrectly escaped in the Href and HrefList properties, - disallowing urls with ampersands (&) in them. -* Added: deserializer for Sabre\DAVACL\Property\CurrentUserPrivilegeSet. -* Fixed: Issue 335: Client only deserializes properties with status 200. -* Fixed: Issue 341: Escaping xml in 423 Locked error responses. -* Added: Issue 339: beforeGetPropertiesForPath event. - - -1.7.7 (2013-04-11) ------------------- - -* The zip release ships with sabre/vobject 2.0.7. -* Fixed: Assets in the browser plugins were not being served on windows - machines. - - -1.7.6 (2013-04-08) ------------------- - -* The zip release ships with sabre/vobject 2.0.7. -* Fixed: vcardurl in database schema can now hold 255 characters instead of 80 - (which is often way to small). -* Fixed: The browser plugin potentially allowed people to open any arbitrary - file on windows servers (CVE-2013-1939). - - -1.7.5 (2013-03-01) ------------------- - -* The zip release ships with sabre/vobject 2.0.6. -* Change: No longer advertising support for 4.0 vcards. iOS and OS X address - book don't handle this well, and just advertising 3.0 support seems like the - most logical course of action. -* Added: ->setVerifyPeers to Sabre_DAV_Client (greatly resisting against it, - don't use this..). - - -1.7.4 (2013-01-19) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Changed: To be compatibile with MS Office 2011 for Mac, a workaround was - removed that was added to support old versions of Windows XP (pre-SP3). - Indeed! We needed a crazy workaround to work with one MS product in the past, - and we can't keep that workaround to be compatible with another MS product. -* Fixed: expand-properties REPORT had incorrect values for the href element. -* Fixed: Range requests now work for non-seekable streams. (Thanks Alfred - Klomp). -* Fixed: Changed serialization of {DAV:}getlastmodified and {DAV:}supportedlock - to improve compatiblity with MS Office 2011 for Mac. -* Changed: reverted the automatic translation of 'DAV:' xml namespaces to - 'urn:DAV' when parsing files. Issues were reported with libxml 2.6.32, on a - relatively recent debian release, so we'll wait till 2015 to take this one out - again. -* Added: Sabre_DAV_Exception_ServiceUnavailable, for emitting 503's. - - -1.7.3 (2012-12-01) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Fixed: Removing double slashes from getPropertiesForPath. -* Change: Marked a few more properties in the CardDAV as protected, instead of - private. -* Fixed: SharingPlugin now plays nicer with other plugins with similar - functionality. -* Fixed: Issue 174. Sending back HTTP/1.0 for requests with this version. - - -1.7.2 (2012-11-08) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Added: ACL plugin advertises support for 'calendarserver-principal- - property-search'. -* Fixed: [#153] Allowing for relative http principals in iMip requests. -* Added: Support for cs:first-name and cs:last-name properties in sharing - invites. -* Fixed: Made a bunch of properties protected, where they were private before. -* Added: Some non-standard properties for sharing to improve compatibility. -* Fixed: some bugfixes in postgres sql script. -* Fixed: When requesting some properties using PROPFIND, they could show up as - both '200 Ok' and '403 Forbidden'. -* Fixed: calendar-proxy principals were not checked for deeper principal - membership than 1 level. -* Fixed: setGroupMemberSet argument now correctly receives relative principal - urls, instead of the absolute ones. -* Fixed: Server class will filter out any bonus properties if any extra were - returned. This means the implementor of the IProperty class can be a bit - lazier when implementing. Note: bug numbers after this line refer to Google - Code tickets. We're using github now. - - -1.7.1 (2012-10-07) ------------------- - -* Fixed: include path problem in the migration script. - - -1.7.0 (2012-10-06) ------------------- - -* BC Break: The calendarobjects database table has a bunch of new fields, and a - migration script is required to ensure everything will keep working. Read the - wiki for more details. -* BC Break: The ICalendar interface now has a new method: calendarQuery. -* BC Break: In this version a number of classes have been deleted, that have - been previously deprecated. Namely: - Sabre_DAV_Directory (now: - Sabre_DAV_Collection) - Sabre_DAV_SimpleDirectory (now: - Sabre_DAV_SimpleCollection) -* BC Break: Sabre_CalDAV_Schedule_IMip::sendMessage now has an extra argument. - If you extended this class, you should fix this method. It's only used for - informational purposes. -* BC Break: The DAV: namespace is no longer converted to urn:DAV. This was a - workaround for a bug in older PHP versions (pre-5.3). -* Removed: Sabre.includes.php was deprecated, and is now removed. -* Removed: Sabre_CalDAV_Server was deprecated, and is now removed. Please use - Sabre_DAV_Server and check the examples in the examples/ directory. -* Changed: The Sabre_VObject library now spawned into it's own project! The - VObject library is still included in the SabreDAV zip package. -* Added: Experimental interfaces to allow implementation of caldav-sharing. Note - that no implementation is provided yet, just the api hooks. -* Added: Free-busy reporting compliant with the caldav-scheduling standard. This - allows iCal and other clients to fetch other users' free-busy data. -* Added: Experimental NotificationSupport interface to add caldav notifications. -* Added: VCF Export plugin. If enabled, it can generate an export of an entire - addressbook. -* Added: Support for PATCH using a SabreDAV format, to live-patch files. -* Added: Support for Prefer: return-minimal and Brief: t headers for PROPFIND - and PROPPATCH requests. -* Changed: Responsibility for dealing with the calendar-query is now moved from - the CalDAV plugin to the CalDAV backends. This allows for heavy optimizations. -* Changed: The CalDAV PDO backend is now a lot faster for common calendar - queries. -* Changed: We are now using the composer autoloader. -* Changed: The CalDAV backend now all implement an interface. -* Changed: Instead of Sabre_DAV_Property, Sabre_DAV_PropertyInterface is now the - basis of every property class. -* Update: Caching results for principal lookups. This should cut down queries - and performance for a number of heavy requests. -* Update: ObjectTree caches lookups much more aggresively, which will help - especially speeding up a bunch of REPORT queries. -* Added: Support for the schedule-calendar-transp property. -* Fixed: Marking both the text/calendar and text/x-vcard as UTF-8 encoded. -* Fixed: Workaround for the SOGO connector, as it doesn't understand receiving - "text/x-vcard; charset=utf-8" for a contenttype. -* Added: Sabre_DAV_Client now throws more specific exceptions in cases where we - already has an exception class. -* Added: Sabre_DAV_PartialUpdate. This plugin allows you to use the PATCH method - to update parts of a file. -* Added: Tons of timezone name mappings for Microsoft Exchange. -* Added: Support for an 'exception' event in the server class. -* Fixed: Uploaded VCards without a UID are now rejected. (thanks Dominik!) -* Fixed: Rejecting calendar objects if they are not in the - supported-calendar-component list. (thanks Armin!) -* Fixed: Issue 219: serialize() now reorders correctly. -* Fixed: Sabre_DAV_XMLUtil no longer returns empty $dom->childNodes if there is - whitespace in $dom. -* Fixed: Returning 409 Conflict instead of 500 when an attempt is made to create - a file as a child of something that's not a collection. -* Fixed: Issue 237: xml-encoding values in SabreDAV error responses. -* Fixed: Returning 403, instead of 501 when an unknown REPORT is requested. -* Fixed: Postfixing slash on {DAV:}owner properties. -* Fixed: Several embarrassing spelling mistakes in docblocks. - - -1.6.10 (2013-06-17) -------------------- - -* Fixed: Text was incorrectly escaped in the Href and HrefList properties, - disallowing urls with ampersands (&) in them. -* Fixed: Issue 341: Escaping xml in 423 Locked error responses. - - -1.6.9 (2013-04-11) ------------------- - -* Fixed: Assets in the browser plugins were not being served on windows - machines. - - -1.6.8 (2013-04-08) ------------------- - -* Fixed: vcardurl in database schema can now hold 255 characters instead of 80 - (which is often way to small). -* Fixed: The browser plugin potentially allowed people to open any arbitrary - file on windows servers. (CVE-2013-1939). - - -1.6.7 (2013-03-01) ------------------- - -* Change: No longer advertising support for 4.0 vcards. iOS and OS X address - book don't handle this well, and just advertising 3.0 support seems like the - most logical course of action. -* Added: ->setVerifyPeers to Sabre_DAV_Client (greatly resisting against it, - don't use this..). - - -1.6.6 (2013-01-19) ------------------- - -* Fixed: Backported a fix for broken XML serialization in error responses. - (Thanks @DeepDiver1975!) - - -1.6.5 (2012-10-04) ------------------- - -* Fixed: Workaround for line-ending bug OS X 10.8 addressbook has. -* Added: Ability to allow users to set SSL certificates for the Client class. - (Thanks schiesbn!). -* Fixed: Directory indexes with lots of nodes should be a lot faster. -* Fixed: Issue 235: E_NOTICE thrown when doing a propfind request with - Sabre_DAV_Client, and no valid properties are returned. -* Fixed: Issue with filtering on alarms in tasks. - - -1.6.4 (2012-08-02) ------------------- - -* Fixed: Issue 220: Calendar-query filters may fail when filtering on alarms, if - an overridden event has it's alarm removed. -* Fixed: Compatibility for OS/X 10.8 iCal in the IMipHandler. -* Fixed: Issue 222: beforeWriteContent shouldn't be called for lock requests. -* Fixed: Problem with POST requests to the outbox if mailto: was not lower - cased. -* Fixed: Yearly recurrence rule expansion on leap-days no behaves correctly. -* Fixed: Correctly checking if recurring, all-day events with no dtstart fall in - a timerange if the start of the time-range exceeds the start of the instance - of an event, but not the end. -* Fixed: All-day recurring events wouldn't match if an occurence ended exactly - on the start of a time-range. -* Fixed: HTTP basic auth did not correctly deal with passwords containing colons - on some servers. -* Fixed: Issue 228: DTEND is now non-inclusive for all-day events in the - calendar-query REPORT and free-busy calculations. - - -1.6.3 (2012-06-12) ------------------- - -* Added: It's now possible to specify in Sabre_DAV_Client which type of - authentication is to be used. -* Fixed: Issue 206: Sabre_DAV_Client PUT requests are fixed. -* Fixed: Issue 205: Parsing an iCalendar 0-second date interval. -* Fixed: Issue 112: Stronger validation of iCalendar objects. Now making sure - every iCalendar object only contains 1 component, and disallowing vcards, - forcing every component to have a UID. -* Fixed: Basic validation for vcards in the CardDAV plugin. -* Fixed: Issue 213: Workaround for an Evolution bug, that prevented it from - updating events. -* Fixed: Issue 211: A time-limit query on a non-relative alarm trigger in a - recurring event could result in an endless loop. -* Fixed: All uri fields are now a maximum of 200 characters. The Bynari outlook - plugin used much longer strings so this should improve compatibility. -* Fixed: Added a workaround for a bug in KDE 4.8.2 contact syncing. See - https://bugs.kde.org/show_bug.cgi?id=300047 -* Fixed: Issue 217: Sabre_DAV_Tree_FileSystem was pretty broken. - - -1.6.2 (2012-04-16) ------------------- - -* Fixed: Sabre_VObject_Node::$parent should have been public. -* Fixed: Recurrence rules of events are now taken into consideration when doing - time-range queries on alarms. -* Fixed: Added a workaround for the fact that php's DateInterval cannot parse - weeks and days at the same time. -* Added: Sabre_DAV_Server::$exposeVersion, allowing you to hide SabreDAV's - version number from various outputs. -* Fixed: DTSTART values would be incorrect when expanding events. -* Fixed: DTSTART and DTEND would be incorrect for expansion of WEEKLY BYDAY - recurrences. -* Fixed: Issue 203: A problem with overridden events hitting the exact date and - time of a subsequent event in the recurrence set. -* Fixed: There was a problem with recurrence rules, for example the 5th tuesday - of the month, if this day did not exist. -* Added: New HTTP status codes from draft-nottingham-http-new-status-04. - - -1.6.1 (2012-03-05) ------------------- - -* Added: createFile and put() can now return an ETag. -* Added: Sending back an ETag on for operations on CardDAV backends. This should - help with OS X 10.6 Addressbook compatibility. -* Fixed: Fixed a bug where an infinite loop could occur in the recurrence - iterator if the recurrence was YEARLY, with a BYMONTH rule, and either BYDAY - or BYMONTHDAY match the first day of the month. -* Fixed: Events that are excluded using EXDATE are still counted in the COUNT= - parameter in the RRULE property. -* Added: Support for time-range filters on VALARM components. -* Fixed: Correctly filtering all-day events. -* Fixed: Sending back correct mimetypes from the browser plugin (thanks - Jürgen). -* Fixed: Issue 195: Sabre_CardDAV pear package had an incorrect dependency. -* Fixed: Calendardata would be destroyed when performing a MOVE request. - - -1.6.0 (2012-02-22) ------------------- - -* BC Break: Now requires PHP 5.3 -* BC Break: Any node that implemented Sabre_DAVACL_IACL must now also implement - the getSupportedPrivilegeSet method. See website for details. -* BC Break: Moved functions from Sabre_CalDAV_XMLUtil to - Sabre_VObject_DateTimeParser. -* BC Break: The Sabre_DAVACL_IPrincipalCollection now has two new methods: - 'searchPrincipals' and 'updatePrincipal'. -* BC Break: Sabre_DAV_ILockable is removed and all related per-node locking - functionality. -* BC Break: Sabre_DAV_Exception_FileNotFound is now deprecated in favor of - Sabre_DAV_Exception_NotFound. The former will be removed in a later version. -* BC Break: Removed Sabre_CalDAV_ICalendarUtil, use Sabre_VObject instead. -* BC Break: Sabre_CalDAV_Server is now deprecated, check out the documentation - on how to setup a caldav server with just Sabre_DAV_Server. -* BC Break: Default Principals PDO backend now needs a new field in the - 'principals' table. See the website for details. -* Added: Ability to create new calendars and addressbooks from within the - browser plugin. -* Added: Browser plugin: icons for various nodes. -* Added: Support for FREEBUSY reports! -* Added: Support for creating principals with admin-level privileges. -* Added: Possibility to let server send out invitation emails on behalf of - CalDAV client, using Sabre_CalDAV_Schedule_IMip. -* Changed: beforeCreateFile event now passes data argument by reference. -* Changed: The 'propertyMap' property from Sabre_VObject_Reader, must now be - specified in Sabre_VObject_Property::$classMap. -* Added: Ability for plugins to tell the ACL plugin which principal plugins are - searchable. -* Added: [DAVACL] Per-node overriding of supported privileges. This allows for - custom privileges where needed. -* Added: [DAVACL] Public 'principalSearch' method on the DAVACL plugin, which - allows for easy searching for principals, based on their properties. -* Added: Sabre_VObject_Component::getComponents() to return a list of only - components and not properties. -* Added: An includes.php file in every sub-package (CalDAV, CardDAV, DAV, - DAVACL, HTTP, VObject) as an alternative to the autoloader. This often works - much faster. -* Added: Support for the 'Me card', which allows Addressbook.app users specify - which vcard is their own. -* Added: Support for updating principal properties in the DAVACL principal - backends. -* Changed: Major refactoring in the calendar-query REPORT code. Should make - things more flexible and correct. -* Changed: The calendar-proxy-[read|write] principals will now only appear in - the tree, if they actually exist in the Principal backend. This should reduce - some problems people have been having with this. -* Changed: Sabre_VObject_Element_* classes are now renamed to - Sabre_VObject_Property. Old classes are retained for backwards compatibility, - but this will be removed in the future. -* Added: Sabre_VObject_FreeBusyGenerator to generate free-busy reports based on - lists of events. -* Added: Sabre_VObject_RecurrenceIterator to find all the dates and times for - recurring events. -* Fixed: Issue 97: Correctly handling RRULE for the calendar-query REPORT. -* Fixed: Issue 154: Encoding of VObject parameters with no value was incorrect. -* Added: Support for {DAV:}acl-restrictions property from RFC3744. -* Added: The contentlength for calendar objects can now be supplied by a CalDAV - backend, allowing for more optimizations. -* Fixed: Much faster implementation of Sabre_DAV_URLUtil::encodePath. -* Fixed: {DAV:}getcontentlength may now be not specified. -* Fixed: Issue 66: Using rawurldecode instead of urldecode to decode paths from - clients. This means that + will now be treated as a literal rather than a - space, and this should improve compatibility with the Windows built-in client. -* Added: Sabre_DAV_Exception_PaymentRequired exception, to emit HTTP 402 status - codes. -* Added: Some mysql unique constraints to example files. -* Fixed: Correctly formatting HTTP dates. -* Fixed: Issue 94: Sending back Last-Modified header for 304 responses. -* Added: Sabre_VObject_Component_VEvent, Sabre_VObject_Component_VJournal, - Sabre_VObject_Component_VTodo and Sabre_VObject_Component_VCalendar. -* Changed: Properties are now also automatically mapped to their appropriate - classes, if they are created using the add() or __set() methods. -* Changed: Cloning VObject objects now clones the entire tree, rather than just - the default shallow copy. -* Added: Support for recurrence expansion in the CALDAV:calendar-multiget and - CALDAV:calendar-query REPORTS. -* Changed: CalDAV PDO backend now sorts calendars based on the internal - 'calendarorder' field. -* Added: Issue 181: Carddav backends may no optionally not supply the carddata - in getCards, if etag and size are specified. This may speed up certain - requests. -* Added: More arguments to beforeWriteContent and beforeCreateFile (see - WritingPlugins wiki document). -* Added: Hook for iCalendar validation. This allows us to validate iCalendar - objects when they're uploaded. At the moment we're just validating syntax. -* Added: VObject now support Windows Timezone names correctly (thanks mrpace2). -* Added: If a timezonename could not be detected, we fall back on the default - PHP timezone. -* Added: Now a Composer package (thanks willdurand). -* Fixed: Support for \N as a newline character in the VObject reader. -* Added: afterWriteContent, afterCreateFile and afterUnbind events. -* Added: Postgresql example files. Not part of the unittests though, so use at - your own risk. -* Fixed: Issue 182: Removed backticks from sql queries, so it will work with - Postgres. - - -1.5.9 (2012-04-16) ------------------- - -* Fixed: Issue with parsing timezone identifiers that were surrounded by quotes. - (Fixes emClient compatibility). - - -1.5.8 (2012-02-22) ------------------- - -* Fixed: Issue 95: Another timezone parsing issue, this time in calendar-query. - - -1.5.7 (2012-02-19) ------------------- - -* Fixed: VObject properties are now always encoded before components. -* Fixed: Sabre_DAVACL had issues with multiple levels of privilege aggregration. -* Changed: Added 'GuessContentType' plugin to fileserver.php example. -* Fixed: The Browser plugin will now trigger the correct events when creating - files. -* Fixed: The ICSExportPlugin now considers ACL's. -* Added: Made it optional to supply carddata from an Addressbook backend when - requesting getCards. This can make some operations much faster, and could - result in much lower memory use. -* Fixed: Issue 187: Sabre_DAV_UUIDUtil was missing from includes file. -* Fixed: Issue 191: beforeUnlock was triggered twice. - - -1.5.6 (2012-01-07) ------------------- - -* Fixed: Issue 174: VObject could break UTF-8 characters. -* Fixed: pear package installation issues. - - -1.5.5 (2011-12-16) ------------------- - -* Fixed: CalDAV time-range filter workaround for recurring events. -* Fixed: Bug in Sabre_DAV_Locks_Backend_File that didn't allow multiple files to - be locked at the same time. - - -1.5.4 (2011-10-28) ------------------- - -* Fixed: GuessContentType plugin now supports mixed case file extensions. -* Fixed: DATE-TIME encoding was wrong in VObject. (we used 'DATETIME'). -* Changed: Sending back HTTP 204 after a PUT request on an existing resource - instead of HTTP 200. This should fix Evolution CardDAV client compatibility. -* Fixed: Issue 95: Parsing X-LIC-LOCATION if it's available. -* Added: All VObject elements now have a reference to their parent node. - - -1.5.3 (2011-09-28) ------------------- - -* Fixed: Sabre_DAV_Collection was missing from the includes file. -* Fixed: Issue 152. iOS 1.4.2 apparantly requires HTTP/1.1 200 OK to be in - uppercase. -* Fixed: Issue 153: Support for files with mixed newline styles in - Sabre_VObject. -* Fixed: Issue 159: Automatically converting any vcard and icalendardata to - UTF-8. -* Added: Sabre_DAV_SimpleFile class for easy static file creation. -* Added: Issue 158: Support for the CARDDAV:supported-address-data property. - - -1.5.2 (2011-09-21) ------------------- - -* Fixed: carddata and calendardata MySQL fields are now of type 'mediumblob'. - 'TEXT' was too small sometimes to hold all the data. -* Fixed: {DAV:}supported-report-set is now correctly reporting the reports for - IAddressBook. -* Added: Sabre_VObject_Property::add() to add duplicate parameters to - properties. -* Added: Issue 151: Sabre_CalDAV_ICalendar and Sabre_CalDAV_ICalendarObject - interfaces. -* Fixed: Issue 140: Not returning 201 Created if an event cancelled the creation - of a file. -* Fixed: Issue 150: Faster URLUtil::encodePath() implementation. -* Fixed: Issue 144: Browser plugin could interfere with - TemporaryFileFilterPlugin if it was loaded first. -* Added: It's not possible to specify more 'alternate uris' in principal - backends. - - -1.5.1 (2011-08-24) ------------------- - -* Fixed: Issue 137. Hiding action interface in HTML browser for non-collections. -* Fixed: addressbook-query is now correctly returned from the - {DAV:}supported-report-set property. -* Fixed: Issue 142: Bugs in groupwareserver.php example. -* Fixed: Issue 139: Rejecting PUT requests with Content-Range. - - -1.5.0 (2011-08-12) ------------------- - -* Added: CardDAV support. -* Added: An experimental WebDAV client. -* Added: MIME-Directory grouping support in the VObject library. This is very - useful for people attempting to parse vcards. -* BC Break: Adding parameters with the VObject libraries now overwrites the - previous parameter, rather than just add it. This makes more sense for 99% of - the cases. -* BC Break: lib/Sabre.autoload.php is now removed in favor of - lib/Sabre/autoload.php. -* Deprecated: Sabre_DAV_Directory is now deprecated and will be removed in a - future version. Use Sabre_DAV_Collection instead. -* Deprecated: Sabre_DAV_SimpleDirectory is now deprecated and will be removed in - a future version. Use Sabre_DAV_SimpleCollection instead. -* Fixed: Problem with overriding tablenames for the CalDAV backend. -* Added: Clark-notation parser to XML utility. -* Added: unset() support to VObject components. -* Fixed: Refactored CalDAV property fetching to be faster and simpler. -* Added: Central string-matcher for CalDAV and CardDAV plugins. -* Added: i;unicode-casemap support -* Fixed: VObject bug: wouldn't parse parameters if they weren't specified in - uppercase. -* Fixed: VObject bug: Parameters now behave more like Properties. -* Fixed: VObject bug: Parameters with no value are now correctly parsed. -* Changed: If calendars don't specify which components they allow, 'all' - components are assumed (e.g.: VEVENT, VTODO, VJOURNAL). -* Changed: Browser plugin now uses POST variable 'sabreAction' instead of - 'action' to reduce the chance of collisions. - - -1.4.4 (2011-07-07) ------------------- - -* Fixed: Issue 131: Custom CalDAV backends could break in certain cases. -* Added: The option to override the default tablename all PDO backends use. - (Issue 60). -* Fixed: Issue 124: 'File' authentication backend now takes realm into - consideration. -* Fixed: Sabre_DAV_Property_HrefList now properly deserializes. This allows - users to update the {DAV:}group-member-set property. -* Added: Helper functions for DateTime-values in Sabre_VObject package. -* Added: VObject library can now automatically map iCalendar properties to - custom classes. - - -1.4.3 (2011-04-25) ------------------- - -* Fixed: Issue 123: Added workaround for Windows 7 UNLOCK bug. -* Fixed: datatype of lastmodified field in mysql.calendars.sql. Please change - the DATETIME field to an INT to ensure this field will work correctly. -* Change: Sabre_DAV_Property_Principal is now renamed to - Sabre_DAVACL_Property_Principal. -* Added: API level support for ACL HTTP method. -* Fixed: Bug in serializing {DAV:}acl property. -* Added: deserializer for {DAV:}resourcetype property. -* Added: deserializer for {DAV:}acl property. -* Added: deserializer for {DAV:}principal property. - - -1.4.2-beta (2011-04-01) ------------------------ - -* Added: It's not possible to disable listing of nodes that are denied read - access by ACL. -* Fixed: Changed a few properties in CalDAV classes from private to protected. -* Fixed: Issue 119: Terrible things could happen when relying on guessBaseUri, - the server was running on the root of the domain and a user tried to access a - file ending in .php. This is a slight BC break. -* Fixed: Issue 118: Lock tokens in If headers without a uri should be treated as - the request uri, not 'all relevant uri's. -* Fixed: Issue 120: PDO backend was incorrectly fetching too much locks in cases - where there were similar named locked files in a directory. - - -1.4.1-beta (2011-02-26) ------------------------ - -* Fixed: Sabre_DAV_Locks_Backend_PDO returned too many locks. -* Fixed: Sabre_HTTP_Request::getHeader didn't return Content-Type when running - on apache, so a few workarounds were added. -* Change: Slightly changed CalDAV Backend API's, to allow for heavy - optimizations. This is non-bc breaking. - - -1.4.0-beta (2011-02-12) ------------------------ - -* Added: Partly RFC3744 ACL support. -* Added: Calendar-delegation (caldav-proxy) support. -* BC break: In order to fix Issue 99, a new argument had to be added to - Sabre_DAV_Locks_Backend_*::getLocks classes. Consult the classes for details. -* Deprecated: Sabre_DAV_Locks_Backend_FS is now deprecated and will be removed - in a later version. Use PDO or the new File class instead. -* Deprecated: The Sabre_CalDAV_ICalendarUtil class is now marked deprecated, and - will be removed in a future version. Please use Sabre_VObject instead. -* Removed: All principal-related functionality has been removed from the - Sabre_DAV_Auth_Plugin, and moved to the Sabre_DAVACL_Plugin. -* Added: VObject library, for easy vcard/icalendar parsing using a natural - interface. -* Added: Ability to automatically generate full .ics feeds off calendars. To - use: Add the Sabre_CalDAV_ICSExportPlugin, and add ?export to your calendar - url. -* Added: Plugins can now specify a pluginname, for easy access using - Sabre_DAV_Server::getPlugin(). -* Added: beforeGetProperties event. -* Added: updateProperties event. -* Added: Principal listings and calendar-access can now be done privately, - disallowing users from accessing or modifying other users' data. -* Added: You can now pass arrays to the Sabre_DAV_Server constructor. If it's an - array with node-objects, a Root collection will automatically be created, and - the nodes are used as top-level children. -* Added: The principal base uri is now customizable. It used to be hardcoded to - 'principals/[user]'. -* Added: getSupportedReportSet method in ServerPlugin class. This allows you to - easily specify which reports you're implementing. -* Added: A '..' link to the HTML browser. -* Fixed: Issue 99: Locks on child elements were ignored when their parent nodes - were deleted. -* Fixed: Issue 90: lockdiscovery property and LOCK response now include a - {DAV}lockroot element. -* Fixed: Issue 96: support for 'default' collation in CalDAV text-match filters. -* Fixed: Issue 102: Ensuring that copy and move with identical source and - destination uri's fails. -* Fixed: Issue 105: Supporting MKCALENDAR with no body. -* Fixed: Issue 109: Small fixes in Sabre_HTTP_Util. -* Fixed: Issue 111: Properly catching the ownername in a lock (if it's a string) -* Fixed: Sabre_DAV_ObjectTree::nodeExist always returned false for the root - node. -* Added: Global way to easily supply new resourcetypes for certain node classes. -* Fixed: Issue 59: Allowing the user to override the authentication realm in - Sabre_CalDAV_Server. -* Update: Issue 97: Looser time-range checking if there's a recurrence rule in - an event. This fixes 'missing recurring events'. - - -1.3.0 (2010-10-14) ------------------- - -* Added: childExists method to Sabre_DAV_ICollection. This is an api break, so - if you implement Sabre_DAV_ICollection directly, add the method. -* Changed: Almost all HTTP method implementations now take a uri argument, - including events. This allows for internal rerouting of certain calls. If you - have custom plugins, make sure they use this argument. If they don't, they - will likely still work, but it might get in the way of future changes. -* Changed: All getETag methods MUST now surround the etag with double-quotes. - This was a mistake made in all previous SabreDAV versions. If you don't do - this, any If-Match, If-None-Match and If: headers using Etags will work - incorrectly. (Issue 85). -* Added: Sabre_DAV_Auth_Backend_AbstractBasic class, which can be used to easily - implement basic authentication. -* Removed: Sabre_DAV_PermissionDenied class. Use Sabre_DAV_Forbidden instead. -* Removed: Sabre_DAV_IDirectory interface, use Sabre_DAV_ICollection instead. -* Added: Browser plugin now uses {DAV:}displayname if this property is - available. -* Added: Cache layer in the ObjectTree. -* Added: Tree classes now have a delete and getChildren method. -* Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if the - date is an exact match. -* Fixed: Support for multiple ETags in If-Match and If-None-Match headers. -* Fixed: Improved baseUrl handling. -* Fixed: Issue 67: Non-seekable stream support in ::put()/::get(). -* Fixed: Issue 65: Invalid dates are now ignored. -* Updated: Refactoring in Sabre_CalDAV to make everything a bit more ledgable. -* Fixed: Issue 88, Issue 89: Fixed compatibility for running SabreDAV on - Windows. -* Fixed: Issue 86: Fixed Content-Range top-boundary from 'file size' to 'file - size'-1. - - -1.2.5 (2010-08-18) ------------------- - -* Fixed: Issue 73: guessBaseUrl fails for some servers. -* Fixed: Issue 67: SabreDAV works better with non-seekable streams. -* Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if - the date is an exact match. - - -1.2.4 (2010-07-13) ------------------- - -* Fixed: Issue 62: Guessing baseUrl fails when url contains a query-string. -* Added: Apache configuration sample for CGI/FastCGI setups. -* Fixed: Issue 64: Only returning calendar-data when it was actually requested. - - -1.2.3 (2010-06-26) ------------------- - -* Fixed: Issue 57: Supporting quotes around etags in If-Match and If-None-Match - - -1.2.2 (2010-06-21) ------------------- - -* Updated: SabreDAV now attempts to guess the BaseURI if it's not set. -* Updated: Better compatibility with BitKinex -* Fixed: Issue 56: Incorrect behaviour for If-None-Match headers and GET - requests. -* Fixed: Issue with certain encoded paths in Browser Plugin. - - -1.2.1 (2010-06-07) ------------------- - -* Fixed: Issue 50, patch by Mattijs Hoitink. -* Fixed: Issue 51, Adding windows 7 lockfiles to TemporaryFileFilter. -* Fixed: Issue 38, Allowing custom filters to be added to TemporaryFileFilter. -* Fixed: Issue 53, ETags in the If: header were always failing. This behaviour - is now corrected. -* Added: Apache Authentication backend, in case authentication through .htaccess - is desired. -* Updated: Small improvements to example files. - - -1.2.0 (2010-05-24) ------------------- - -* Fixed: Browser plugin now displays international characters. -* Changed: More properties in CalDAV classes are now protected instead of - private. - - -1.2.0beta3 (2010-05-14) ------------------------ - -* Fixed: Custom properties were not properly sent back for allprops requests. -* Fixed: Issue 49, incorrect parsing of PROPPATCH, affecting Office 2007. -* Changed: Removed CalDAV items from includes.php, and added a few missing ones. - - -1.2.0beta2 (2010-05-04) ------------------------ - -* Fixed: Issue 46: Fatal error for some non-existent nodes. -* Updated: some example sql to include email address. -* Added: 208 and 508 statuscodes from RFC5842. -* Added: Apache2 configuration examples - - -1.2.0beta1 (2010-04-28) ------------------------ - -* Fixed: redundant namespace declaration in resourcetypes. -* Fixed: 2 locking bugs triggered by litmus when no Sabre_DAV_ILockable - interface is used. -* Changed: using http://sabredav.org/ns for all custom xml properties. -* Added: email address property to principals. -* Updated: CalendarObject validation. - - -1.2.0alpha4 (2010-04-24) ------------------------- - -* Added: Support for If-Range, If-Match, If-None-Match, If-Modified-Since, - If-Unmodified-Since. -* Changed: Brand new build system. Functionality is split up between Sabre, - Sabre_HTTP, Sabre_DAV and Sabre_CalDAV packages. In addition to that a new - non-pear package will be created with all this functionality combined. -* Changed: Autoloader moved to Sabre/autoload.php. -* Changed: The Allow: header is now more accurate, with appropriate HTTP methods - per uri. -* Changed: Now throwing back Sabre_DAV_Exception_MethodNotAllowed on a few - places where Sabre_DAV_Exception_NotImplemented was used. - - -1.2.0alpha3 (2010-04-20) ------------------------- - -* Update: Complete rewrite of property updating. Now easier to use and atomic. -* Fixed: Issue 16, automatically adding trailing / to baseUri. -* Added: text/plain is used for .txt files in GuessContentType plugin. -* Added: support for principal-property-search and principal-search-property-set - reports. -* Added: Issue 31: Hiding exception information by default. Can be turned on - with the Sabre_DAV_Server::$debugExceptions property. - - -1.2.0alpha2 (2010-04-08) ------------------------- - -* Added: Calendars are now private and can only be read by the owner. -* Fixed: double namespace declaration in multistatus responses. -* Added: MySQL database dumps. MySQL is now also supported next to SQLite. -* Added: expand-properties REPORT from RFC 3253. -* Added: Sabre_DAV_Property_IHref interface for properties exposing urls. -* Added: Issue 25: Throwing error on broken Finder behaviour. -* Changed: Authentication backend is now aware of current user. - - -1.2.0alpha1 (2010-03-31) ------------------------- - -* Fixed: Issue 26: Workaround for broken GVFS behaviour with encoded special - characters. -* Fixed: Issue 34: Incorrect Lock-Token response header for LOCK. Fixes Office - 2010 compatibility. -* Added: Issue 35: SabreDAV version to header to OPTIONS response to ease - debugging. -* Fixed: Issue 36: Incorrect variable name, throwing error in some requests. -* Fixed: Issue 37: Incorrect smultron regex in temporary filefilter. -* Fixed: Issue 33: Converting ISO-8859-1 characters to UTF-8. -* Fixed: Issue 39 & Issue 40: Basename fails on non-utf-8 locales. -* Added: More unittests. -* Added: SabreDAV version to all error responses. -* Added: URLUtil class for decoding urls. -* Changed: Now using pear.sabredav.org pear channel. -* Changed: Sabre_DAV_Server::getCopyAndMoveInfo is now a public method. - - -1.1.2-alpha (2010-03-18) ------------------------- - -* Added: RFC5397 - current-user-principal support. -* Fixed: Issue 27: encoding entities in property responses. -* Added: naturalselection script now allows the user to specify a 'minimum - number of bytes' for deletion. This should reduce load due to less crawling -* Added: Full support for the calendar-query report. -* Added: More unittests. -* Added: Support for complex property deserialization through the static - ::unserialize() method. -* Added: Support for modifying calendar-component-set -* Fixed: Issue 29: Added TIMEOUT_INFINITE constant - - -1.1.1-alpha (2010-03-11) ------------------------- - -* Added: RFC5689 - Extended MKCOL support. -* Fixed: Evolution support for CalDAV. -* Fixed: PDO-locks backend was pretty much completely broken. This is 100% - unittested now. -* Added: support for ctags. -* Fixed: Comma's between HTTP methods in 'Allow' method. -* Changed: default argument for Sabre_DAV_Locks_Backend_FS. This means a - datadirectory must always be specified from now on. -* Changed: Moved Sabre_DAV_Server::parseProps to - Sabre_DAV_XMLUtil::parseProperties. -* Changed: Sabre_DAV_IDirectory is now Sabre_DAV_ICollection. -* Changed: Sabre_DAV_Exception_PermissionDenied is now - Sabre_DAV_Exception_Forbidden. -* Changed: Sabre_CalDAV_ICalendarCollection is removed. -* Added: Sabre_DAV_IExtendedCollection. -* Added: Many more unittests. -* Added: support for calendar-timezone property. - - -1.1.0-alpha (2010-03-01) ------------------------- - -* Note: This version is forked from version 1.0.5, so release dates may be out - of order. -* Added: CalDAV - RFC 4791 -* Removed: Sabre_PHP_Exception. PHP has a built-in ErrorException for this. -* Added: PDO authentication backend. -* Added: Example sql for auth, caldav, locks for sqlite. -* Added: Sabre_DAV_Browser_GuessContentType plugin -* Changed: Authentication plugin refactored, making it possible to implement - non-digest authentication. -* Fixed: Better error display in browser plugin. -* Added: Support for {DAV:}supported-report-set -* Added: XML utility class with helper functions for the WebDAV protocol. -* Added: Tons of unittests -* Added: PrincipalCollection and Principal classes -* Added: Sabre_DAV_Server::getProperties for easy property retrieval -* Changed: {DAV:}resourceType defaults to 0 -* Changed: Any non-null resourceType now gets a / appended to the href value. - Before this was just for {DAV:}collection's, but this is now also the case for - for example {DAV:}principal. -* Changed: The Href property class can now optionally create non-relative uri's. -* Changed: Sabre_HTTP_Response now returns false if headers are already sent and - header-methods are called. -* Fixed: Issue 19: HEAD requests on Collections -* Fixed: Issue 21: Typo in Sabre_DAV_Property_Response -* Fixed: Issue 18: Doesn't work with Evolution Contacts - - -1.0.15 (2010-05-28) -------------------- - -* Added: Issue 31: Hiding exception information by default. Can be turned on - with the Sabre_DAV_Server::$debugExceptions property. -* Added: Moved autoload from lib/ to lib/Sabre/autoload.php. This is also the - case in the upcoming 1.2.0, so it will improve future compatibility. - - -1.0.14 (2010-04-15) -------------------- - -* Fixed: double namespace declaration in multistatus responses. - - -1.0.13 (2010-03-30) -------------------- - -* Fixed: Issue 40: Last references to basename/dirname - - -1.0.12 (2010-03-30) -------------------- - -* Fixed: Issue 37: Incorrect smultron regex in temporary filefilter. -* Fixed: Issue 26: Workaround for broken GVFS behaviour with encoded special - characters. -* Fixed: Issue 33: Converting ISO-8859-1 characters to UTF-8. -* Fixed: Issue 39: Basename fails on non-utf-8 locales. -* Added: More unittests. -* Added: SabreDAV version to all error responses. -* Added: URLUtil class for decoding urls. -* Updated: Now using pear.sabredav.org pear channel. - - -1.0.11 (2010-03-23) -------------------- - -* Non-public release. This release is identical to 1.0.10, but it is used to - test releasing packages to pear.sabredav.org. - - -1.0.10 (2010-03-22) -------------------- - -* Fixed: Issue 34: Invalid Lock-Token header response. -* Added: Issue 35: Addign SabreDAV version to HTTP OPTIONS responses. - - -1.0.9 (2010-03-19) ------------------- - -* Fixed: Issue 27: Entities not being encoded in PROPFIND responses. -* Fixed: Issue 29: Added missing TIMEOUT_INFINITE constant. - - -1.0.8 (2010-03-03) ------------------- - -* Fixed: Issue 21: typos causing errors -* Fixed: Issue 23: Comma's between methods in Allow header. -* Added: Sabre_DAV_ICollection interface, to aid in future compatibility. -* Added: Sabre_DAV_Exception_Forbidden exception. This will replace - Sabre_DAV_Exception_PermissionDenied in the future, and can already be used to - ensure future compatibility. - - -1.0.7 (2010-02-24) ------------------- - -* Fixed: Issue 19 regression for MS Office - - -1.0.6 (2010-02-23) ------------------- - -* Fixed: Issue 19: HEAD requests on Collections - - -1.0.5 (2010-01-22) ------------------- - -* Fixed: Fatal error when a malformed url was used for unlocking, in conjuction - with Sabre.autoload.php due to a incorrect filename. -* Fixed: Improved unittests and build system - - -1.0.4 (2010-01-11) ------------------- - -* Fixed: needed 2 different releases. One for googlecode and one for pearfarm. - This is to retain the old method to install SabreDAV until pearfarm becomes - the standard installation method. - - -1.0.3 (2010-01-11) ------------------- - -* Added: RFC4709 support (davmount) -* Added: 6 unittests -* Added: naturalselection. A tool to keep cache directories below a specified - theshold. -* Changed: Now using pearfarm.org channel server. - - -1.0.1 (2009-12-22) ------------------- - -* Fixed: Issue 15: typos in examples -* Fixed: Minor pear installation issues - - -1.0.0 (2009-11-02) ------------------- - -* Added: SimpleDirectory class. This class allows creating static directory - structures with ease. -* Changed: Custom complex properties and exceptions now get an instance of - Sabre_DAV_Server as their first argument in serialize() -* Changed: Href complex property now prepends server's baseUri -* Changed: delete before an overwriting copy/move is now handles by server class - instead of tree classes -* Changed: events must now explicitly return false to stop execution. Before, - execution would be stopped by anything loosely evaluating to false. -* Changed: the getPropertiesForPath method now takes a different set of - arguments, and returns a different response. This allows plugin developers to - return statuses for properties other than 200 and 404. The hrefs are now also - always calculated relative to the baseUri, and not the uri of the request. -* Changed: generatePropFindResponse is renamed to generateMultiStatus, and now - takes a list of properties similar to the response of getPropertiesForPath. - This was also needed to improve flexibility for plugin development. -* Changed: Auth plugins are no longer included. They were not yet stable - quality, so they will probably be reintroduced in a later version. -* Changed: PROPPATCH also used generateMultiStatus now. -* Removed: unknownProperties event. This is replaced by the afterGetProperties - event, which should provide more flexibility. -* Fixed: Only calling getSize() on IFile instances in httpHead() -* Added: beforeBind event. This is invoked upon file or directory creation -* Added: beforeWriteContent event, this is invoked by PUT and LOCK on an - existing resource. -* Added: beforeUnbind event. This is invoked right before deletion of any - resource. -* Added: afterGetProperties event. This event can be used to make modifications - to property responses. -* Added: beforeLock and beforeUnlock events. -* Added: afterBind event. -* Fixed: Copy and Move could fail in the root directory. This is now fixed. -* Added: Plugins can now be retrieved by their classname. This is useful for - inter-plugin communication. -* Added: The Auth backend can now return usernames and user-id's. -* Added: The Auth backend got a getUsers method -* Added: Sabre_DAV_FSExt_Directory now returns quota info - - -0.12.1-beta (2009-09-11) ------------------------- - -* Fixed: UNLOCK bug. Unlock didn't work at all - - -0.12-beta (2009-09-10) ----------------------- - -* Updated: Browser plugin now shows multiple {DAV:}resourcetype values if - available. -* Added: Experimental PDO backend for Locks Manager -* Fixed: Sending Content-Length: 0 for every empty response. This improves NGinx - compatibility. -* Fixed: Last modification time is reported in UTC timezone. This improves - Finder compatibility. - - -0.11-beta (2009-08-11) ----------------------- - -* Updated: Now in Beta -* Updated: Pear package no longer includes docs/ directory. These just contained - rfc's, which are publicly available. This reduces the package from ~800k to - ~60k -* Added: generatePropfindResponse now takes a baseUri argument -* Added: ResourceType property can now contain multiple resourcetypes. -* Fixed: Issue 13. - - -0.10-alpha (2009-08-03) ------------------------ - -* Added: Plugin to automatically map GET requests to non-files to PROPFIND - (Sabre_DAV_Browser_MapGetToPropFind). This should allow easier debugging of - complicated WebDAV setups. -* Added: Sabre_DAV_Property_Href class. For future use. -* Added: Ability to choose to use auth-int, auth or both for HTTP Digest - authentication. (Issue 11) -* Changed: Made more methods in Sabre_DAV_Server public. -* Fixed: TemporaryFileFilter plugin now intercepts HTTP LOCK requests to - non-existent files. (Issue 12) -* Added: Central list of defined xml namespace prefixes. This can reduce - Bandwidth and legibility for xml bodies with user-defined namespaces. -* Added: now a PEAR-compatible package again, thanks to Michael Gauthier -* Changed: moved default copy and move logic from ObjectTree to Tree class - -0.9a-alpha (2009-07-21) ----------------------- - -* Fixed: Broken release - -0.9-alpha (2009-07-21) ----------------------- - -* Changed: Major refactoring, removed most of the logic from the Tree objects. - The Server class now directly works with the INode, IFile and IDirectory - objects. If you created your own Tree objects, this will most likely break in - this release. -* Changed: Moved all the Locking logic from the Tree and Server classes into a - separate plugin. -* Changed: TemporaryFileFilter is now a plugin. -* Added: Comes with an autoloader script. This can be used instead of the - includer script, and is preferred by some people. -* Added: AWS Authentication class. -* Added: simpleserversetup.py script. This will quickly get a fileserver up and - running. -* Added: When subscribing to events, it is now possible to supply a priority. - This is for example needed to ensure that the Authentication Plugin is used - before any other Plugin. -* Added: 22 new tests. -* Added: Users-manager plugin for .htdigest files. Experimental and subject to - change. -* Added: RFC 2324 HTTP 418 status code -* Fixed: Exclusive locks could in some cases be picked up as shared locks -* Fixed: Digest auth for non-apache servers had a bug (still not actually tested - this well). - - -0.8-alpha (2009-05-30) ----------------------- - -* Changed: Renamed all exceptions! This is a compatibility break. Every - Exception now follows Sabre_DAV_Exception_FileNotFound convention instead of - Sabre_DAV_FileNotFoundException. -* Added: Browser plugin now allows uploading and creating directories straight - from the browser. -* Added: 12 more unittests -* Fixed: Locking bug, which became prevalent on Windows Vista. -* Fixed: Netdrive support -* Fixed: TemporaryFileFilter filtered out too many files. Fixed some of the - regexes. -* Fixed: Added README and ChangeLog to package - - -0.7-alpha (2009-03-29) ----------------------- - -* Added: System to return complex properties from PROPFIND. -* Added: support for {DAV:}supportedlock. -* Added: support for {DAV:}lockdiscovery. -* Added: 6 new tests. -* Added: New plugin system. -* Added: Simple HTML directory plugin, for browser access. -* Added: Server class now sends back standard pre-condition error xml bodies. - This was new since RFC4918. -* Added: Sabre_DAV_Tree_Aggregrate, which can 'host' multiple Tree objects into - one. -* Added: simple basis for HTTP REPORT method. This method is not used yet, but - can be used by plugins to add reports. -* Changed: ->getSize is only called for files, no longer for collections. r303 -* Changed: Sabre_DAV_FilterTree is now Sabre_DAV_Tree_Filter -* Changed: Sabre_DAV_TemporaryFileFilter is now called - Sabre_DAV_Tree_TemporaryFileFilter. -* Changed: removed functions (get(/set)HTTPRequest(/Response)) from Server - class, and using a public property instead. -* Fixed: bug related to parsing proppatch and propfind requests. Didn't show up - in most clients, but it needed fixing regardless. (r255) -* Fixed: auth-int is now properly supported within HTTP Digest. -* Fixed: Using application/xml for a mimetype vs. text/xml as per RFC4918 sec - 8.2. -* Fixed: TemporaryFileFilter now lets through GET's if they actually exist on - the backend. (r274) -* FIxed: Some methods didn't get passed through in the FilterTree (r283). -* Fixed: LockManager is now slightly more complex, Tree classes slightly less. - (r287) - - -0.6-alpha (2009-02-16) ----------------------- - -* Added: Now uses streams for files, instead of strings. This means it won't - require to hold entire files in memory, which can be an issue if you're - dealing with big files. Note that this breaks compatibility for put() and - createFile methods. -* Added: HTTP Digest Authentication helper class. -* Added: Support for HTTP Range header -* Added: Support for ETags within If: headers -* Added: The API can now return ETags and override the default Content-Type -* Added: starting with basic framework for unittesting, using PHPUnit. -* Added: 49 unittests. -* Added: Abstraction for the HTTP request. -* Updated: Using Clark Notation for tags in properties. This means tags are - serialized as {namespace}tagName instead of namespace#tagName -* Fixed: HTTP_BasicAuth class now works as expected. -* Fixed: DAV_Server uses / for a default baseUrl. -* Fixed: Last modification date is no longer ignored in PROPFIND. -* Fixed: PROPFIND now sends back information about the requestUri even when - "Depth: 1" is specified. - - -0.5-alpha (2009-01-14) ----------------------- - -* Added: Added a very simple example for implementing a mapping to PHP file - streams. This should allow easy implementation of for example a WebDAV to FTP - proxy. -* Added: HTTP Basic Authentication helper class. -* Added: Sabre_HTTP_Response class. This centralizes HTTP operations and will be - a start towards the creating of a testing framework. -* Updated: Backwards compatibility break: all require_once() statements are - removed from all the files. It is now recommended to use autoloading of - classes, or just including lib/Sabre.includes.php. This fix was made to allow - easier integration into applications not using this standard inclusion model. -* Updated: Better in-file documentation. -* Updated: Sabre_DAV_Tree can now work with Sabre_DAV_LockManager. -* Updated: Fixes a shared-lock bug. -* Updated: Removed ?> from the bottom of each php file. -* Updated: Split up some operations from Sabre_DAV_Server to - Sabre_HTTP_Response. -* Fixed: examples are now actually included in the pear package. - - -0.4-alpha (2008-11-05) ----------------------- - -* Passes all litmus tests! -* Added: more examples -* Added: Custom property support -* Added: Shared lock support -* Added: Depth support to locks -* Added: Locking on unmapped urls (non-existent nodes) -* Fixed: Advertising as WebDAV class 3 support - - -0.3-alpha (2008-06-29) ----------------------- - -* Fully working in MS Windows clients. -* Added: temporary file filter: support for smultron files. -* Added: Phing build scripts -* Added: PEAR package -* Fixed: MOVE bug identified using finder. -* Fixed: Using gzuncompress instead of gzdecode in the temporary file filter. - This seems more common. - - -0.2-alpha (2008-05-27) ----------------------- - -* Somewhat working in Windows clients -* Added: Working PROPPATCH method (doesn't support custom properties yet) -* Added: Temporary filename handling system -* Added: Sabre_DAV_IQuota to return quota information -* Added: PROPFIND now reads the request body and only supplies the requested - properties - - -0.1-alpha (2008-04-04) ----------------------- - -* First release! -* Passes litmus: basic, http and copymove test. -* Fully working in Finder and DavFS2. - -Project started: 2007-12-13 - -[vobj]: http://sabre.io/vobject/ -[evnt]: http://sabre.io/event/ -[http]: http://sabre.io/http/ -[uri]: http://sabre.io/uri/ -[xml]: http://sabre.io/xml/ -[mi20]: http://sabre.io/dav/upgrade/1.8-to-2.0/ -[rfc6638]: http://tools.ietf.org/html/rfc6638 "CalDAV Scheduling" -[rfc7240]: http://tools.ietf.org/html/rfc7240 -[calendar-availability]: https://tools.ietf.org/html/draft-daboo-calendar-availability-05 diff --git a/vendor/sabre/dav/LICENSE b/vendor/sabre/dav/LICENSE deleted file mode 100644 index fd3539e33..000000000 --- a/vendor/sabre/dav/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (C) 2007-2016 fruux GmbH (https://fruux.com/). - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of SabreDAV nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sabre/dav/README.md b/vendor/sabre/dav/README.md deleted file mode 100644 index 278187b55..000000000 --- a/vendor/sabre/dav/README.md +++ /dev/null @@ -1,29 +0,0 @@ -![sabre's logo](http://sabre.io/img/logo.png) SabreDAV -====================================================== - -Introduction ------------- - -SabreDAV is the most popular WebDAV framework for PHP. Use it to create WebDAV, CalDAV and CardDAV servers. - -Full documentation can be found on the website: - -http://sabre.io/ - -Build status ------------- - -| branch | status | minimum PHP version | -| ------------ | ------ | ------------------- | -| master | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=master)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 | -| 3.0 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=3.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | -| 2.1 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=2.1)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | -| 2.0 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=2.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | -| 1.8 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.8)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | -| 1.7 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.7)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | -| 1.6 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=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. diff --git a/vendor/sabre/dav/bin/build.php b/vendor/sabre/dav/bin/build.php index 82b1e7530..c4ba20941 100755 --- a/vendor/sabre/dav/bin/build.php +++ b/vendor/sabre/dav/bin/build.php @@ -110,7 +110,7 @@ function test() { echo " Running all unittests.\n"; echo " This may take a while.\n\n"; - system(__DIR__ . '/phpunit --configuration ' . $baseDir . '/tests/phpunit.xml --stop-on-failure', $code); + system(__DIR__ . '/phpunit --configuration ' . $baseDir . '/tests/phpunit.xml.dist --stop-on-failure', $code); if ($code != 0) { echo "PHPUnit reported error code $code\n"; die(1); diff --git a/vendor/sabre/dav/bin/migrateto17.php b/vendor/sabre/dav/bin/migrateto17.php index a1173c584..3ccf0a380 100755 --- a/vendor/sabre/dav/bin/migrateto17.php +++ b/vendor/sabre/dav/bin/migrateto17.php @@ -3,7 +3,7 @@ echo "SabreDAV migrate script for version 1.7\n"; -if ($argc < 2) { +if ($argc<2) { echo <<getAttribute(PDO::ATTR_DRIVER_NAME)) { + switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) { case 'mysql' : @@ -150,7 +150,7 @@ $stmt = $pdo->prepare('UPDATE calendarobjects SET etag = ?, size = ?, componentt echo "Total records found: " . $result->rowCount() . "\n"; $done = 0; $total = $result->rowCount(); -while ($row = $result->fetch()) { +while($row = $result->fetch()) { try { $newData = getDenormalizedData($row['calendardata']); @@ -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([ + $stmt->execute(array( $newData['etag'], $newData['size'], $newData['componentType'], $newData['firstOccurence'], $newData['lastOccurence'], $row['id'], - ]); + )); $done++; if ($done % 500 === 0) { @@ -188,7 +188,7 @@ if (array_key_exists('transparent', $row)) { echo "Adding the 'transparent' field to the calendars table\n"; - switch ($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) { + switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) { case 'mysql' : $pdo->exec("ALTER TABLE calendars ADD transparent TINYINT(1) NOT NULL DEFAULT '0'"); @@ -229,8 +229,8 @@ function getDenormalizedData($calendarData) { $component = null; $firstOccurence = null; $lastOccurence = null; - foreach ($vObject->getComponents() as $component) { - if ($component->name !== 'VTIMEZONE') { + foreach($vObject->getComponents() as $component) { + if ($component->name!=='VTIMEZONE') { $componentType = $component->name; break; } @@ -262,7 +262,7 @@ function getDenormalizedData($calendarData) { $lastOccurence = $maxDate->getTimeStamp(); } else { $end = $it->getDtEnd(); - while ($it->valid() && $end < $maxDate) { + while($it->valid() && $end < $maxDate) { $end = $it->getDtEnd(); $it->next(); @@ -273,12 +273,12 @@ function getDenormalizedData($calendarData) { } } - return [ - 'etag' => md5($calendarData), - 'size' => strlen($calendarData), - 'componentType' => $componentType, + return array( + 'etag' => md5($calendarData), + 'size' => strlen($calendarData), + 'componentType' => $componentType, 'firstOccurence' => $firstOccurence, 'lastOccurence' => $lastOccurence, - ]; + ); } diff --git a/vendor/sabre/dav/bin/migrateto21.php b/vendor/sabre/dav/bin/migrateto21.php index f42c4cf88..c81ee5cca 100755 --- a/vendor/sabre/dav/bin/migrateto21.php +++ b/vendor/sabre/dav/bin/migrateto21.php @@ -169,10 +169,6 @@ switch ($driver) { ) '); break; - $pdo->exec(' - CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri); - '); - break; } echo "Done.\n"; diff --git a/vendor/sabre/dav/bin/migrateto32.php b/vendor/sabre/dav/bin/migrateto32.php new file mode 100755 index 000000000..59732b511 --- /dev/null +++ b/vendor/sabre/dav/bin/migrateto32.php @@ -0,0 +1,268 @@ +#!/usr/bin/env php +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 "Creating 'calendarinstances'\n"; +$addValueType = false; +try { + $result = $pdo->query('SELECT * FROM calendarinstances LIMIT 1'); + $result->fetch(\PDO::FETCH_ASSOC); + echo "calendarinstances exists. Assuming this part of the migration has already been done.\n"; +} catch (Exception $e) { + echo "calendarinstances does not yet exist. Creating table and migrating data.\n"; + + switch ($driver) { + case 'mysql' : + $pdo->exec(<<exec(" +INSERT INTO calendarinstances + ( + calendarid, + principaluri, + access, + displayname, + uri, + description, + calendarorder, + calendarcolor, + transparent + ) +SELECT + id, + principaluri, + 1, + displayname, + uri, + description, + calendarorder, + calendarcolor, + transparent +FROM calendars +"); + break; + case 'sqlite' : + $pdo->exec(<<exec(" +INSERT INTO calendarinstances + ( + calendarid, + principaluri, + access, + displayname, + uri, + description, + calendarorder, + calendarcolor, + transparent + ) +SELECT + id, + principaluri, + 1, + displayname, + uri, + description, + calendarorder, + calendarcolor, + transparent +FROM calendars +"); + break; + } + +} +try { + $result = $pdo->query('SELECT * FROM calendars LIMIT 1'); + $row = $result->fetch(\PDO::FETCH_ASSOC); + + if (!$row) { + echo "Source table is empty.\n"; + $migrateCalendars = true; + } + + $columnCount = count($row); + if ($columnCount === 3) { + echo "The calendars table has 3 columns already. Assuming this part of the migration was already done.\n"; + $migrateCalendars = false; + } else { + echo "The calendars table has " . $columnCount . " columns.\n"; + $migrateCalendars = true; + } + +} catch (Exception $e) { + echo "calendars table does not exist. This is a major problem. Exiting.\n"; + exit(-1); +} + +if ($migrateCalendars) { + + $calendarBackup = 'calendars_3_1_' . $backupPostfix; + echo "Backing up 'calendars' to '", $calendarBackup, "'\n"; + + switch ($driver) { + case 'mysql' : + $pdo->exec('RENAME TABLE calendars TO ' . $calendarBackup); + break; + case 'sqlite' : + $pdo->exec('ALTER TABLE calendars RENAME TO ' . $calendarBackup); + break; + + } + + echo "Creating new calendars table.\n"; + switch ($driver) { + case 'mysql' : + $pdo->exec(<<exec(<<exec(<<propertyMap); - $fields[] = 'id'; + $fields[] = 'calendarid'; $fields[] = 'uri'; $fields[] = 'synctoken'; $fields[] = 'components'; $fields[] = 'principaluri'; $fields[] = 'transparent'; + $fields[] = 'access'; // Making fields a comma-delimited list $fields = implode(', ', $fields); - $stmt = $this->pdo->prepare("SELECT " . $fields . " FROM " . $this->calendarTableName . " WHERE principaluri = ? ORDER BY calendarorder ASC"); + $stmt = $this->pdo->prepare(<<calendarInstancesTableName}.id as id, $fields FROM {$this->calendarInstancesTableName} + LEFT JOIN {$this->calendarTableName} ON + {$this->calendarInstancesTableName}.calendarid = {$this->calendarTableName}.id +WHERE principaluri = ? ORDER BY calendarorder ASC +SQL + ); $stmt->execute([$principalUri]); $calendars = []; @@ -161,15 +184,27 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S } $calendar = [ - 'id' => $row['id'], + 'id' => [(int)$row['calendarid'], (int)$row['id']], 'uri' => $row['uri'], 'principaluri' => $row['principaluri'], '{' . CalDAV\Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken'] ? $row['synctoken'] : '0'), '{http://sabredav.org/ns}sync-token' => $row['synctoken'] ? $row['synctoken'] : '0', '{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new CalDAV\Xml\Property\SupportedCalendarComponentSet($components), '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp' => new CalDAV\Xml\Property\ScheduleCalendarTransp($row['transparent'] ? 'transparent' : 'opaque'), + 'share-resource-uri' => '/ns/share/' . $row['calendarid'], ]; + $calendar['share-access'] = (int)$row['access']; + // 1 = owner, 2 = readonly, 3 = readwrite + if ($row['access'] > 1) { + // We need to find more information about the original owner. + //$stmt2 = $this->pdo->prepare('SELECT principaluri FROM ' . $this->calendarInstancesTableName . ' WHERE access = 1 AND id = ?'); + //$stmt2->execute([$row['id']]); + + // read-only is for backwards compatbility. Might go away in + // the future. + $calendar['read-only'] = (int)$row['access'] === \Sabre\DAV\Sharing\Plugin::ACCESS_READ; + } foreach ($this->propertyMap as $xmlName => $dbName) { $calendar[$xmlName] = $row[$dbName]; @@ -199,31 +234,38 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S $fieldNames = [ 'principaluri', 'uri', - 'synctoken', 'transparent', + 'calendarid', ]; $values = [ ':principaluri' => $principalUri, ':uri' => $calendarUri, - ':synctoken' => 1, ':transparent' => 0, ]; - // Default value + $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'; - $fieldNames[] = 'components'; if (!isset($properties[$sccs])) { - $values[':components'] = 'VEVENT,VTODO'; + // Default value + $components = 'VEVENT,VTODO'; } else { if (!($properties[$sccs] instanceof CalDAV\Xml\Property\SupportedCalendarComponentSet)) { throw new DAV\Exception('The ' . $sccs . ' property must be of type: \Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet'); } - $values[':components'] = implode(',', $properties[$sccs]->getValue()); + $components = implode(',', $properties[$sccs]->getValue()); } $transp = '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp'; if (isset($properties[$transp])) { - $values[':transparent'] = $properties[$transp]->getValue() === 'transparent'; + $values[':transparent'] = $properties[$transp]->getValue() === 'transparent' ? 1 : 0; } + $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarTableName . " (synctoken, components) VALUES (1, ?)"); + $stmt->execute([$components]); + + $calendarId = $this->pdo->lastInsertId( + $this->calendarTableName . '_id_seq' + ); + + $values[':calendarid'] = $calendarId; foreach ($this->propertyMap as $xmlName => $dbName) { if (isset($properties[$xmlName])) { @@ -233,10 +275,14 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S } } - $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")"); + $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarInstancesTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")"); + $stmt->execute($values); - return $this->pdo->lastInsertId(); + return [ + $calendarId, + $this->pdo->lastInsertId($this->calendarInstancesTableName . '_id_seq') + ]; } @@ -252,16 +298,21 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S * * Read the PropPatch documenation for more info and examples. * - * @param string $calendarId + * @param mixed $calendarId * @param \Sabre\DAV\PropPatch $propPatch * @return void */ function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + $supportedProperties = array_keys($this->propertyMap); $supportedProperties[] = '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp'; - $propPatch->handle($supportedProperties, function($mutations) use ($calendarId) { + $propPatch->handle($supportedProperties, function($mutations) use ($calendarId, $instanceId) { $newValues = []; foreach ($mutations as $propertyName => $propertyValue) { @@ -282,8 +333,8 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S $valuesSql[] = $fieldName . ' = ?'; } - $stmt = $this->pdo->prepare("UPDATE " . $this->calendarTableName . " SET " . implode(', ', $valuesSql) . " WHERE id = ?"); - $newValues['id'] = $calendarId; + $stmt = $this->pdo->prepare("UPDATE " . $this->calendarInstancesTableName . " SET " . implode(', ', $valuesSql) . " WHERE id = ?"); + $newValues['id'] = $instanceId; $stmt->execute(array_values($newValues)); $this->addChange($calendarId, "", 2); @@ -297,19 +348,49 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S /** * Delete a calendar and all it's objects * - * @param string $calendarId + * @param mixed $calendarId * @return void */ function deleteCalendar($calendarId) { - $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ?'); - $stmt->execute([$calendarId]); + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; - $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarTableName . ' WHERE id = ?'); - $stmt->execute([$calendarId]); + $stmt = $this->pdo->prepare('SELECT access FROM ' . $this->calendarInstancesTableName . ' where id = ?'); + $stmt->execute([$instanceId]); + $access = (int)$stmt->fetchColumn(); + + if ($access === \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER) { + + /** + * If the user is the owner of the calendar, we delete all data and all + * instances. + **/ + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ?'); + $stmt->execute([$calendarId]); + + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarChangesTableName . ' WHERE calendarid = ?'); + $stmt->execute([$calendarId]); + + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarInstancesTableName . ' WHERE calendarid = ?'); + $stmt->execute([$calendarId]); + + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarTableName . ' WHERE id = ?'); + $stmt->execute([$calendarId]); + + } else { + + /** + * If it was an instance of a shared calendar, we only delete that + * instance. + */ + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarInstancesTableName . ' WHERE id = ?'); + $stmt->execute([$instanceId]); + + } - $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarChangesTableName . ' WHERE calendarid = ?'); - $stmt->execute([$calendarId]); } @@ -341,11 +422,16 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S * used/fetched to determine these numbers. If both are specified the * amount of times this is needed is reduced by a great degree. * - * @param string $calendarId + * @param mixed $calendarId * @return array */ function getCalendarObjects($calendarId) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ?'); $stmt->execute([$calendarId]); @@ -354,9 +440,8 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S $result[] = [ 'id' => $row['id'], 'uri' => $row['uri'], - 'lastmodified' => $row['lastmodified'], + 'lastmodified' => (int)$row['lastmodified'], 'etag' => '"' . $row['etag'] . '"', - 'calendarid' => $row['calendarid'], 'size' => (int)$row['size'], 'component' => strtolower($row['componenttype']), ]; @@ -378,12 +463,17 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S * * This method must return null if the object did not exist. * - * @param string $calendarId + * @param mixed $calendarId * @param string $objectUri * @return array|null */ function getCalendarObject($calendarId, $objectUri) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, calendardata, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri = ?'); $stmt->execute([$calendarId, $objectUri]); $row = $stmt->fetch(\PDO::FETCH_ASSOC); @@ -393,9 +483,8 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S return [ 'id' => $row['id'], 'uri' => $row['uri'], - 'lastmodified' => $row['lastmodified'], + 'lastmodified' => (int)$row['lastmodified'], 'etag' => '"' . $row['etag'] . '"', - 'calendarid' => $row['calendarid'], 'size' => (int)$row['size'], 'calendardata' => $row['calendardata'], 'component' => strtolower($row['componenttype']), @@ -417,6 +506,11 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S */ function getMultipleCalendarObjects($calendarId, array $uris) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + $query = 'SELECT id, uri, lastmodified, etag, calendarid, size, calendardata, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri IN ('; // Inserting a whole bunch of question marks $query .= implode(',', array_fill(0, count($uris), '?')); @@ -431,9 +525,8 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S $result[] = [ 'id' => $row['id'], 'uri' => $row['uri'], - 'lastmodified' => $row['lastmodified'], + 'lastmodified' => (int)$row['lastmodified'], 'etag' => '"' . $row['etag'] . '"', - 'calendarid' => $row['calendarid'], 'size' => (int)$row['size'], 'calendardata' => $row['calendardata'], 'component' => strtolower($row['componenttype']), @@ -465,6 +558,11 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S */ function createCalendarObject($calendarId, $objectUri, $calendarData) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + $extraData = $this->getDenormalizedData($calendarData); $stmt = $this->pdo->prepare('INSERT INTO ' . $this->calendarObjectTableName . ' (calendarid, uri, calendardata, lastmodified, etag, size, componenttype, firstoccurence, lastoccurence, uid) VALUES (?,?,?,?,?,?,?,?,?,?)'); @@ -506,6 +604,11 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S */ function updateCalendarObject($calendarId, $objectUri, $calendarData) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + $extraData = $this->getDenormalizedData($calendarData); $stmt = $this->pdo->prepare('UPDATE ' . $this->calendarObjectTableName . ' SET calendardata = ?, lastmodified = ?, etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ?, uid = ? WHERE calendarid = ? AND uri = ?'); @@ -583,6 +686,10 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S } } + + // Ensure Occurence values are positive + if ($firstOccurence < 0) $firstOccurence = 0; + if ($lastOccurence < 0) $lastOccurence = 0; } // Destroy circular references to PHP will GC the object. @@ -604,12 +711,17 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S * * The object uri is only the basename, or filename and not a full path. * - * @param string $calendarId + * @param mixed $calendarId * @param string $objectUri * @return void */ function deleteCalendarObject($calendarId, $objectUri) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri = ?'); $stmt->execute([$calendarId, $objectUri]); @@ -665,12 +777,17 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S * This specific implementation (for the PDO) backend optimizes filters on * specific components, and VEVENT time-ranges. * - * @param string $calendarId + * @param mixed $calendarId * @param array $filters * @return array */ function calendarQuery($calendarId, array $filters) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + $componentType = null; $requirePostFilter = true; $timeRange = null; @@ -766,14 +883,14 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S $query = <<calendarObjectTableName AS calendarobjects LEFT JOIN - $this->calendarTableName AS calendars - ON calendarobjects.calendarid = calendars.id + $this->calendarInstancesTableName AS calendar_instances + ON calendarobjects.calendarid = calendar_instances.calendarid WHERE - calendars.principaluri = ? + calendar_instances.principaluri = ? AND calendarobjects.uid = ? SQL; @@ -837,7 +954,7 @@ SQL; * * The limit is 'suggestive'. You are free to ignore it. * - * @param string $calendarId + * @param mixed $calendarId * @param string $syncToken * @param int $syncLevel * @param int $limit @@ -845,6 +962,11 @@ SQL; */ function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null) { + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + // Current synctoken $stmt = $this->pdo->prepare('SELECT synctoken FROM ' . $this->calendarTableName . ' WHERE id = ?'); $stmt->execute([ $calendarId ]); @@ -1043,7 +1165,9 @@ SQL; $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarSubscriptionsTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")"); $stmt->execute($values); - return $this->pdo->lastInsertId(); + return $this->pdo->lastInsertId( + $this->calendarSubscriptionsTableName . '_id_seq' + ); } @@ -1207,4 +1331,179 @@ SQL; } + /** + * Updates the list of shares. + * + * @param mixed $calendarId + * @param \Sabre\DAV\Xml\Element\Sharee[] $sharees + * @return void + */ + function updateInvites($calendarId, array $sharees) { + + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); + } + $currentInvites = $this->getInvites($calendarId); + list($calendarId, $instanceId) = $calendarId; + + $removeStmt = $this->pdo->prepare("DELETE FROM " . $this->calendarInstancesTableName . " WHERE calendarid = ? AND share_href = ? AND access IN (2,3)"); + $updateStmt = $this->pdo->prepare("UPDATE " . $this->calendarInstancesTableName . " SET access = ?, share_displayname = ?, share_invitestatus = ? WHERE calendarid = ? AND share_href = ?"); + + $insertStmt = $this->pdo->prepare(' +INSERT INTO ' . $this->calendarInstancesTableName . ' + ( + calendarid, + principaluri, + access, + displayname, + uri, + description, + calendarorder, + calendarcolor, + timezone, + transparent, + share_href, + share_displayname, + share_invitestatus + ) + SELECT + ?, + ?, + ?, + displayname, + ?, + description, + calendarorder, + calendarcolor, + timezone, + 1, + ?, + ?, + ? + FROM ' . $this->calendarInstancesTableName . ' WHERE id = ?'); + + foreach ($sharees as $sharee) { + + if ($sharee->access === \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS) { + // if access was set no NOACCESS, it means access for an + // existing sharee was removed. + $removeStmt->execute([$calendarId, $sharee->href]); + continue; + } + + if (is_null($sharee->principal)) { + // If the server could not determine the principal automatically, + // we will mark the invite status as invalid. + $sharee->inviteStatus = \Sabre\DAV\Sharing\Plugin::INVITE_INVALID; + } else { + // Because sabre/dav does not yet have an invitation system, + // every invite is automatically accepted for now. + $sharee->inviteStatus = \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED; + } + + foreach ($currentInvites as $oldSharee) { + + if ($oldSharee->href === $sharee->href) { + // This is an update + $sharee->properties = array_merge( + $oldSharee->properties, + $sharee->properties + ); + $updateStmt->execute([ + $sharee->access, + isset($sharee->properties['{DAV:}displayname']) ? $sharee->properties['{DAV:}displayname'] : null, + $sharee->inviteStatus ?: $oldSharee->inviteStatus, + $calendarId, + $sharee->href + ]); + continue 2; + } + + } + // If we got here, it means it was a new sharee + $insertStmt->execute([ + $calendarId, + $sharee->principal, + $sharee->access, + \Sabre\DAV\UUIDUtil::getUUID(), + $sharee->href, + isset($sharee->properties['{DAV:}displayname']) ? $sharee->properties['{DAV:}displayname'] : null, + $sharee->inviteStatus ?: \Sabre\DAV\Sharing\Plugin::INVITE_NORESPONSE, + $instanceId + ]); + + } + + } + + /** + * Returns the list of people whom a calendar is shared with. + * + * Every item in the returned list must be a Sharee object with at + * least the following properties set: + * $href + * $shareAccess + * $inviteStatus + * + * and optionally: + * $properties + * + * @param mixed $calendarId + * @return \Sabre\DAV\Xml\Element\Sharee[] + */ + function getInvites($calendarId) { + + if (!is_array($calendarId)) { + throw new \InvalidArgumentException('The value passed to getInvites() is expected to be an array with a calendarId and an instanceId'); + } + list($calendarId, $instanceId) = $calendarId; + + $query = <<calendarInstancesTableName} +WHERE + calendarid = ? +SQL; + + $stmt = $this->pdo->prepare($query); + $stmt->execute([$calendarId]); + + $result = []; + while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + + $result[] = new Sharee([ + 'href' => isset($row['share_href']) ? $row['share_href'] : \Sabre\HTTP\encodePath($row['principaluri']), + 'access' => (int)$row['access'], + /// Everyone is always immediately accepted, for now. + 'inviteStatus' => (int)$row['share_invitestatus'], + 'properties' => + !empty($row['share_displayname']) + ? [ '{DAV:}displayname' => $row['share_displayname'] ] + : [], + 'principal' => $row['principaluri'], + ]); + + } + return $result; + + } + + /** + * Publishes a calendar + * + * @param mixed $calendarId + * @param bool $value + * @return void + */ + function setPublishStatus($calendarId, $value) { + + throw new \Exception('Not implemented'); + + } + } diff --git a/vendor/sabre/dav/lib/CalDAV/Backend/SharingSupport.php b/vendor/sabre/dav/lib/CalDAV/Backend/SharingSupport.php index 6a11b0ab1..8b6e074e0 100644 --- a/vendor/sabre/dav/lib/CalDAV/Backend/SharingSupport.php +++ b/vendor/sabre/dav/lib/CalDAV/Backend/SharingSupport.php @@ -5,231 +5,48 @@ namespace Sabre\CalDAV\Backend; /** * Adds support for sharing features to a CalDAV server. * - * Note: This feature is experimental, and may change in between different - * SabreDAV versions. + * CalDAV backends that implement this interface, must make the following + * modifications to getCalendarsForUser: * - * Early warning: Currently SabreDAV provides no implementation for this. This - * is, because in it's current state there is no elegant way to do this. - * The problem lies in the fact that a real CalDAV server with sharing support - * would first need email support (with invite notifications), and really also - * a browser-frontend that allows people to accept or reject these shares. - * - * In addition, the CalDAV backends are currently kept as independent as - * possible, and should not be aware of principals, email addresses or - * accounts. - * - * Adding an implementation for Sharing to standard-sabredav would contradict - * these goals, so for this reason this is currently not implemented, although - * it may very well in the future; but probably not before SabreDAV 2.0. - * - * The interface works however, so if you implement all this, and do it - * correctly sharing _will_ work. It's not particularly easy, and I _urge you_ - * to make yourself acquainted with the following document first: - * - * https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt - * - * An overview - * =========== - * - * Implementing this interface will allow a user to share his or her calendars - * to other users. Effectively, when a calendar is shared the calendar will - * show up in both the Sharer's and Sharee's calendar-home root. - * This interface adds a few methods that ensure that this happens, and there - * are also a number of new requirements in the base-class you must now follow. - * - * - * How it works - * ============ - * - * When a user shares a calendar, the updateShares() method will be called with - * a list of sharees that are now added, and a list of sharees that have been - * removed. - * Removal is instant, but when a sharee is added the sharee first gets a - * chance to accept or reject the invitation for a share. - * - * After a share is accepted, the calendar will be returned from - * getUserCalendars for both the sharer, and the sharee. - * - * If the sharee deletes the calendar, only their share gets deleted. When the - * owner deletes a calendar, it will be removed for everybody. - * - * - * Notifications - * ============= - * - * During all these sharing operations, a lot of notifications are sent back - * and forward. - * - * Whenever the list of sharees for a calendar has been changed (they have been - * added, removed or modified) all sharees should get a notification for this - * change. - * This notification is always represented by: - * - * Sabre\CalDAV\Notifications\Notification\Invite - * - * In the case of an invite, the sharee may reply with an 'accept' or - * 'decline'. These are always represented by: - * - * Sabre\CalDAV\Notifications\Notification\InviteReply - * - * - * Calendar access by sharees - * ========================== - * - * As mentioned earlier, shared calendars must now also be returned for - * getCalendarsForUser for sharees. A few things change though. - * - * The following properties must be specified: - * - * 1. {http://calendarserver.org/ns/}shared-url - * - * This property MUST contain the url to the original calendar, that is.. the - * path to the calendar from the owner. - * - * 2. {http://sabredav.org/ns}owner-principal - * - * This is a url to to the principal who is sharing the calendar. - * - * 3. {http://sabredav.org/ns}read-only - * - * This should be either 0 or 1, depending on if the user has read-only or - * read-write access to the calendar. - * - * Only when this is done, the calendar will correctly be marked as a calendar - * that's shared to him, thus allowing clients to display the correct interface - * and ACL enforcement. - * - * If a sharee deletes their calendar, only their instance of the calendar - * should be deleted, the original should still exists. - * Pretty much any 'dead' WebDAV properties on these shared calendars should be - * specific to a user. This means that if the displayname is changed by a - * sharee, the original is not affected. This is also true for: - * * The description - * * The color - * * The order - * * And any other dead properties. - * - * Properties like a ctag should not be different for multiple instances of the - * calendar. - * - * Lastly, objects *within* calendars should also have user-specific data. The - * two things that are user-specific are: - * * VALARM objects - * * The TRANSP property - * - * This _also_ implies that if a VALARM is deleted by a sharee for some event, - * this has no effect on the original VALARM. - * - * Understandably, the this last requirement is one of the hardest. - * Realisticly, I can see people ignoring this part of the spec, but that could - * cause a different set of issues. - * - * - * Publishing - * ========== - * - * When a user publishes a url, the server should generate a 'publish url'. - * This is a read-only url, anybody can use to consume the calendar feed. - * - * Calendars are in one of two states: - * * published - * * unpublished - * - * If a calendar is published, the following property should be returned - * for each calendar in getCalendarsForUser. - * - * {http://calendarserver.org/ns/}publish-url - * - * This element should contain a {DAV:}href element, which points to the - * public url that does not require authentication. Unlike every other href, - * this url must be absolute. - * - * Ideally, the following property is always returned - * - * {http://calendarserver.org/ns/}pre-publish-url - * - * This property should contain the url that the calendar _would_ have, if it - * were to be published. iCal uses this to display the url, before the user - * will actually publish it. - * - * - * Selectively disabling publish or share feature - * ============================================== - * - * If Sabre\CalDAV\Property\AllowedSharingModes is returned from - * 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, - * and update the interface appropriately. If this property is not returned by - * the backend, the SharingPlugin automatically injects it and assumes both - * features are available. + * 1. Return shared calendars for users. + * 2. For every calendar, return calendar-resource-uri. This strings is a URI or + * relative URI reference that must be unique for every calendar, but + * identical for every instance of the same shared calenar. + * 3. For every calenar, you must return a share-access element. This element + * should contain one of the Sabre\DAV\Sharing\Plugin:ACCESS_* contants and + * indicates the access level the user has. * * @copyright Copyright (C) fruux GmbH (https://fruux.com/) * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -interface SharingSupport extends NotificationSupport { +interface SharingSupport extends BackendInterface { /** * Updates the list of shares. * - * The first array is a list of people that are to be added to the - * calendar. - * - * Every element in the add array has the following properties: - * * href - A url. Usually a mailto: address - * * commonName - Usually a first and last name, or false - * * summary - A description of the share, can also be false - * * readOnly - A boolean value - * - * Every element in the remove array is just the address string. - * - * Note that if the calendar is currently marked as 'not shared' by and - * this method is called, the calendar should be 'upgraded' to a shared - * calendar. - * * @param mixed $calendarId - * @param array $add - * @param array $remove + * @param \Sabre\DAV\Xml\Element\Sharee[] $sharees * @return void */ - function updateShares($calendarId, array $add, array $remove); + function updateInvites($calendarId, array $sharees); /** * Returns the list of people whom this calendar is shared with. * - * Every element in this array should have the following properties: - * * href - Often a mailto: address - * * commonName - Optional, for example a first + last name - * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. - * * readOnly - boolean - * * summary - Optional, a description for the share + * Every item in the returned list must be a Sharee object with at + * least the following properties set: + * $href + * $shareAccess + * $inviteStatus * - * This method may be called by either the original instance of the - * calendar, as well as the shared instances. In the case of the shared - * instances, it is perfectly acceptable to return an empty array in case - * there are privacy concerns. + * and optionally: + * $properties * * @param mixed $calendarId - * @return array - */ - function getShares($calendarId); - - /** - * This method is called when a user replied to a request to share. - * - * If the user chose to accept the share, this method should return the - * newly created calendar url. - * - * @param string href The sharee who is replying (often a mailto: address) - * @param int status One of the SharingPlugin::STATUS_* constants - * @param string $calendarUri The url to the calendar thats being shared - * @param string $inReplyTo The unique id this message is a response to - * @param string $summary A description of the reply - * @return null|string + * @return \Sabre\DAV\Xml\Element\Sharee[] */ - function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null); + function getInvites($calendarId); /** * Publishes a calendar diff --git a/vendor/sabre/dav/lib/CalDAV/Backend/SimplePDO.php b/vendor/sabre/dav/lib/CalDAV/Backend/SimplePDO.php new file mode 100644 index 000000000..f8238ea9a --- /dev/null +++ b/vendor/sabre/dav/lib/CalDAV/Backend/SimplePDO.php @@ -0,0 +1,296 @@ +pdo = $pdo; + + } + + /** + * Returns a list of calendars for a principal. + * + * 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. This is just the 'base uri' or 'filename' of the calendar. + * * principaluri. The owner of the calendar. Almost always the same as + * principalUri passed to this method. + * + * 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\Xml\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 + */ + function getCalendarsForUser($principalUri) { + + // Making fields a comma-delimited list + $stmt = $this->pdo->prepare("SELECT id, uri FROM simple_calendars WHERE principaluri = ? ORDER BY id ASC"); + $stmt->execute([$principalUri]); + + $calendars = []; + while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + + $calendars[] = [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'principaluri' => $principalUri, + ]; + + } + + return $calendars; + + } + + /** + * 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. + * + * @param string $principalUri + * @param string $calendarUri + * @param array $properties + * @return string + */ + function createCalendar($principalUri, $calendarUri, array $properties) { + + $stmt = $this->pdo->prepare("INSERT INTO simple_calendars (principaluri, uri) VALUES (?, ?)"); + $stmt->execute([$principalUri, $calendarUri]); + + return $this->pdo->lastInsertId(); + + } + + /** + * Delete a calendar and all it's objects + * + * @param string $calendarId + * @return void + */ + function deleteCalendar($calendarId) { + + $stmt = $this->pdo->prepare('DELETE FROM simple_calendarobjects WHERE calendarid = ?'); + $stmt->execute([$calendarId]); + + $stmt = $this->pdo->prepare('DELETE FROM simple_calendars WHERE id = ?'); + $stmt->execute([$calendarId]); + + } + + /** + * Returns all calendar objects within a calendar. + * + * Every item contains an array with the following keys: + * * calendardata - The iCalendar-compatible calendar data + * * 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"') + * * 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. + * + * The calendardata is also optional. If it's not returned + * 'getCalendarObject' will be called later, which *is* expected to return + * calendardata. + * + * If neither etag or size are specified, the calendardata will be + * used/fetched to determine these numbers. If both are specified the + * amount of times this is needed is reduced by a great degree. + * + * @param string $calendarId + * @return array + */ + function getCalendarObjects($calendarId) { + + $stmt = $this->pdo->prepare('SELECT id, uri, calendardata FROM simple_calendarobjects WHERE calendarid = ?'); + $stmt->execute([$calendarId]); + + $result = []; + foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) { + $result[] = [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'etag' => '"' . md5($row['calendardata']) . '"', + 'calendarid' => $calendarId, + 'size' => strlen($row['calendardata']), + 'calendardata' => $row['calendardata'], + ]; + } + + return $result; + + } + + /** + * 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. + * + * This method must return null if the object did not exist. + * + * @param string $calendarId + * @param string $objectUri + * @return array|null + */ + function getCalendarObject($calendarId, $objectUri) { + + $stmt = $this->pdo->prepare('SELECT id, uri, calendardata FROM simple_calendarobjects WHERE calendarid = ? AND uri = ?'); + $stmt->execute([$calendarId, $objectUri]); + $row = $stmt->fetch(\PDO::FETCH_ASSOC); + + if (!$row) return null; + + return [ + 'id' => $row['id'], + 'uri' => $row['uri'], + 'etag' => '"' . md5($row['calendardata']) . '"', + 'calendarid' => $calendarId, + 'size' => strlen($row['calendardata']), + 'calendardata' => $row['calendardata'], + ]; + + } + + /** + * Creates a new calendar object. + * + * 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. + * + * 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 + * the exact same as this request body, you should omit the ETag. + * + * @param mixed $calendarId + * @param string $objectUri + * @param string $calendarData + * @return string|null + */ + function createCalendarObject($calendarId, $objectUri, $calendarData) { + + $stmt = $this->pdo->prepare('INSERT INTO simple_calendarobjects (calendarid, uri, calendardata) VALUES (?,?,?)'); + $stmt->execute([ + $calendarId, + $objectUri, + $calendarData + ]); + + return '"' . md5($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. + * + * 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 + * the exact same as this request body, you should omit the ETag. + * + * @param mixed $calendarId + * @param string $objectUri + * @param string $calendarData + * @return string|null + */ + function updateCalendarObject($calendarId, $objectUri, $calendarData) { + + $stmt = $this->pdo->prepare('UPDATE simple_calendarobjects SET calendardata = ? WHERE calendarid = ? AND uri = ?'); + $stmt->execute([$calendarData, $calendarId, $objectUri]); + + return '"' . md5($calendarData) . '"'; + + } + + /** + * Deletes an existing calendar object. + * + * The object uri is only the basename, or filename and not a full path. + * + * @param string $calendarId + * @param string $objectUri + * @return void + */ + function deleteCalendarObject($calendarId, $objectUri) { + + $stmt = $this->pdo->prepare('DELETE FROM simple_calendarobjects WHERE calendarid = ? AND uri = ?'); + $stmt->execute([$calendarId, $objectUri]); + + } + +} diff --git a/vendor/sabre/dav/lib/CalDAV/Calendar.php b/vendor/sabre/dav/lib/CalDAV/Calendar.php index ff8e19b15..90ace0d21 100644 --- a/vendor/sabre/dav/lib/CalDAV/Calendar.php +++ b/vendor/sabre/dav/lib/CalDAV/Calendar.php @@ -18,6 +18,8 @@ use Sabre\DAV\PropPatch; */ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, DAV\IMultiGet { + use DAVACL\ACLTrait; + /** * This is an array with calendar information * @@ -86,7 +88,7 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, foreach ($this->calendarInfo as $propName => $propValue) { - if ($propName[0] === '{') + if (!is_null($propValue) && $propName[0] === '{') $response[$propName] = $this->calendarInfo[$propName]; } @@ -227,7 +229,7 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, /** * Returns the last modification date as a unix timestamp. * - * @return void + * @return null */ function getLastModified() { @@ -248,19 +250,6 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, } - /** - * 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. * @@ -360,50 +349,6 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, } - /** - * 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. diff --git a/vendor/sabre/dav/lib/CalDAV/CalendarHome.php b/vendor/sabre/dav/lib/CalDAV/CalendarHome.php index a53f829e2..0a4bfb68f 100644 --- a/vendor/sabre/dav/lib/CalDAV/CalendarHome.php +++ b/vendor/sabre/dav/lib/CalDAV/CalendarHome.php @@ -22,6 +22,8 @@ use Sabre\HTTP\URLUtil; */ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL { + use DAVACL\ACLTrait; + /** * CalDAV backend * @@ -147,11 +149,7 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL { 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); - } + return new SharedCalendar($this->caldavBackend, $calendar); } else { return new Calendar($this->caldavBackend, $calendar); } @@ -198,11 +196,7 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL { $objs = []; foreach ($calendars as $calendar) { if ($this->caldavBackend instanceof Backend\SharingSupport) { - if (isset($calendar['{http://calendarserver.org/ns/}shared-url'])) { - $objs[] = new SharedCalendar($this->caldavBackend, $calendar); - } else { - $objs[] = new ShareableCalendar($this->caldavBackend, $calendar); - } + $objs[] = new SharedCalendar($this->caldavBackend, $calendar); } else { $objs[] = new Calendar($this->caldavBackend, $calendar); } @@ -278,11 +272,9 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL { } /** - * Returns the owner principal + * Returns the owner of the calendar home. * - * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * @return string */ function getOwner() { @@ -290,19 +282,6 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL { } - /** - * 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. * @@ -348,37 +327,6 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL { } - /** - * 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() { - - return null; - - } /** * This method is called when a user replied to a request to share. diff --git a/vendor/sabre/dav/lib/CalDAV/CalendarObject.php b/vendor/sabre/dav/lib/CalDAV/CalendarObject.php index 393ca4cbd..001b35112 100644 --- a/vendor/sabre/dav/lib/CalDAV/CalendarObject.php +++ b/vendor/sabre/dav/lib/CalDAV/CalendarObject.php @@ -11,6 +11,8 @@ namespace Sabre\CalDAV; */ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\DAVACL\IACL { + use \Sabre\DAVACL\ACLTrait; + /** * Sabre\CalDAV\Backend\BackendInterface * @@ -191,19 +193,6 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ } - /** - * 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. * @@ -226,22 +215,12 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ // The default ACL return [ [ - 'privilege' => '{DAV:}read', - 'principal' => $this->calendarInfo['principaluri'], - 'protected' => true, - ], - [ - 'privilege' => '{DAV:}write', + 'privilege' => '{DAV:}all', 'principal' => $this->calendarInfo['principaluri'], 'protected' => true, ], [ - 'privilege' => '{DAV:}read', - 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', - 'protected' => true, - ], - [ - 'privilege' => '{DAV:}write', + 'privilege' => '{DAV:}all', 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', 'protected' => true, ], @@ -255,36 +234,4 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\ } - /** - * Updates the ACL - * - * This method will receive a list of new ACE's. - * - * @param array $acl - * @return void - */ - function setACL(array $acl) { - - throw new \Sabre\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() { - - return null; - - } - } diff --git a/vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php b/vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php index 8c296d50f..a3a824c71 100644 --- a/vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php +++ b/vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php @@ -170,13 +170,13 @@ class ICSExportPlugin extends DAV\ServerPlugin { protected function generateResponse($path, $start, $end, $expand, $componentType, $format, $properties, ResponseInterface $response) { $calDataProp = '{' . Plugin::NS_CALDAV . '}calendar-data'; + $calendarNode = $this->server->tree->getNodeForPath($path); $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' => [ @@ -246,17 +246,29 @@ class ICSExportPlugin extends DAV\ServerPlugin { $mergedCalendar = $mergedCalendar->expand($start, $end, $calendarTimeZone); } - $response->setHeader('Content-Type', $format); + $filenameExtension = '.ics'; switch ($format) { case 'text/calendar' : $mergedCalendar = $mergedCalendar->serialize(); + $filenameExtension = '.ics'; break; case 'application/calendar+json' : $mergedCalendar = json_encode($mergedCalendar->jsonSerialize()); + $filenameExtension = '.json'; break; } + $filename = preg_replace( + '/[^a-zA-Z0-9-_ ]/um', + '', + $calendarNode->getName() + ); + $filename .= '-' . date('Y-m-d') . $filenameExtension; + + $response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"'); + $response->setHeader('Content-Type', $format); + $response->setStatus(200); $response->setBody($mergedCalendar); @@ -272,11 +284,11 @@ class ICSExportPlugin extends DAV\ServerPlugin { function mergeObjects(array $properties, array $inputObjects) { $calendar = new VObject\Component\VCalendar(); - $calendar->version = '2.0'; + $calendar->VERSION = '2.0'; if (DAV\Server::$exposeVersion) { - $calendar->prodid = '-//SabreDAV//SabreDAV ' . DAV\Version::VERSION . '//EN'; + $calendar->PRODID = '-//SabreDAV//SabreDAV ' . DAV\Version::VERSION . '//EN'; } else { - $calendar->prodid = '-//SabreDAV//SabreDAV//EN'; + $calendar->PRODID = '-//SabreDAV//SabreDAV//EN'; } if (isset($properties['{DAV:}displayname'])) { $calendar->{'X-WR-CALNAME'} = $properties['{DAV:}displayname']; diff --git a/vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php b/vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php index cfda91a55..7420d94f7 100644 --- a/vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php +++ b/vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php @@ -5,7 +5,7 @@ namespace Sabre\CalDAV; /** * This interface represents a Calendar that can be shared with other users. * - * @copyright Copyright (C) fruux GmbH (https://fruux.com/) + * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ diff --git a/vendor/sabre/dav/lib/CalDAV/ISharedCalendar.php b/vendor/sabre/dav/lib/CalDAV/ISharedCalendar.php index 84442ac21..15f3b5335 100644 --- a/vendor/sabre/dav/lib/CalDAV/ISharedCalendar.php +++ b/vendor/sabre/dav/lib/CalDAV/ISharedCalendar.php @@ -2,6 +2,8 @@ namespace Sabre\CalDAV; +use Sabre\DAV\Sharing\ISharedNode; + /** * This interface represents a Calendar that is shared by a different user. * @@ -9,28 +11,16 @@ namespace Sabre\CalDAV; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -interface ISharedCalendar extends ICalendar { - - /** - * This method should return the url of the owners' copy of the shared - * calendar. - * - * @return string - */ - function getSharedUrl(); +interface ISharedCalendar extends ISharedNode { /** - * Returns the list of people whom this calendar is shared with. + * Marks this calendar as published. * - * Every element in this array should have the following properties: - * * href - Often a mailto: address - * * commonName - Optional, for example a first + last name - * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. - * * readOnly - boolean - * * summary - Optional, a description for the share + * Publishing a calendar should automatically create a read-only, public, + * subscribable calendar. * - * @return array + * @param bool $value + * @return void */ - function getShares(); - + function setPublishStatus($value); } diff --git a/vendor/sabre/dav/lib/CalDAV/Notifications/Collection.php b/vendor/sabre/dav/lib/CalDAV/Notifications/Collection.php index 1fcc1171c..5fda61dfa 100644 --- a/vendor/sabre/dav/lib/CalDAV/Notifications/Collection.php +++ b/vendor/sabre/dav/lib/CalDAV/Notifications/Collection.php @@ -22,6 +22,8 @@ use Sabre\DAVACL; */ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { + use DAVACL\ACLTrait; + /** * The notification backend * @@ -96,78 +98,4 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL { } - /** - * 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 [ - [ - 'principal' => $this->getOwner(), - 'privilege' => '{DAV:}read', - 'protected' => true, - ], - [ - 'principal' => $this->getOwner(), - 'privilege' => '{DAV:}write', - 'protected' => true, - ] - ]; - - } - - /** - * Updates the ACL - * - * This method will receive a list of new ACE's as an array argument. - * - * @param array $acl - * @return void - */ - function setACL(array $acl) { - - throw new DAV\Exception\NotImplemented('Updating ACLs is not implemented here'); - - } - - /** - * 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; - - } - } diff --git a/vendor/sabre/dav/lib/CalDAV/Notifications/Node.php b/vendor/sabre/dav/lib/CalDAV/Notifications/Node.php index 47e78d5de..11df0c94b 100644 --- a/vendor/sabre/dav/lib/CalDAV/Notifications/Node.php +++ b/vendor/sabre/dav/lib/CalDAV/Notifications/Node.php @@ -20,6 +20,8 @@ use Sabre\DAVACL; */ class Node extends DAV\File implements INode, DAVACL\IACL { + use DAVACL\ACLTrait; + /** * The notification backend * @@ -116,78 +118,4 @@ class Node extends DAV\File implements INode, DAVACL\IACL { } - /** - * 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 [ - [ - 'principal' => $this->getOwner(), - 'privilege' => '{DAV:}read', - 'protected' => true, - ], - [ - 'principal' => $this->getOwner(), - 'privilege' => '{DAV:}write', - 'protected' => true, - ] - ]; - - } - - /** - * Updates the ACL - * - * This method will receive a list of new ACE's as an array argument. - * - * @param array $acl - * @return void - */ - function setACL(array $acl) { - - throw new DAV\Exception\NotImplemented('Updating ACLs is not implemented here'); - - } - - /** - * 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; - - } - } diff --git a/vendor/sabre/dav/lib/CalDAV/Plugin.php b/vendor/sabre/dav/lib/CalDAV/Plugin.php index 663490023..71ba75206 100644 --- a/vendor/sabre/dav/lib/CalDAV/Plugin.php +++ b/vendor/sabre/dav/lib/CalDAV/Plugin.php @@ -5,8 +5,9 @@ namespace Sabre\CalDAV; use DateTimeZone; use Sabre\DAV; use Sabre\DAV\Exception\BadRequest; +use Sabre\DAV\INode; use Sabre\DAV\MkCol; -use Sabre\DAV\Xml\Property\Href; +use Sabre\DAV\Xml\Property\LocalHref; use Sabre\DAVACL; use Sabre\VObject; use Sabre\HTTP; @@ -186,6 +187,7 @@ class Plugin extends DAV\ServerPlugin { $server->on('beforeCreateFile', [$this, 'beforeCreateFile']); $server->on('beforeWriteContent', [$this, 'beforeWriteContent']); $server->on('afterMethod:GET', [$this, 'httpAfterGET']); + $server->on('getSupportedPrivilegeSet', [$this, 'getSupportedPrivilegeSet']); $server->xml->namespaceMap[self::NS_CALDAV] = 'cal'; $server->xml->namespaceMap[self::NS_CALENDARSERVER] = 'cs'; @@ -233,9 +235,10 @@ class Plugin extends DAV\ServerPlugin { * * @param string $reportName * @param mixed $report + * @param mixed $path * @return bool */ - function report($reportName, $report) { + function report($reportName, $report, $path) { switch ($reportName) { case '{' . self::NS_CALDAV . '}calendar-multiget' : @@ -341,7 +344,7 @@ class Plugin extends DAV\ServerPlugin { $calendarHomePath = $this->getCalendarHomeForPrincipal($principalUrl); if (is_null($calendarHomePath)) return null; - return new Href($calendarHomePath . '/'); + return new LocalHref($calendarHomePath . '/'); }); // The calendar-user-address-set property is basically mapped to @@ -349,7 +352,7 @@ class Plugin extends DAV\ServerPlugin { $propFind->handle('{' . self::NS_CALDAV . '}calendar-user-address-set', function() use ($node) { $addresses = $node->getAlternateUriSet(); $addresses[] = $this->server->getBaseUri() . $node->getPrincipalUrl() . '/'; - return new Href($addresses, false); + return new LocalHref($addresses); }); // For some reason somebody thought it was a good idea to add // another one of these properties. We're supporting it too. @@ -394,8 +397,8 @@ class Plugin extends DAV\ServerPlugin { } - $propFind->set($propRead, new Href($readList)); - $propFind->set($propWrite, new Href($writeList)); + $propFind->set($propRead, new LocalHref($readList)); + $propFind->set($propWrite, new LocalHref($writeList)); } @@ -821,11 +824,7 @@ class Plugin extends DAV\ServerPlugin { $data = stream_get_contents($data); } - $before = md5($data); - // Converting the data to unicode, if needed. - $data = DAV\StringUtil::ensureUTF8($data); - - if ($before !== md5($data)) $modified = true; + $before = $data; try { @@ -865,7 +864,7 @@ class Plugin extends DAV\ServerPlugin { } $foundType = null; - $foundUID = null; + foreach ($vobj->getComponents() as $component) { switch ($component->name) { case 'VTIMEZONE' : @@ -873,31 +872,59 @@ class Plugin extends DAV\ServerPlugin { case 'VEVENT' : case 'VTODO' : case 'VJOURNAL' : - if (is_null($foundType)) { - $foundType = $component->name; - if (!in_array($foundType, $supportedComponents)) { - throw new Exception\InvalidComponentType('This calendar only supports ' . implode(', ', $supportedComponents) . '. We found a ' . $foundType); - } - if (!isset($component->UID)) { - throw new DAV\Exception\BadRequest('Every ' . $component->name . ' component must have an UID'); - } - $foundUID = (string)$component->UID; - } else { - if ($foundType !== $component->name) { - throw new DAV\Exception\BadRequest('A calendar object must only contain 1 component. We found a ' . $component->name . ' as well as a ' . $foundType); - } - if ($foundUID !== (string)$component->UID) { - throw new DAV\Exception\BadRequest('Every ' . $component->name . ' in this object must have identical UIDs'); - } - } + $foundType = $component->name; break; - default : - throw new DAV\Exception\BadRequest('You are not allowed to create components of type: ' . $component->name . ' here'); + } + + } + + if (!$foundType || !in_array($foundType, $supportedComponents)) { + throw new Exception\InvalidComponentType('iCalendar objects must at least have a component of type ' . implode(', ', $supportedComponents)); + } + + $options = VObject\Node::PROFILE_CALDAV; + $prefer = $this->server->getHTTPPrefer(); + + if ($prefer['handling'] !== 'strict') { + $options |= VObject\Node::REPAIR; + } + + $messages = $vobj->validate($options); + $highestLevel = 0; + $warningMessage = null; + + // $messages contains a list of problems with the vcard, along with + // their severity. + foreach ($messages as $message) { + + if ($message['level'] > $highestLevel) { + // Recording the highest reported error level. + $highestLevel = $message['level']; + $warningMessage = $message['message']; } + switch ($message['level']) { + + case 1 : + // Level 1 means that there was a problem, but it was repaired. + $modified = true; + break; + case 2 : + // Level 2 means a warning, but not critical + break; + case 3 : + // Level 3 means a critical error + throw new DAV\Exception\UnsupportedMediaType('Validation error in iCalendar: ' . $message['message']); + + } + + } + if ($warningMessage) { + $response->setHeader( + 'X-Sabre-Ew-Gross', + 'iCalendar validation warning: ' . $warningMessage + ); } - if (!$foundType) - throw new DAV\Exception\BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL'); // We use an extra variable to allow event handles to tell us wether // the object was modified or not. @@ -917,12 +944,12 @@ class Plugin extends DAV\ServerPlugin { ] ); - if ($subModified) { + if ($modified || $subModified) { // An event handler told us that it modified the object. $data = $vobj->serialize(); // Using md5 to figure out if there was an *actual* change. - if (!$modified && $before !== md5($data)) { + if (!$modified && strcmp($data, $before) !== 0) { $modified = true; } @@ -933,6 +960,22 @@ class Plugin extends DAV\ServerPlugin { } + /** + * This method is triggered whenever a subsystem reqeuests the privileges + * that are supported on a particular node. + * + * @param INode $node + * @param array $supportedPrivilegeSet + */ + function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilegeSet) { + + if ($node instanceof ICalendar) { + $supportedPrivilegeSet['{DAV:}read']['aggregates']['{' . self::NS_CALDAV . '}read-free-busy'] = [ + 'abstract' => false, + 'aggregates' => [], + ]; + } + } /** * This method is used to generate HTML output for the diff --git a/vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php b/vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php index 13212565e..6b374ea3f 100644 --- a/vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php +++ b/vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php @@ -17,6 +17,8 @@ use Sabre\VObject; */ class Inbox extends DAV\Collection implements IInbox { + use DAVACL\ACLTrait; + /** * CalDAV backend * @@ -118,19 +120,6 @@ class Inbox extends DAV\Collection implements IInbox { } - /** - * 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. * @@ -167,58 +156,11 @@ class Inbox extends DAV\Collection implements IInbox { 'protected' => true, ], [ - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-deliver-invite', + 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-deliver', '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; } diff --git a/vendor/sabre/dav/lib/CalDAV/Schedule/Outbox.php b/vendor/sabre/dav/lib/CalDAV/Schedule/Outbox.php index dabaee2ca..29eefa744 100644 --- a/vendor/sabre/dav/lib/CalDAV/Schedule/Outbox.php +++ b/vendor/sabre/dav/lib/CalDAV/Schedule/Outbox.php @@ -19,6 +19,8 @@ use Sabre\DAVACL; */ class Outbox extends DAV\Collection implements IOutbox { + use DAVACL\ACLTrait; + /** * The principal Uri * @@ -74,19 +76,6 @@ class Outbox extends DAV\Collection implements IOutbox { } - /** - * 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. * @@ -103,12 +92,7 @@ class Outbox extends DAV\Collection implements IOutbox { return [ [ - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy', - 'principal' => $this->getOwner(), - 'protected' => true, - ], - [ - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent', + 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-send', 'principal' => $this->getOwner(), 'protected' => true, ], @@ -118,12 +102,7 @@ class Outbox extends DAV\Collection implements IOutbox { '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', + 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-send', 'principal' => $this->getOwner() . '/calendar-proxy-write', 'protected' => true, ], @@ -141,44 +120,4 @@ class Outbox extends DAV\Collection implements IOutbox { } - /** - * 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() { - - $default = DAVACL\Plugin::getDefaultSupportedPrivilegeSet(); - $default['aggregates'][] = [ - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy', - ]; - $default['aggregates'][] = [ - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent', - ]; - - return $default; - - } - } diff --git a/vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php b/vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php index 827d6209b..47511140f 100644 --- a/vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php +++ b/vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php @@ -5,10 +5,12 @@ namespace Sabre\CalDAV\Schedule; use DateTimeZone; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; +use Sabre\DAV\Sharing; use Sabre\DAV\PropFind; use Sabre\DAV\PropPatch; use Sabre\DAV\INode; use Sabre\DAV\Xml\Property\Href; +use Sabre\DAV\Xml\Property\LocalHref; use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; use Sabre\VObject; @@ -100,12 +102,13 @@ class Plugin extends ServerPlugin { 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']); + $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']); + $server->on('getSupportedPrivilegeSet', [$this, 'getSupportedPrivilegeSet']); $ns = '{' . self::NS_CALDAV . '}'; @@ -215,7 +218,7 @@ class Plugin extends ServerPlugin { } $outboxPath = $calendarHomePath . '/outbox/'; - return new Href($outboxPath); + return new LocalHref($outboxPath); }); // schedule-inbox-URL property @@ -227,7 +230,7 @@ class Plugin extends ServerPlugin { } $inboxPath = $calendarHomePath . '/inbox/'; - return new Href($inboxPath); + return new LocalHref($inboxPath); }); @@ -245,18 +248,28 @@ class Plugin extends ServerPlugin { $result = $this->server->getPropertiesForPath($calendarHomePath, [ '{DAV:}resourcetype', + '{DAV:}share-access', $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. + if (!isset($child[200]['{DAV:}resourcetype']) || !$child[200]['{DAV:}resourcetype']->is('{' . self::NS_CALDAV . '}calendar')) { + // Node is either not a calendar continue; } + if (isset($child[200]['{DAV:}share-access'])) { + $shareAccess = $child[200]['{DAV:}share-access']->getValue(); + if ($shareAccess !== Sharing\Plugin::ACCESS_NOTSHARED && $shareAccess !== Sharing\Plugin::ACCESS_SHAREDOWNER) { + // Node is a shared node, not owned by the relevant + // user. + 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']); + return new LocalHref($child['href']); } } @@ -492,7 +505,7 @@ class Plugin extends ServerPlugin { } 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'; + $iTipMessage->scheduleStatus = '3.8;insufficient privileges: ' . $privilege . ' is required on the recipient schedule inbox.'; return; } @@ -560,6 +573,65 @@ class Plugin extends ServerPlugin { } + /** + * This method is triggered whenever a subsystem requests the privileges + * that are supported on a particular node. + * + * We need to add a number of privileges for scheduling purposes. + * + * @param INode $node + * @param array $supportedPrivilegeSet + */ + function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilegeSet) { + + $ns = '{' . self::NS_CALDAV . '}'; + if ($node instanceof IOutbox) { + $supportedPrivilegeSet[$ns . 'schedule-send'] = [ + 'abstract' => false, + 'aggregates' => [ + $ns . 'schedule-send-invite' => [ + 'abstract' => false, + 'aggregates' => [], + ], + $ns . 'schedule-send-reply' => [ + 'abstract' => false, + 'aggregates' => [], + ], + $ns . 'schedule-send-freebusy' => [ + 'abstract' => false, + 'aggregates' => [], + ], + // Privilege from an earlier scheduling draft, but still + // used by some clients. + $ns . 'schedule-post-vevent' => [ + 'abstract' => false, + 'aggregates' => [], + ], + ] + ]; + } + if ($node instanceof IInbox) { + $supportedPrivilegeSet[$ns . 'schedule-deliver'] = [ + 'abstract' => false, + 'aggregates' => [ + $ns . 'schedule-deliver-invite' => [ + 'abstract' => false, + 'aggregates' => [], + ], + $ns . 'schedule-deliver-reply' => [ + 'abstract' => false, + 'aggregates' => [], + ], + $ns . 'schedule-query-freebusy' => [ + 'abstract' => false, + 'aggregates' => [], + ], + ] + ]; + } + + } + /** * This method looks at an old iCalendar object, a new iCalendar object and * starts sending scheduling messages based on the changes. @@ -647,7 +719,7 @@ class Plugin extends ServerPlugin { /** * This method handles POST requests to the schedule-outbox. * - * Currently, two types of requests are support: + * Currently, two types of requests are supported: * * FREEBUSY requests from RFC 6638 * * Simple iTIP messages from draft-desruisseaux-caldav-sched-04 * @@ -699,7 +771,7 @@ class Plugin extends ServerPlugin { if ($componentType === 'VFREEBUSY' && $method === 'REQUEST') { - $acl && $acl->checkPrivileges($outboxPath, '{' . self::NS_CALDAV . '}schedule-query-freebusy'); + $acl && $acl->checkPrivileges($outboxPath, '{' . self::NS_CALDAV . '}schedule-send-freebusy'); $this->handleFreeBusyRequest($outboxNode, $vObject, $request, $response); // Destroy circular references so PHP can GC the object. @@ -727,7 +799,7 @@ class Plugin extends ServerPlugin { protected function handleFreeBusyRequest(IOutbox $outbox, VObject\Component $vObject, RequestInterface $request, ResponseInterface $response) { $vFreeBusy = $vObject->VFREEBUSY; - $organizer = $vFreeBusy->organizer; + $organizer = $vFreeBusy->ORGANIZER; $organizer = (string)$organizer; @@ -863,6 +935,9 @@ class Plugin extends ServerPlugin { $homeSet = $result[0][200][$caldavNS . 'calendar-home-set']->getHref(); $inboxUrl = $result[0][200][$caldavNS . 'schedule-inbox-URL']->getHref(); + // Do we have permission? + $aclPlugin->checkPrivileges($inboxUrl, $caldavNS . 'schedule-query-freebusy'); + // Grabbing the calendar list $objects = []; $calendarTimeZone = new DateTimeZone('UTC'); @@ -882,8 +957,6 @@ class Plugin extends ServerPlugin { continue; } - $aclPlugin->checkPrivileges($homeSet . $node->getName(), $caldavNS . 'read-free-busy'); - if (isset($props[$ctz])) { $vtimezoneObj = VObject\Reader::read($props[$ctz]); $calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone(); diff --git a/vendor/sabre/dav/lib/CalDAV/Schedule/SchedulingObject.php b/vendor/sabre/dav/lib/CalDAV/Schedule/SchedulingObject.php index a36646e6c..6d9d3d5ec 100644 --- a/vendor/sabre/dav/lib/CalDAV/Schedule/SchedulingObject.php +++ b/vendor/sabre/dav/lib/CalDAV/Schedule/SchedulingObject.php @@ -134,22 +134,12 @@ class SchedulingObject extends \Sabre\CalDAV\CalendarObject implements IScheduli // 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', + 'privilege' => '{DAV:}all', + 'principal' => '{DAV:}owner', 'protected' => true, ], [ - 'privilege' => '{DAV:}write', + 'privilege' => '{DAV:}all', 'principal' => $this->objectData['principaluri'] . '/calendar-proxy-write', 'protected' => true, ], diff --git a/vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php b/vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php index c11695d5f..c81c96300 100644 --- a/vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php +++ b/vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php @@ -6,7 +6,7 @@ namespace Sabre\CalDAV; * This object represents a CalDAV calendar that can be shared with other * users. * - * @copyright Copyright (C) fruux GmbH (https://fruux.com/) + * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ diff --git a/vendor/sabre/dav/lib/CalDAV/SharedCalendar.php b/vendor/sabre/dav/lib/CalDAV/SharedCalendar.php index 7973eff9c..7a77616e3 100644 --- a/vendor/sabre/dav/lib/CalDAV/SharedCalendar.php +++ b/vendor/sabre/dav/lib/CalDAV/SharedCalendar.php @@ -2,6 +2,8 @@ namespace Sabre\CalDAV; +use Sabre\DAV\Sharing\Plugin as SPlugin; + /** * This object represents a CalDAV calendar that is shared by a different user. * @@ -12,50 +14,84 @@ namespace Sabre\CalDAV; class SharedCalendar extends Calendar implements ISharedCalendar { /** - * Constructor + * Returns the 'access level' for the instance of this shared resource. + * + * The value should be one of the Sabre\DAV\Sharing\Plugin::ACCESS_ + * constants. * - * @param Backend\BackendInterface $caldavBackend - * @param array $calendarInfo + * @return int */ - function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo) { - - $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)'); - } - } + function getShareAccess() { - parent::__construct($caldavBackend, $calendarInfo); + return isset($this->calendarInfo['share-access']) ? $this->calendarInfo['share-access'] : SPlugin::ACCESS_NOTSHARED; } /** - * This method should return the url of the owners' copy of the shared - * calendar. + * This function must return a URI that uniquely identifies the shared + * resource. This URI should be identical across instances, and is + * also used in several other XML bodies to connect invites to + * resources. + * + * This may simply be a relative reference to the original shared instance, + * but it could also be a urn. As long as it's a valid URI and unique. * * @return string */ - function getSharedUrl() { + function getShareResourceUri() { + + return $this->calendarInfo['share-resource-uri']; + + } + + /** + * Updates the list of sharees. + * + * Every item must be a Sharee object. + * + * @param \Sabre\DAV\Xml\Element\Sharee[] $sharees + * @return void + */ + function updateInvites(array $sharees) { - return $this->calendarInfo['{http://calendarserver.org/ns/}shared-url']; + $this->caldavBackend->updateInvites($this->calendarInfo['id'], $sharees); } /** - * Returns the owner principal + * Returns the list of people whom this resource is shared with. + * + * Every item in the returned array must be a Sharee object with + * at least the following properties set: + * + * * $href + * * $shareAccess + * * $inviteStatus * - * This must be a url to a principal, or null if there's no owner + * and optionally: * - * @return string|null + * * $properties + * + * @return \Sabre\DAV\Xml\Element\Sharee[] */ - function getOwner() { + function getInvites() { - return $this->calendarInfo['{http://sabredav.org/ns}owner-principal']; + return $this->caldavBackend->getInvites($this->calendarInfo['id']); + + } + + /** + * Marks this calendar as published. + * + * Publishing a calendar should automatically create a read-only, public, + * subscribable calendar. + * + * @param bool $value + * @return void + */ + function setPublishStatus($value) { + + $this->caldavBackend->setPublishStatus($this->calendarInfo['id'], $value); } @@ -73,32 +109,72 @@ class SharedCalendar extends Calendar implements ISharedCalendar { */ 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[] = [ - 'privilege' => '{DAV:}read', - 'principal' => $this->calendarInfo['principaluri'], - 'protected' => true, - ]; - 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, - ]; + $acl = []; + + switch ($this->getShareAccess()) { + case SPlugin::ACCESS_NOTSHARED : + case SPlugin::ACCESS_SHAREDOWNER : + $acl[] = [ + 'privilege' => '{DAV:}share', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}share', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ]; + // No break intentional! + case SPlugin::ACCESS_READWRITE : + $acl[] = [ + 'privilege' => '{DAV:}write', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}write', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ]; + // No break intentional! + case SPlugin::ACCESS_READ : + $acl[] = [ + 'privilege' => '{DAV:}write-properties', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}write-properties', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read', + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy', + 'principal' => '{DAV:}authenticated', + 'protected' => true, + ]; + break; } return $acl; } + /** * This method returns the ACL's for calendar objects in this calendar. * The result of this method automatically gets passed to the @@ -108,40 +184,45 @@ class SharedCalendar extends Calendar implements ISharedCalendar { */ 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, - ]; + $acl = []; + + switch ($this->getShareAccess()) { + case SPlugin::ACCESS_NOTSHARED : + // No break intentional + case SPlugin::ACCESS_SHAREDOWNER : + // No break intentional + case SPlugin::ACCESS_READWRITE: + $acl[] = [ + 'privilege' => '{DAV:}write', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}write', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ]; + // No break intentional + case SPlugin::ACCESS_READ: + $acl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ]; + $acl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read', + 'protected' => true, + ]; + break; } - return $acl; - - } - - /** - * Returns the list of people whom this calendar is shared with. - * - * Every element in this array should have the following properties: - * * href - Often a mailto: address - * * commonName - Optional, for example a first + last name - * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. - * * readOnly - boolean - * * summary - Optional, a description for the share - * - * @return array - */ - function getShares() { - - return $this->caldavBackend->getShares($this->calendarInfo['id']); + return $acl; } diff --git a/vendor/sabre/dav/lib/CalDAV/SharingPlugin.php b/vendor/sabre/dav/lib/CalDAV/SharingPlugin.php index 5154fb1de..6f7df02bc 100644 --- a/vendor/sabre/dav/lib/CalDAV/SharingPlugin.php +++ b/vendor/sabre/dav/lib/CalDAV/SharingPlugin.php @@ -4,6 +4,7 @@ namespace Sabre\CalDAV; use Sabre\DAV; use Sabre\DAV\Xml\Property\Href; +use Sabre\DAV\Xml\Property\LocalHref; use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; @@ -25,15 +26,6 @@ use Sabre\HTTP\ResponseInterface; */ 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. * @@ -83,7 +75,10 @@ class SharingPlugin extends DAV\ServerPlugin { function initialize(DAV\Server $server) { $this->server = $server; - $server->resourceTypeMapping['Sabre\\CalDAV\\ISharedCalendar'] = '{' . Plugin::NS_CALENDARSERVER . '}shared'; + + if (is_null($this->server->getPlugin('sharing'))) { + throw new \LogicException('The generic "sharing" plugin must be loaded before the caldav sharing plugin. Call $server->addPlugin(new \Sabre\DAV\Sharing\Plugin()); before this one.'); + } array_push( $this->server->protectedProperties, @@ -114,24 +109,8 @@ class SharingPlugin extends DAV\ServerPlugin { */ 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 @@ -158,7 +137,7 @@ class SharingPlugin extends DAV\ServerPlugin { } return new Xml\Property\Invite( - $node->getShares(), + $node->getInvites(), $ownerInfo ); @@ -179,10 +158,18 @@ class SharingPlugin extends DAV\ServerPlugin { */ function propFindLate(DAV\PropFind $propFind, DAV\INode $node) { - if ($node instanceof IShareableCalendar) { + if ($node instanceof ISharedCalendar) { + $shareAccess = $node->getShareAccess(); if ($rt = $propFind->get('{DAV:}resourcetype')) { - if (count($node->getShares()) > 0) { - $rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner'); + switch ($shareAccess) { + case \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER : + $rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner'); + break; + case \Sabre\DAV\Sharing\Plugin::ACCESS_READ : + case \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE : + $rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared'); + break; + } } $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', function() { @@ -211,21 +198,24 @@ class SharingPlugin extends DAV\ServerPlugin { function propPatch($path, DAV\PropPatch $propPatch) { $node = $this->server->tree->getNodeForPath($path); - if (!$node instanceof IShareableCalendar) + if (!$node instanceof ISharedCalendar) 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); + if ($node->getShareAccess() === \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER || $node->getShareAccess() === \Sabre\DAV\Sharing\Plugin::ACCESS_NOTSHARED) { - return true; + $propPatch->handle('{DAV:}resourcetype', function($value) use ($node) { + if ($value->is('{' . Plugin::NS_CALENDARSERVER . '}shared-owner')) return false; + $shares = $node->getInvites(); + foreach ($shares as $share) { + $share->access = DAV\Sharing\Plugin::ACCESS_NOACCESS; + } + $node->updateInvites($shares); - }); + return true; + + }); + + } } @@ -267,26 +257,12 @@ class SharingPlugin extends DAV\ServerPlugin { switch ($documentType) { - // Dealing with the 'share' document, which modified invitees on a - // calendar. + // Both the DAV:share-resource and CALENDARSERVER:share requests + // behave identically. 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); + $sharingPlugin = $this->server->getPlugin('sharing'); + $sharingPlugin->shareResource($path, $message->sharees); $response->setStatus(200); // Adding this because sending a response body may cause issues, @@ -328,11 +304,11 @@ class SharingPlugin extends DAV\ServerPlugin { $response->setHeader('X-Sabre-Status', 'everything-went-well'); if ($url) { - $writer = $this->server->xml->getWriter($this->server->getBaseUri()); + $writer = $this->server->xml->getWriter(); $writer->openMemory(); $writer->startDocument(); $writer->startElement('{' . Plugin::NS_CALENDARSERVER . '}shared-as'); - $writer->write(new Href($url)); + $writer->write(new LocalHref($url)); $writer->endElement(); $response->setHeader('Content-Type', 'application/xml'); $response->setBody($writer->outputMemory()); @@ -345,7 +321,7 @@ class SharingPlugin extends DAV\ServerPlugin { case '{' . Plugin::NS_CALENDARSERVER . '}publish-calendar' : // We can only deal with IShareableCalendar objects - if (!$node instanceof IShareableCalendar) { + if (!$node instanceof ISharedCalendar) { return; } $this->server->transactionType = 'post-publish-calendar'; @@ -355,7 +331,7 @@ class SharingPlugin extends DAV\ServerPlugin { // If there's no ACL support, we allow everything if ($acl) { - $acl->checkPrivileges($path, '{DAV:}write'); + $acl->checkPrivileges($path, '{DAV:}share'); } $node->setPublishStatus(true); @@ -373,7 +349,7 @@ class SharingPlugin extends DAV\ServerPlugin { case '{' . Plugin::NS_CALENDARSERVER . '}unpublish-calendar' : // We can only deal with IShareableCalendar objects - if (!$node instanceof IShareableCalendar) { + if (!$node instanceof ISharedCalendar) { return; } $this->server->transactionType = 'post-unpublish-calendar'; @@ -383,7 +359,7 @@ class SharingPlugin extends DAV\ServerPlugin { // If there's no ACL support, we allow everything if ($acl) { - $acl->checkPrivileges($path, '{DAV:}write'); + $acl->checkPrivileges($path, '{DAV:}share'); } $node->setPublishStatus(false); diff --git a/vendor/sabre/dav/lib/CalDAV/Subscriptions/Subscription.php b/vendor/sabre/dav/lib/CalDAV/Subscriptions/Subscription.php index ee53da2c6..3bb3451f3 100644 --- a/vendor/sabre/dav/lib/CalDAV/Subscriptions/Subscription.php +++ b/vendor/sabre/dav/lib/CalDAV/Subscriptions/Subscription.php @@ -5,8 +5,8 @@ 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\DAVACL\ACLTrait; use Sabre\CalDAV\Backend\SubscriptionSupport; /** @@ -20,6 +20,8 @@ use Sabre\CalDAV\Backend\SubscriptionSupport; */ class Subscription extends Collection implements ISubscription, IACL { + use ACLTrait; + /** * caldavBackend * @@ -144,7 +146,7 @@ class Subscription extends Collection implements ISubscription, IACL { * The Server class will filter out the extra. * * @param array $properties - * @return void + * @return array */ function getProperties($properties) { @@ -154,7 +156,7 @@ class Subscription extends Collection implements ISubscription, IACL { switch ($prop) { case '{http://calendarserver.org/ns/}source' : - $r[$prop] = new Href($this->subscriptionInfo['source'], false); + $r[$prop] = new Href($this->subscriptionInfo['source']); break; default : if (array_key_exists($prop, $this->subscriptionInfo)) { @@ -182,19 +184,6 @@ class Subscription extends Collection implements ISubscription, IACL { } - /** - * 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. * @@ -211,22 +200,12 @@ class Subscription extends Collection implements ISubscription, IACL { return [ [ - 'privilege' => '{DAV:}read', - 'principal' => $this->getOwner(), - 'protected' => true, - ], - [ - 'privilege' => '{DAV:}write', + 'privilege' => '{DAV:}all', 'principal' => $this->getOwner(), 'protected' => true, ], [ - 'privilege' => '{DAV:}read', - 'principal' => $this->getOwner() . '/calendar-proxy-write', - 'protected' => true, - ], - [ - 'privilege' => '{DAV:}write', + 'privilege' => '{DAV:}all', 'principal' => $this->getOwner() . '/calendar-proxy-write', 'protected' => true, ], @@ -239,36 +218,4 @@ class Subscription extends Collection implements ISubscription, IACL { } - /** - * 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; - - } - } diff --git a/vendor/sabre/dav/lib/CalDAV/Xml/Notification/Invite.php b/vendor/sabre/dav/lib/CalDAV/Xml/Notification/Invite.php index 7fb022e33..1ca64f3e8 100644 --- a/vendor/sabre/dav/lib/CalDAV/Xml/Notification/Invite.php +++ b/vendor/sabre/dav/lib/CalDAV/Xml/Notification/Invite.php @@ -5,6 +5,7 @@ namespace Sabre\CalDAV\Xml\Notification; use Sabre\Xml\Writer; use Sabre\CalDAV\SharingPlugin as SharingPlugin; use Sabre\CalDAV; +use Sabre\DAV; /** * This class represents the cs:invite-notification notification element. @@ -210,16 +211,10 @@ class Invite implements NotificationInterface { switch ($this->type) { - case SharingPlugin::STATUS_ACCEPTED : + case DAV\Sharing\Plugin::INVITE_ACCEPTED : $writer->writeElement($cs . 'invite-accepted'); break; - case SharingPlugin::STATUS_DECLINED : - $writer->writeElement($cs . 'invite-declined'); - break; - case SharingPlugin::STATUS_DELETED : - $writer->writeElement($cs . 'invite-deleted'); - break; - case SharingPlugin::STATUS_NORESPONSE : + case DAV\Sharing\Plugin::INVITE_NORESPONSE : $writer->writeElement($cs . 'invite-noresponse'); break; diff --git a/vendor/sabre/dav/lib/CalDAV/Xml/Notification/InviteReply.php b/vendor/sabre/dav/lib/CalDAV/Xml/Notification/InviteReply.php index 945323fed..51bfc178a 100644 --- a/vendor/sabre/dav/lib/CalDAV/Xml/Notification/InviteReply.php +++ b/vendor/sabre/dav/lib/CalDAV/Xml/Notification/InviteReply.php @@ -5,6 +5,7 @@ namespace Sabre\CalDAV\Xml\Notification; use Sabre\Xml\Writer; use Sabre\CalDAV; use Sabre\CalDAV\SharingPlugin; +use Sabre\DAV; /** * This class represents the cs:invite-reply notification element. @@ -162,10 +163,10 @@ class InviteReply implements NotificationInterface { switch ($this->type) { - case SharingPlugin::STATUS_ACCEPTED : + case DAV\Sharing\Plugin::INVITE_ACCEPTED : $writer->writeElement($cs . 'invite-accepted'); break; - case SharingPlugin::STATUS_DECLINED : + case DAV\Sharing\Plugin::INVITE_DECLINED : $writer->writeElement($cs . 'invite-declined'); break; diff --git a/vendor/sabre/dav/lib/CalDAV/Xml/Property/Invite.php b/vendor/sabre/dav/lib/CalDAV/Xml/Property/Invite.php index 3ee053214..40ff6b936 100644 --- a/vendor/sabre/dav/lib/CalDAV/Xml/Property/Invite.php +++ b/vendor/sabre/dav/lib/CalDAV/Xml/Property/Invite.php @@ -2,11 +2,10 @@ namespace Sabre\CalDAV\Xml\Property; -use Sabre\Xml\Element; -use Sabre\Xml\Reader; +use Sabre\Xml\XmlSerializable; use Sabre\Xml\Writer; use Sabre\CalDAV\Plugin; -use Sabre\CalDAV\SharingPlugin; +use Sabre\DAV; /** * Invite property @@ -20,53 +19,23 @@ use Sabre\CalDAV\SharingPlugin; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Invite implements Element { +class Invite implements XmlSerializable { /** * The list of users a calendar has been shared to. * - * @var array + * @var Sharee[] */ - protected $users; - - /** - * The organizer contains information about the person who shared the - * object. - * - * @var array - */ - protected $organizer; + protected $sharees; /** * Creates the property. * - * Users is an array. Each element of the array has the following - * properties: - * - * * href - Often a mailto: address - * * commonName - Optional, for example a first and lastname for a user. - * * status - One of the SharingPlugin::STATUS_* constants. - * * readOnly - true or false - * * summary - Optional, description of the share - * - * The organizer key is optional to specify. It's only useful when a - * 'sharee' requests the sharing information. - * - * The organizer may have the following properties: - * * href - Often a mailto: address. - * * commonName - Optional human-readable name. - * * firstName - Optional first name. - * * lastName - Optional last name. - * - * If you wonder why these two structures are so different, I guess a - * valid answer is that the current spec is still a draft. - * - * @param array $users + * @param Sharee[] $sharees */ - function __construct(array $users, array $organizer = null) { + function __construct(array $sharees) { - $this->users = $users; - $this->organizer = $organizer; + $this->sharees = $sharees; } @@ -77,7 +46,7 @@ class Invite implements Element { */ function getValue() { - return $this->users; + return $this->sharees; } @@ -104,149 +73,55 @@ class Invite implements Element { $cs = '{' . Plugin::NS_CALENDARSERVER . '}'; - if (!is_null($this->organizer)) { - - $writer->startElement($cs . 'organizer'); - $writer->writeElement('{DAV:}href', $this->organizer['href']); - - if (isset($this->organizer['commonName']) && $this->organizer['commonName']) { - $writer->writeElement($cs . 'common-name', $this->organizer['commonName']); - } - if (isset($this->organizer['firstName']) && $this->organizer['firstName']) { - $writer->writeElement($cs . 'first-name', $this->organizer['firstName']); - } - if (isset($this->organizer['lastName']) && $this->organizer['lastName']) { - $writer->writeElement($cs . 'last-name', $this->organizer['lastName']); - } - $writer->endElement(); // organizer + foreach ($this->sharees as $sharee) { - } - - foreach ($this->users as $user) { - - $writer->startElement($cs . 'user'); - $writer->writeElement('{DAV:}href', $user['href']); - if (isset($user['commonName']) && $user['commonName']) { - $writer->writeElement($cs . 'common-name', $user['commonName']); - } - switch ($user['status']) { - - case SharingPlugin::STATUS_ACCEPTED : - $writer->writeElement($cs . 'invite-accepted'); - break; - case SharingPlugin::STATUS_DECLINED : - $writer->writeElement($cs . 'invite-declined'); - break; - case SharingPlugin::STATUS_NORESPONSE : - $writer->writeElement($cs . 'invite-noresponse'); - break; - case SharingPlugin::STATUS_INVALID : - $writer->writeElement($cs . 'invite-invalid'); - break; - } - - $writer->startElement($cs . 'access'); - if ($user['readOnly']) { - $writer->writeElement($cs . 'read'); + if ($sharee->access === \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER) { + $writer->startElement($cs . 'organizer'); } else { - $writer->writeElement($cs . 'read-write'); - } - $writer->endElement(); // access - - if (isset($user['summary']) && $user['summary']) { - $writer->writeElement($cs . 'summary', $user['summary']); - } - - $writer->endElement(); //user - - } - - } - - /** - * 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) { - - $cs = '{' . Plugin::NS_CALENDARSERVER . '}'; - - $users = []; - - foreach ($reader->parseInnerTree() as $elem) { + $writer->startElement($cs . 'user'); - if ($elem['name'] !== $cs . 'user') - continue; - - $user = [ - 'href' => null, - 'commonName' => null, - 'readOnly' => null, - 'summary' => null, - 'status' => null, - ]; - - foreach ($elem['value'] as $userElem) { - - switch ($userElem['name']) { - case $cs . 'invite-accepted' : - $user['status'] = SharingPlugin::STATUS_ACCEPTED; - break; - case $cs . 'invite-declined' : - $user['status'] = SharingPlugin::STATUS_DECLINED; + switch ($sharee->inviteStatus) { + case DAV\Sharing\Plugin::INVITE_ACCEPTED : + $writer->writeElement($cs . 'invite-accepted'); break; - case $cs . 'invite-noresponse' : - $user['status'] = SharingPlugin::STATUS_NORESPONSE; + case DAV\Sharing\Plugin::INVITE_DECLINED : + $writer->writeElement($cs . 'invite-declined'); break; - case $cs . 'invite-invalid' : - $user['status'] = SharingPlugin::STATUS_INVALID; + case DAV\Sharing\Plugin::INVITE_NORESPONSE : + $writer->writeElement($cs . 'invite-noresponse'); break; - case '{DAV:}href' : - $user['href'] = $userElem['value']; + case DAV\Sharing\Plugin::INVITE_INVALID : + $writer->writeElement($cs . 'invite-invalid'); break; - case $cs . 'common-name' : - $user['commonName'] = $userElem['value']; - break; - case $cs . 'access' : - foreach ($userElem['value'] as $accessHref) { - if ($accessHref['name'] === $cs . 'read') { - $user['readOnly'] = true; - } - } + } + + $writer->startElement($cs . 'access'); + switch ($sharee->access) { + case DAV\Sharing\Plugin::ACCESS_READWRITE : + $writer->writeElement($cs . 'read-write'); break; - case $cs . 'summary' : - $user['summary'] = $userElem['value']; + case DAV\Sharing\Plugin::ACCESS_READ : + $writer->writeElement($cs . 'read'); break; } + $writer->endElement(); // access } - if (!$user['status']) { - throw new \InvalidArgumentException('Every user must have one of cs:invite-accepted, cs:invite-declined, cs:invite-noresponse or cs:invite-invalid'); - } - $users[] = $user; + $href = new \Sabre\DAV\Xml\Property\Href($sharee->href); + $href->xmlSerialize($writer); - } + if (isset($sharee->properties['{DAV:}displayname'])) { + $writer->writeElement($cs . 'common-name', $sharee->properties['{DAV:}displayname']); + } + if ($sharee->comment) { + $writer->writeElement($cs . 'summary', $sharee->comment); + } + $writer->endElement(); // organizer or user - return new self($users); + } } + } diff --git a/vendor/sabre/dav/lib/CalDAV/Xml/Request/InviteReply.php b/vendor/sabre/dav/lib/CalDAV/Xml/Request/InviteReply.php index ec627156f..2ecf6c2bb 100644 --- a/vendor/sabre/dav/lib/CalDAV/Xml/Request/InviteReply.php +++ b/vendor/sabre/dav/lib/CalDAV/Xml/Request/InviteReply.php @@ -2,12 +2,13 @@ namespace Sabre\CalDAV\Xml\Request; +use Sabre\CalDAV\Plugin; +use Sabre\CalDAV\SharingPlugin; +use Sabre\DAV; +use Sabre\DAV\Exception\BadRequest; use Sabre\Xml\Reader; use Sabre\Xml\XmlDeserializable; use Sabre\Xml\Element\KeyValue; -use Sabre\DAV\Exception\BadRequest; -use Sabre\CalDAV\Plugin; -use Sabre\CalDAV\SharingPlugin; /** * Invite-reply POST request parser @@ -121,10 +122,10 @@ class InviteReply implements XmlDeserializable { } break; case '{' . Plugin::NS_CALENDARSERVER . '}invite-accepted' : - $status = SharingPlugin::STATUS_ACCEPTED; + $status = DAV\Sharing\Plugin::INVITE_ACCEPTED; break; case '{' . Plugin::NS_CALENDARSERVER . '}invite-declined' : - $status = SharingPlugin::STATUS_DECLINED; + $status = DAV\Sharing\Plugin::INVITE_DECLINED; break; case '{' . Plugin::NS_CALENDARSERVER . '}in-reply-to' : $inReplyTo = $value; diff --git a/vendor/sabre/dav/lib/CalDAV/Xml/Request/Share.php b/vendor/sabre/dav/lib/CalDAV/Xml/Request/Share.php index dacc5dc94..b5d9a133c 100644 --- a/vendor/sabre/dav/lib/CalDAV/Xml/Request/Share.php +++ b/vendor/sabre/dav/lib/CalDAV/Xml/Request/Share.php @@ -2,9 +2,10 @@ namespace Sabre\CalDAV\Xml\Request; +use Sabre\CalDAV\Plugin; +use Sabre\DAV\Xml\Element\Sharee; use Sabre\Xml\Reader; use Sabre\Xml\XmlDeserializable; -use Sabre\CalDAV\Plugin; /** * Share POST request parser @@ -20,37 +21,20 @@ use Sabre\CalDAV\Plugin; class Share implements XmlDeserializable { /** - * The list of new people added or updated. - * - * Every element has the following keys: - * 1. href - An email address - * 2. commonName - Some name - * 3. summary - An optional description of the share - * 4. readOnly - true or false - * - * @var array - */ - public $set = []; - - /** - * List of people removed from the share list. - * - * The list is a flat list of email addresses (including mailto:). + * The list of new people added or updated or removed from the share. * - * @var array + * @var Sharee[] */ - public $remove = []; + public $sharees = []; /** * Constructor * - * @param array $set - * @param array $remove + * @param Sharee[] $sharees */ - function __construct(array $set, array $remove) { + function __construct(array $sharees) { - $this->set = $set; - $this->remove = $remove; + $this->sharees = $sharees; } @@ -77,13 +61,12 @@ class Share implements XmlDeserializable { */ static function xmlDeserialize(Reader $reader) { - $elems = $reader->parseInnerTree([ + $elems = $reader->parseGetElements([ '{' . Plugin::NS_CALENDARSERVER . '}set' => 'Sabre\\Xml\\Element\\KeyValue', '{' . Plugin::NS_CALENDARSERVER . '}remove' => 'Sabre\\Xml\\Element\\KeyValue', ]); - $set = []; - $remove = []; + $sharees = []; foreach ($elems as $elem) { switch ($elem['name']) { @@ -94,22 +77,34 @@ class Share implements XmlDeserializable { $sumElem = '{' . Plugin::NS_CALENDARSERVER . '}summary'; $commonName = '{' . Plugin::NS_CALENDARSERVER . '}common-name'; - $set[] = [ + $properties = []; + if (isset($sharee[$commonName])) { + $properties['{DAV:}displayname'] = $sharee[$commonName]; + } + + $access = array_key_exists('{' . Plugin::NS_CALENDARSERVER . '}read-write', $sharee) + ? \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE + : \Sabre\DAV\Sharing\Plugin::ACCESS_READ; + + $sharees[] = new Sharee([ 'href' => $sharee['{DAV:}href'], - 'commonName' => isset($sharee[$commonName]) ? $sharee[$commonName] : null, - 'summary' => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null, - 'readOnly' => !array_key_exists('{' . Plugin::NS_CALENDARSERVER . '}read-write', $sharee), - ]; + 'properties' => $properties, + 'access' => $access, + 'comment' => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null + ]); break; case '{' . Plugin::NS_CALENDARSERVER . '}remove' : - $remove[] = $elem['value']['{DAV:}href']; + $sharees[] = new Sharee([ + 'href' => $elem['value']['{DAV:}href'], + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS + ]); break; } } - return new self($set, $remove); + return new self($sharees); } diff --git a/vendor/sabre/dav/lib/CardDAV/AddressBook.php b/vendor/sabre/dav/lib/CardDAV/AddressBook.php index 70bec8760..6dd098618 100644 --- a/vendor/sabre/dav/lib/CardDAV/AddressBook.php +++ b/vendor/sabre/dav/lib/CardDAV/AddressBook.php @@ -16,6 +16,8 @@ use Sabre\DAVACL; */ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IProperties, DAVACL\IACL, DAV\Sync\ISyncCollection, DAV\IMultiGet { + use DAVACL\ACLTrait; + /** * This is an array with addressbook information * @@ -236,48 +238,6 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie } - /** - * 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, - ], - - ]; - - } /** * This method returns the ACL's for card nodes in this address book. @@ -290,12 +250,7 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie return [ [ - 'privilege' => '{DAV:}read', - 'principal' => $this->getOwner(), - 'protected' => true, - ], - [ - 'privilege' => '{DAV:}write', + 'privilege' => '{DAV:}all', 'principal' => $this->getOwner(), 'protected' => true, ], @@ -303,37 +258,6 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie } - /** - * 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() { - - return null; - - } /** * This method returns the current sync-token for this collection. diff --git a/vendor/sabre/dav/lib/CardDAV/AddressBookHome.php b/vendor/sabre/dav/lib/CardDAV/AddressBookHome.php index ebc251832..888a44a40 100644 --- a/vendor/sabre/dav/lib/CardDAV/AddressBookHome.php +++ b/vendor/sabre/dav/lib/CardDAV/AddressBookHome.php @@ -18,6 +18,8 @@ use Sabre\Uri; */ class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection, DAVACL\IACL { + use DAVACL\ACLTrait; + /** * Principal uri * @@ -186,78 +188,4 @@ class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection, } - /** - * 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->principalUri, - 'protected' => true, - ], - [ - 'privilege' => '{DAV:}write', - 'principal' => $this->principalUri, - '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('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; - - } - } diff --git a/vendor/sabre/dav/lib/CardDAV/Backend/BackendInterface.php b/vendor/sabre/dav/lib/CardDAV/Backend/BackendInterface.php index b9691b906..54e42b899 100644 --- a/vendor/sabre/dav/lib/CardDAV/Backend/BackendInterface.php +++ b/vendor/sabre/dav/lib/CardDAV/Backend/BackendInterface.php @@ -55,12 +55,15 @@ interface BackendInterface { function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch); /** - * Creates a new address book + * Creates a new address book. + * + * This method should return the id of the new address book. The id can be + * in any format, including ints, strings, arrays or objects. * * @param string $principalUri * @param string $url Just the 'basename' of the url. * @param array $properties - * @return void + * @return mixed */ function createAddressBook($principalUri, $url, array $properties); diff --git a/vendor/sabre/dav/lib/CardDAV/Backend/PDO.php b/vendor/sabre/dav/lib/CardDAV/Backend/PDO.php index 5509ddc02..7c3feff93 100644 --- a/vendor/sabre/dav/lib/CardDAV/Backend/PDO.php +++ b/vendor/sabre/dav/lib/CardDAV/Backend/PDO.php @@ -128,7 +128,7 @@ class PDO extends AbstractBackend implements SyncSupport { } else { $query .= ', '; } - $query .= ' `' . $key . '` = :' . $key . ' '; + $query .= ' ' . $key . ' = :' . $key . ' '; } $query .= ' WHERE id = :addressbookid'; @@ -180,7 +180,9 @@ class PDO extends AbstractBackend implements SyncSupport { $query = 'INSERT INTO ' . $this->addressBooksTableName . ' (uri, displayname, description, principaluri, synctoken) VALUES (:uri, :displayname, :description, :principaluri, 1)'; $stmt = $this->pdo->prepare($query); $stmt->execute($values); - return $this->pdo->lastInsertId(); + return $this->pdo->lastInsertId( + $this->addressBooksTableName . '_id_seq' + ); } @@ -230,6 +232,7 @@ class PDO extends AbstractBackend implements SyncSupport { $result = []; while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { $row['etag'] = '"' . $row['etag'] . '"'; + $row['lastmodified'] = (int)$row['lastmodified']; $result[] = $row; } return $result; @@ -258,6 +261,7 @@ class PDO extends AbstractBackend implements SyncSupport { if (!$result) return false; $result['etag'] = '"' . $result['etag'] . '"'; + $result['lastmodified'] = (int)$result['lastmodified']; return $result; } @@ -286,6 +290,7 @@ class PDO extends AbstractBackend implements SyncSupport { $result = []; while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { $row['etag'] = '"' . $row['etag'] . '"'; + $row['lastmodified'] = (int)$row['lastmodified']; $result[] = $row; } return $result; diff --git a/vendor/sabre/dav/lib/CardDAV/Card.php b/vendor/sabre/dav/lib/CardDAV/Card.php index 8da672502..0a040be6b 100644 --- a/vendor/sabre/dav/lib/CardDAV/Card.php +++ b/vendor/sabre/dav/lib/CardDAV/Card.php @@ -14,6 +14,8 @@ use Sabre\DAV; */ class Card extends DAV\File implements ICard, DAVACL\IACL { + use DAVACL\ACLTrait; + /** * CardDAV backend * @@ -181,18 +183,6 @@ class Card extends DAV\File implements ICard, DAVACL\IACL { } - /** - * 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. @@ -215,12 +205,7 @@ class Card extends DAV\File implements ICard, DAVACL\IACL { return [ [ - 'privilege' => '{DAV:}read', - 'principal' => $this->addressBookInfo['principaluri'], - 'protected' => true, - ], - [ - 'privilege' => '{DAV:}write', + 'privilege' => '{DAV:}all', 'principal' => $this->addressBookInfo['principaluri'], 'protected' => true, ], @@ -228,36 +213,4 @@ class Card extends DAV\File implements ICard, DAVACL\IACL { } - /** - * 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() { - - return null; - - } - } diff --git a/vendor/sabre/dav/lib/CardDAV/Plugin.php b/vendor/sabre/dav/lib/CardDAV/Plugin.php index b8bded098..0507df100 100644 --- a/vendor/sabre/dav/lib/CardDAV/Plugin.php +++ b/vendor/sabre/dav/lib/CardDAV/Plugin.php @@ -4,7 +4,7 @@ namespace Sabre\CardDAV; use Sabre\DAV; use Sabre\DAV\Exception\ReportNotSupported; -use Sabre\DAV\Xml\Property\Href; +use Sabre\DAV\Xml\Property\LocalHref; use Sabre\DAVACL; use Sabre\HTTP; use Sabre\HTTP\RequestInterface; @@ -156,11 +156,11 @@ class Plugin extends DAV\ServerPlugin { $path = $propFind->getPath(); $propFind->handle('{' . self::NS_CARDDAV . '}addressbook-home-set', function() use ($path) { - return new Href($this->getAddressBookHomeForPrincipal($path) . '/'); + return new LocalHref($this->getAddressBookHomeForPrincipal($path) . '/'); }); if ($this->directories) $propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function() { - return new Href($this->directories); + return new LocalHref($this->directories); }); } @@ -334,12 +334,7 @@ class Plugin extends DAV\ServerPlugin { $data = stream_get_contents($data); } - $before = md5($data); - - // Converting the data to unicode, if needed. - $data = DAV\StringUtil::ensureUTF8($data); - - if (md5($data) !== $before) $modified = true; + $before = $data; try { @@ -366,11 +361,56 @@ class Plugin extends DAV\ServerPlugin { throw new DAV\Exception\UnsupportedMediaType('This collection can only support vcard objects.'); } - if (!isset($vobj->UID)) { - // No UID in vcards is invalid, but we'll just add it in anyway. - $vobj->add('UID', DAV\UUIDUtil::getUUID()); + $options = VObject\Node::PROFILE_CARDDAV; + $prefer = $this->server->getHTTPPrefer(); + + if ($prefer['handling'] !== 'strict') { + $options |= VObject\Node::REPAIR; + } + + $messages = $vobj->validate($options); + + $highestLevel = 0; + $warningMessage = null; + + // $messages contains a list of problems with the vcard, along with + // their severity. + foreach ($messages as $message) { + + if ($message['level'] > $highestLevel) { + // Recording the highest reported error level. + $highestLevel = $message['level']; + $warningMessage = $message['message']; + } + + switch ($message['level']) { + + case 1 : + // Level 1 means that there was a problem, but it was repaired. + $modified = true; + break; + case 2 : + // Level 2 means a warning, but not critical + break; + case 3 : + // Level 3 means a critical error + throw new DAV\Exception\UnsupportedMediaType('Validation error in vCard: ' . $message['message']); + + } + + } + if ($warningMessage) { + $this->server->httpResponse->setHeader( + 'X-Sabre-Ew-Gross', + 'vCard validation warning: ' . $warningMessage + ); + + // Re-serializing object. $data = $vobj->serialize(); - $modified = true; + if (!$modified && strcmp($data, $before) !== 0) { + // This ensures that the system does not send an ETag back. + $modified = true; + } } // Destroy circular references to PHP will GC the object. @@ -803,33 +843,49 @@ class Plugin extends DAV\ServerPlugin { /** * Converts a vcard blob to a different version, or jcard. * - * @param string $data + * @param string|resource $data * @param string $target * @return string */ protected function convertVCard($data, $target) { - $data = VObject\Reader::read($data); - switch ($target) { - default : - case 'vcard3' : - $data = $data->convert(VObject\Document::VCARD30); - $newResult = $data->serialize(); - break; - case 'vcard4' : - $data = $data->convert(VObject\Document::VCARD40); - $newResult = $data->serialize(); - break; - case 'jcard' : - $data = $data->convert(VObject\Document::VCARD40); - $newResult = json_encode($data->jsonSerialize()); - break; - + if (is_resource($data)) { + $data = stream_get_contents($data); } - // Destroy circular references to PHP will GC the object. - $data->destroy(); + $input = VObject\Reader::read($data); + $output = null; + try { - return $newResult; + switch ($target) { + default : + case 'vcard3' : + if ($input->getDocumentType() === VObject\Document::VCARD30) { + // Do nothing + return $data; + } + $output = $input->convert(VObject\Document::VCARD30); + return $output->serialize(); + case 'vcard4' : + if ($input->getDocumentType() === VObject\Document::VCARD40) { + // Do nothing + return $data; + } + $output = $input->convert(VObject\Document::VCARD40); + return $output->serialize(); + case 'jcard' : + $output = $input->convert(VObject\Document::VCARD40); + return json_encode($output); + + } + + } finally { + + // Destroy circular references to PHP will GC the object. + $input->destroy(); + if (!is_null($output)) { + $output->destroy(); + } + } } diff --git a/vendor/sabre/dav/lib/CardDAV/VCFExportPlugin.php b/vendor/sabre/dav/lib/CardDAV/VCFExportPlugin.php index de8b3bb84..d015589ad 100644 --- a/vendor/sabre/dav/lib/CardDAV/VCFExportPlugin.php +++ b/vendor/sabre/dav/lib/CardDAV/VCFExportPlugin.php @@ -70,14 +70,34 @@ class VCFExportPlugin extends DAV\ServerPlugin { $aclPlugin->checkPrivileges($path, '{DAV:}read'); } - $response->setHeader('Content-Type', 'text/directory'); - $response->setStatus(200); - $nodes = $this->server->getPropertiesForPath($path, [ '{' . Plugin::NS_CARDDAV . '}address-data', ], 1); - $response->setBody($this->generateVCF($nodes)); + $format = 'text/directory'; + + $output = null; + $filenameExtension = null; + + switch ($format) { + case 'text/directory': + $output = $this->generateVCF($nodes); + $filenameExtension = '.vcf'; + break; + } + + $filename = preg_replace( + '/[^a-zA-Z0-9-_ ]/um', + '', + $node->getName() + ); + $filename .= '-' . date('Y-m-d') . $filenameExtension; + + $response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"'); + $response->setHeader('Content-Type', $format); + + $response->setStatus(200); + $response->setBody($output); // Returning false to break the event chain return false; diff --git a/vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php b/vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php index 0251decc1..85c5f30d5 100644 --- a/vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php +++ b/vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php @@ -155,8 +155,14 @@ abstract class AbstractDigest implements BackendInterface { $response ); $auth->init(); + + $oldStatus = $response->getStatus() ?: 200; $auth->requireLogin(); + // Preventing the digest utility from modifying the http status code, + // this should be handled by the main plugin. + $response->setStatus($oldStatus); + } } diff --git a/vendor/sabre/dav/lib/DAV/Auth/Plugin.php b/vendor/sabre/dav/lib/DAV/Auth/Plugin.php index 818d8a4ad..4b5f35ac3 100644 --- a/vendor/sabre/dav/lib/DAV/Auth/Plugin.php +++ b/vendor/sabre/dav/lib/DAV/Auth/Plugin.php @@ -4,7 +4,6 @@ namespace Sabre\DAV\Auth; use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; -use Sabre\HTTP\URLUtil; use Sabre\DAV\Exception\NotAuthenticated; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; @@ -25,6 +24,20 @@ use Sabre\DAV\ServerPlugin; */ class Plugin extends ServerPlugin { + /** + * By default this plugin will require that the user is authenticated, + * and refuse any access if the user is not authenticated. + * + * If this setting is set to false, we let the user through, whether they + * are authenticated or not. + * + * This is useful if you want to allow both authenticated and + * unauthenticated access to your server. + * + * @param bool + */ + public $autoRequireLogin = true; + /** * authentication backends */ @@ -107,27 +120,6 @@ class Plugin extends ServerPlugin { } - /** - * Returns the current username. - * - * This method is deprecated and is only kept for backwards compatibility - * purposes. Please switch to getCurrentPrincipal(). - * - * @deprecated Will be removed in a future version! - * @return string|null - */ - function getCurrentUser() { - - // We just do a 'basename' on the principal to give back a sane value - // here. - list(, $userName) = URLUtil::splitPath( - $this->getCurrentPrincipal() - ); - - return $userName; - - } - /** * This method is called before any HTTP method and forces users to be authenticated * @@ -154,6 +146,50 @@ class Plugin extends ServerPlugin { return; } + + $authResult = $this->check($request, $response); + + if ($authResult[0]) { + // Auth was successful + $this->currentPrincipal = $authResult[1]; + $this->loginFailedReasons = null; + return; + } + + + + // If we got here, it means that no authentication backend was + // successful in authenticating the user. + $this->currentPrincipal = null; + $this->loginFailedReasons = $authResult[1]; + + if ($this->autoRequireLogin) { + $this->challenge($request, $response); + throw new NotAuthenticated(implode(', ', $authResult[1])); + } + + } + + /** + * Checks authentication credentials, and logs the user in if possible. + * + * This method returns an array. The first item in the array is a boolean + * indicating if login was successful. + * + * If login was successful, the second item in the array will contain the + * current principal url/path of the logged in user. + * + * If login was not successful, the second item in the array will contain a + * an array with strings. The strings are a list of reasons why login was + * unsuccesful. For every auth backend there will be one reason, so usually + * there's just one. + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return array + */ + function check(RequestInterface $request, ResponseInterface $response) { + if (!$this->backends) { throw new \Sabre\DAV\Exception('No authentication backends were configured on this server.'); } @@ -172,20 +208,56 @@ class Plugin extends ServerPlugin { if ($result[0]) { $this->currentPrincipal = $result[1]; // Exit early - return; + return [true, $result[1]]; } $reasons[] = $result[1]; } - // If we got here, it means that no authentication backend was - // successful in authenticating the user. - $this->currentPrincipal = null; + return [false, $reasons]; + + } + + /** + * This method sends authentication challenges to the user. + * + * This method will for example cause a HTTP Basic backend to set a + * WWW-Authorization header, indicating to the client that it should + * authenticate. + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return array + */ + function challenge(RequestInterface $request, ResponseInterface $response) { foreach ($this->backends as $backend) { $backend->challenge($request, $response); } - throw new NotAuthenticated(implode(', ', $reasons)); + + } + + /** + * List of reasons why login failed for the last login operation. + * + * @var string[]|null + */ + protected $loginFailedReasons; + + /** + * Returns a list of reasons why login was unsuccessful. + * + * This method will return the login failed reasons for the last login + * operation. One for each auth backend. + * + * This method returns null if the last authentication attempt was + * successful, or if there was no authentication attempt yet. + * + * @return string[]|null + */ + function getLoginFailedReasons() { + + return $this->loginFailedReasons; } diff --git a/vendor/sabre/dav/lib/DAV/Browser/Plugin.php b/vendor/sabre/dav/lib/DAV/Browser/Plugin.php index 07ca6c3e5..49359a045 100644 --- a/vendor/sabre/dav/lib/DAV/Browser/Plugin.php +++ b/vendor/sabre/dav/lib/DAV/Browser/Plugin.php @@ -48,7 +48,7 @@ class Plugin extends DAV\ServerPlugin { public $uninterestingProperties = [ '{DAV:}supportedlock', '{DAV:}acl-restrictions', - '{DAV:}supported-privilege-set', +// '{DAV:}supported-privilege-set', '{DAV:}supported-method-set', ]; @@ -112,7 +112,7 @@ class Plugin extends DAV\ServerPlugin { $getVars = $request->getQueryParameters(); // CSP headers - $this->server->httpResponse->setHeader('Content-Security-Policy', "img-src 'self'; style-src 'self';"); + $this->server->httpResponse->setHeader('Content-Security-Policy', "default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self';"); $sabreAction = isset($getVars['sabreAction']) ? $getVars['sabreAction'] : null; @@ -354,7 +354,7 @@ class Plugin extends DAV\ServerPlugin { $output = ''; if ($this->enablePost) { - $this->server->emit('onHTMLActionsPanel', [$node, &$output]); + $this->server->emit('onHTMLActionsPanel', [$node, &$output, $path]); } if ($output) { @@ -368,7 +368,7 @@ class Plugin extends DAV\ServerPlugin { $html .= $this->generateFooter(); - $this->server->httpResponse->setHeader('Content-Security-Policy', "img-src 'self'; style-src 'self';"); + $this->server->httpResponse->setHeader('Content-Security-Policy', "default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self';"); return $html; @@ -477,7 +477,7 @@ HTML; $version = DAV\Version::VERSION; return <<Generated by SabreDAV $version (c)2007-2015 http://sabre.io/ + HTML; @@ -493,9 +493,10 @@ HTML; * * @param DAV\INode $node * @param mixed $output + * @param string $path * @return void */ - function htmlActionsPanel(DAV\INode $node, &$output) { + function htmlActionsPanel(DAV\INode $node, &$output, $path) { if (!$node instanceof DAV\ICollection) return; diff --git a/vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css b/vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css index c9ab2c74f..8869597f0 100644 --- a/vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css +++ b/vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css @@ -96,12 +96,12 @@ header a { vertical-align: middle; border: 0; } -input, button { +input, button, select { font: inherit; color: inherit; } -input[type=text] { +input[type=text], select { border: 1px solid #bbbbbb; line-height: 22px; padding: 5px 10px; @@ -200,7 +200,7 @@ section table { line-height: 40px; } -.actions input[type=text] { +.actions input[type=text], select { width: 450px; } diff --git a/vendor/sabre/dav/lib/DAV/Client.php b/vendor/sabre/dav/lib/DAV/Client.php index d46b397b6..08d5d4702 100644 --- a/vendor/sabre/dav/lib/DAV/Client.php +++ b/vendor/sabre/dav/lib/DAV/Client.php @@ -3,6 +3,7 @@ namespace Sabre\DAV; use Sabre\HTTP; +use Sabre\Uri; /** * SabreDAV DAV client @@ -387,20 +388,10 @@ class Client extends HTTP\Client { */ function getAbsoluteUrl($url) { - // If the url starts with http:// or https://, the url is already absolute. - if (preg_match('/^http(s?):\/\//', $url)) { - return $url; - } - - // If the url starts with a slash, we must calculate the url based off - // the root of the base url. - if (strpos($url, '/') === 0) { - $parts = parse_url($this->baseUri); - return $parts['scheme'] . '://' . $parts['host'] . (isset($parts['port']) ? ':' . $parts['port'] : '') . $url; - } - - // Otherwise... - return $this->baseUri . $url; + return Uri\resolve( + $this->baseUri, + $url + ); } diff --git a/vendor/sabre/dav/lib/DAV/CorePlugin.php b/vendor/sabre/dav/lib/DAV/CorePlugin.php index 3a70b2a7e..a1b052915 100644 --- a/vendor/sabre/dav/lib/DAV/CorePlugin.php +++ b/vendor/sabre/dav/lib/DAV/CorePlugin.php @@ -50,6 +50,8 @@ class CorePlugin extends ServerPlugin { $server->on('propFind', [$this, 'propFindNode'], 120); $server->on('propFind', [$this, 'propFindLate'], 200); + $server->on('exception', [$this, 'exception']); + } /** @@ -844,10 +846,8 @@ class CorePlugin extends ServerPlugin { if ($node instanceof IProperties && $propertyNames = $propFind->get404Properties()) { $nodeProperties = $node->getProperties($propertyNames); - foreach ($propertyNames as $propertyName) { - if (array_key_exists($propertyName, $nodeProperties)) { - $propFind->set($propertyName, $nodeProperties[$propertyName], 200); - } + foreach ($nodeProperties as $propertyName => $propertyValue) { + $propFind->set($propertyName, $propertyValue, 200); } } @@ -904,6 +904,38 @@ class CorePlugin extends ServerPlugin { } + /** + * Listens for exception events, and automatically logs them. + * + * @param Exception $e + */ + function exception($e) { + + $logLevel = \Psr\Log\LogLevel::CRITICAL; + if ($e instanceof \Sabre\DAV\Exception) { + // If it's a standard sabre/dav exception, it means we have a http + // status code available. + $code = $e->getHTTPCode(); + + if ($code >= 400 && $code < 500) { + // user error + $logLevel = \Psr\Log\LogLevel::INFO; + } else { + // Server-side error. We mark it's as an error, but it's not + // critical. + $logLevel = \Psr\Log\LogLevel::ERROR; + } + } + + $this->server->getLogger()->log( + $logLevel, + 'Uncaught exception', + [ + 'exception' => $e, + ] + ); + } + /** * Returns a bunch of meta-data about the plugin. * diff --git a/vendor/sabre/dav/lib/DAV/FS/Directory.php b/vendor/sabre/dav/lib/DAV/FS/Directory.php index 963e5554c..362f7a411 100644 --- a/vendor/sabre/dav/lib/DAV/FS/Directory.php +++ b/vendor/sabre/dav/lib/DAV/FS/Directory.php @@ -140,10 +140,10 @@ class Directory extends Node implements DAV\ICollection, DAV\IQuota { * @return array */ function getQuotaInfo() { - + $absolute = realpath($this->path); return [ - disk_total_space($this->path) - disk_free_space($this->path), - disk_free_space($this->path) + disk_total_space($absolute) - disk_free_space($absolute), + disk_free_space($absolute) ]; } diff --git a/vendor/sabre/dav/lib/DAV/File.php b/vendor/sabre/dav/lib/DAV/File.php index e0a0391db..675956b22 100644 --- a/vendor/sabre/dav/lib/DAV/File.php +++ b/vendor/sabre/dav/lib/DAV/File.php @@ -15,12 +15,24 @@ namespace Sabre\DAV; abstract class File extends Node implements IFile { /** - * Updates the data + * Replaces the contents of the file. * - * data is a readable stream resource. + * The data argument is a readable stream resource. * - * @param resource $data - * @return void + * After a succesful put operation, you may choose to return an ETag. The + * etag must always be surrounded by double-quotes. These quotes must + * appear in the actual string you're returning. + * + * Clients may use the ETag from a PUT request to later on make sure that + * when they update the file, the contents haven't changed in the mean + * time. + * + * If you don't plan to store the file byte-by-byte, and you return a + * different object on a subsequent GET you are strongly recommended to not + * return an ETag, and just return null. + * + * @param string|resource $data + * @return string|null */ function put($data) { diff --git a/vendor/sabre/dav/lib/DAV/ICollection.php b/vendor/sabre/dav/lib/DAV/ICollection.php index 390d9b741..7793070d3 100644 --- a/vendor/sabre/dav/lib/DAV/ICollection.php +++ b/vendor/sabre/dav/lib/DAV/ICollection.php @@ -54,14 +54,14 @@ interface ICollection extends INode { * exist. * * @param string $name - * @return DAV\INode + * @return INode */ function getChild($name); /** * Returns an array with all the child nodes * - * @return DAV\INode[] + * @return INode[] */ function getChildren(); diff --git a/vendor/sabre/dav/lib/DAV/IFile.php b/vendor/sabre/dav/lib/DAV/IFile.php index e16a3a58a..37e7cd33c 100644 --- a/vendor/sabre/dav/lib/DAV/IFile.php +++ b/vendor/sabre/dav/lib/DAV/IFile.php @@ -32,7 +32,7 @@ interface IFile extends INode { * different object on a subsequent GET you are strongly recommended to not * return an ETag, and just return null. * - * @param resource $data + * @param resource|data $data * @return string|null */ function put($data); diff --git a/vendor/sabre/dav/lib/DAV/INode.php b/vendor/sabre/dav/lib/DAV/INode.php index b5e6cb9ef..bb884934d 100644 --- a/vendor/sabre/dav/lib/DAV/INode.php +++ b/vendor/sabre/dav/lib/DAV/INode.php @@ -36,9 +36,10 @@ interface INode { function setName($name); /** - * Returns the last modification time, as a unix timestamp + * Returns the last modification time, as a unix timestamp. Return null + * if the information is not available. * - * @return int + * @return int|null */ function getLastModified(); diff --git a/vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php b/vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php index 910e4979d..2fe843884 100644 --- a/vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php +++ b/vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php @@ -88,6 +88,9 @@ class PDO implements BackendInterface { $stmt->execute([$path]); while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + if (gettype($row['value']) === 'resource') { + $row['value'] = stream_get_contents($row['value']); + } switch ($row['valuetype']) { case null : case self::VT_STRING : @@ -121,7 +124,26 @@ class PDO implements BackendInterface { $propPatch->handleRemaining(function($properties) use ($path) { - $updateStmt = $this->pdo->prepare("REPLACE INTO " . $this->tableName . " (path, name, valuetype, value) VALUES (?, ?, ?, ?)"); + + if ($this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'pgsql') { + + $updateSql = <<tableName} (path, name, valuetype, value) +VALUES (:path, :name, :valuetype, :value) +ON CONFLICT (path, name) +DO UPDATE SET valuetype = :valuetype, value = :value +SQL; + + + } else { + $updateSql = <<tableName} (path, name, valuetype, value) +VALUES (:path, :name, :valuetype, :value) +SQL; + + } + + $updateStmt = $this->pdo->prepare($updateSql); $deleteStmt = $this->pdo->prepare("DELETE FROM " . $this->tableName . " WHERE path = ? AND name = ?"); foreach ($properties as $name => $value) { @@ -136,7 +158,14 @@ class PDO implements BackendInterface { $valueType = self::VT_OBJECT; $value = serialize($value); } - $updateStmt->execute([$path, $name, $valueType, $value]); + + $updateStmt->bindParam('path', $path, \PDO::PARAM_STR); + $updateStmt->bindParam('name', $name, \PDO::PARAM_STR); + $updateStmt->bindParam('valuetype', $valueType, \PDO::PARAM_INT); + $updateStmt->bindParam('value', $value, \PDO::PARAM_LOB); + + $updateStmt->execute(); + } else { $deleteStmt->execute([$path, $name]); } diff --git a/vendor/sabre/dav/lib/DAV/Server.php b/vendor/sabre/dav/lib/DAV/Server.php index b37652812..024b7a557 100644 --- a/vendor/sabre/dav/lib/DAV/Server.php +++ b/vendor/sabre/dav/lib/DAV/Server.php @@ -8,6 +8,10 @@ use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; use Sabre\HTTP\URLUtil; use Sabre\Uri; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; /** * Main DAV server class @@ -16,7 +20,9 @@ use Sabre\Uri; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Server extends EventEmitter { +class Server extends EventEmitter implements LoggerAwareInterface { + + use LoggerAwareTrait; /** * Infinity is used for some request supporting the HTTP Depth header and indicates that the operation should traverse the entire tree @@ -430,6 +436,20 @@ class Server extends EventEmitter { } + /** + * Returns the PSR-3 logger objcet. + * + * @return LoggerInterface + */ + function getLogger() { + + if (!$this->logger) { + $this->logger = new NullLogger(); + } + return $this->logger; + + } + /** * Handles a http request, and execute a method based on its name * @@ -1177,9 +1197,20 @@ class Server extends EventEmitter { if (!$success) { $result = $mkCol->getResult(); - // generateMkCol needs the href key to exist. - $result['href'] = $uri; - return $result; + + $formattedResult = [ + 'href' => $uri, + ]; + + foreach ($result as $propertyName => $status) { + + if (!isset($formattedResult[$status])) { + $formattedResult[$status] = []; + } + $formattedResult[$status][$propertyName] = null; + + } + return $formattedResult; } $this->tree->markDirty($parentUri); diff --git a/vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php b/vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php new file mode 100644 index 000000000..034aefbdc --- /dev/null +++ b/vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php @@ -0,0 +1,69 @@ +server = $server; + + $server->xml->elementMap['{DAV:}share-resource'] = 'Sabre\\DAV\\Xml\\Request\\ShareResource'; + + array_push( + $server->protectedProperties, + '{DAV:}share-mode' + ); + + $server->on('method:POST', [$this, 'httpPost']); + $server->on('propFind', [$this, 'propFind']); + $server->on('getSupportedPrivilegeSet', [$this, 'getSupportedPrivilegeSet']); + $server->on('onHTMLActionsPanel', [$this, 'htmlActionsPanel']); + $server->on('onBrowserPostAction', [$this, 'browserPostAction']); + + } + + /** + * Updates the list of sharees on a shared resource. + * + * The sharees array is a list of people that are to be added modified + * or removed in the list of shares. + * + * @param string $path + * @param Sharee[] $sharees + * @return void + */ + function shareResource($path, array $sharees) { + + $node = $this->server->tree->getNodeForPath($path); + + if (!$node instanceof ISharedNode) { + + throw new Forbidden('Sharing is not allowed on this node'); + + } + + // Getting ACL info + $acl = $this->server->getPlugin('acl'); + + // If there's no ACL support, we allow everything + if ($acl) { + $acl->checkPrivileges($path, '{DAV:}share'); + } + + foreach ($sharees as $sharee) { + // We're going to attempt to get a local principal uri for a share + // href by emitting the getPrincipalByUri event. + $principal = null; + $this->server->emit('getPrincipalByUri', [$sharee->href, &$principal]); + $sharee->principal = $principal; + } + $node->updateInvites($sharees); + + } + + /** + * This event is triggered when properties are requested for nodes. + * + * This allows us to inject any sharings-specific properties. + * + * @param PropFind $propFind + * @param INode $node + * @return void + */ + function propFind(PropFind $propFind, INode $node) { + + if ($node instanceof ISharedNode) { + + $propFind->handle('{DAV:}share-access', function() use ($node) { + + return new Property\ShareAccess($node->getShareAccess()); + + }); + $propFind->handle('{DAV:}invite', function() use ($node) { + + return new Property\Invite($node->getInvites()); + + }); + $propFind->handle('{DAV:}share-resource-uri', function() use ($node) { + + return new Property\Href($node->getShareResourceUri()); + + }); + + } + + } + + /** + * We intercept this to handle POST requests on shared resources + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return null|bool + */ + function httpPost(RequestInterface $request, ResponseInterface $response) { + + $path = $request->getPath(); + $contentType = $request->getHeader('Content-Type'); + + // We're only interested in the davsharing content type. + if (strpos($contentType, 'application/davsharing+xml') === false) { + return; + } + + $message = $this->server->xml->parse( + $request->getBody(), + $request->getUrl(), + $documentType + ); + + switch ($documentType) { + + case '{DAV:}share-resource': + + $this->shareResource($path, $message->sharees); + $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; + + default : + throw new BadRequest('Unexpected document type: ' . $documentType . ' for this Content-Type'); + + } + + } + + /** + * This method is triggered whenever a subsystem reqeuests the privileges + * hat are supported on a particular node. + * + * We need to add a number of privileges for scheduling purposes. + * + * @param INode $node + * @param array $supportedPrivilegeSet + */ + function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilegeSet) { + + if ($node instanceof ISharedNode) { + $supportedPrivilegeSet['{DAV:}share'] = [ + 'abstract' => false, + 'aggregates' => [], + ]; + } + } + + /** + * 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 implements WebDAV resource sharing', + 'link' => 'https://github.com/evert/webdav-sharing' + ]; + + } + + /** + * This method is used to generate HTML output for the + * DAV\Browser\Plugin. + * + * @param INode $node + * @param string $output + * @param string $path + * @return bool|null + */ + function htmlActionsPanel(INode $node, &$output, $path) { + + if (!$node instanceof ISharedNode) { + return; + } + + $aclPlugin = $this->server->getPlugin('acl'); + if ($aclPlugin) { + if (!$aclPlugin->checkPrivileges($path, '{DAV:}share', \Sabre\DAVACL\Plugin::R_PARENT, false)) { + // Sharing is not permitted, we will not draw this interface. + return; + } + } + + $output .= '
+

Share this resource

+ +
+ +
+ +
+ '; + + } + + /** + * This method is triggered for POST actions generated by the browser + * plugin. + * + * @param string $path + * @param string $action + * @param array $postVars + */ + function browserPostAction($path, $action, $postVars) { + + if ($action !== 'share') { + return; + } + + if (empty($postVars['href'])) { + throw new BadRequest('The "href" POST parameter is required'); + } + if (empty($postVars['access'])) { + throw new BadRequest('The "access" POST parameter is required'); + } + + $accessMap = [ + 'readwrite' => self::ACCESS_READWRITE, + 'read' => self::ACCESS_READ, + 'no-access' => self::ACCESS_NOACCESS, + ]; + + if (!isset($accessMap[$postVars['access']])) { + throw new BadRequest('The "access" POST must be readwrite, read or no-access'); + } + $sharee = new Sharee([ + 'href' => $postVars['href'], + 'access' => $accessMap[$postVars['access']], + ]); + + $this->shareResource( + $path, + [$sharee] + ); + return false; + + } + +} diff --git a/vendor/sabre/dav/lib/DAV/Tree.php b/vendor/sabre/dav/lib/DAV/Tree.php index 4563f7c72..5d2792503 100644 --- a/vendor/sabre/dav/lib/DAV/Tree.php +++ b/vendor/sabre/dav/lib/DAV/Tree.php @@ -229,7 +229,7 @@ class Tree { // flushing the entire cache $path = trim($path, '/'); foreach ($this->cache as $nodePath => $node) { - if ($nodePath == $path || strpos($nodePath, $path . '/') === 0) + if ($path === '' || $nodePath == $path || strpos($nodePath, $path . '/') === 0) unset($this->cache[$nodePath]); } diff --git a/vendor/sabre/dav/lib/DAV/Version.php b/vendor/sabre/dav/lib/DAV/Version.php index f9331943a..5430b967c 100644 --- a/vendor/sabre/dav/lib/DAV/Version.php +++ b/vendor/sabre/dav/lib/DAV/Version.php @@ -14,6 +14,6 @@ class Version { /** * Full version number */ - const VERSION = '3.1.3'; + const VERSION = '3.2.0-beta1'; } diff --git a/vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php b/vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php new file mode 100644 index 000000000..dcfd7bd2e --- /dev/null +++ b/vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php @@ -0,0 +1,199 @@ + $v) { + + if (property_exists($this, $k)) { + $this->$k = $v; + } else { + throw new \InvalidArgumentException('Unknown property: ' . $k); + } + + } + + } + + /** + * The xmlSerialize method is called during xml writing. + * + * Use the $writer argument to write its own xml serialization. + * + * An important note: do _not_ create a parent element. Any element + * implementing XmlSerializble should only ever write what's considered + * its 'inner xml'. + * + * The parent of the current element is responsible for writing a + * containing element. + * + * This allows serializers to be re-used for different element names. + * + * If you are opening new elements, you must also close them again. + * + * @param Writer $writer + * @return void + */ + function xmlSerialize(Writer $writer) { + + + $writer->write([ + new Href($this->href), + '{DAV:}prop' => $this->properties, + '{DAV:}share-access' => new ShareAccess($this->access), + ]); + switch ($this->inviteStatus) { + case Plugin::INVITE_NORESPONSE : + $writer->writeElement('{DAV:}invite-noresponse'); + break; + case Plugin::INVITE_ACCEPTED : + $writer->writeElement('{DAV:}invite-accepted'); + break; + case Plugin::INVITE_DECLINED : + $writer->writeElement('{DAV:}invite-declined'); + break; + case Plugin::INVITE_INVALID : + $writer->writeElement('{DAV:}invite-invalid'); + break; + } + + } + + /** + * 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) { + + // Temporarily override configuration + $reader->pushContext(); + $reader->elementMap['{DAV:}share-access'] = 'Sabre\DAV\Xml\Property\ShareAccess'; + $reader->elementMap['{DAV:}prop'] = 'Sabre\Xml\Deserializer\keyValue'; + + $elems = Deserializer\keyValue($reader, 'DAV:'); + + // Restore previous configuration + $reader->popContext(); + + $sharee = new self(); + if (!isset($elems['href'])) { + throw new BadRequest('Every {DAV:}sharee must have a {DAV:}href child-element'); + } + $sharee->href = $elems['href']; + + if (isset($elems['prop'])) { + $sharee->properties = $elems['prop']; + } + if (isset($elems['comment'])) { + $sharee->comment = $elems['comment']; + } + if (!isset($elems['share-access'])) { + throw new BadRequest('Every {DAV:}sharee must have a {DAV:}share-access child element'); + } + $sharee->access = $elems['share-access']->getValue(); + return $sharee; + + } + +} diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/Href.php b/vendor/sabre/dav/lib/DAV/Xml/Property/Href.php index 538e98d0f..0027f72e1 100644 --- a/vendor/sabre/dav/lib/DAV/Xml/Property/Href.php +++ b/vendor/sabre/dav/lib/DAV/Xml/Property/Href.php @@ -7,6 +7,7 @@ use Sabre\DAV\Browser\HtmlOutputHelper; use Sabre\Xml\Element; use Sabre\Xml\Reader; use Sabre\Xml\Writer; +use Sabre\Uri; /** * Href property @@ -31,13 +32,6 @@ class Href implements Element, HtmlOutput { */ protected $hrefs; - /** - * Automatically prefix the url with the server base directory - * - * @var bool - */ - protected $autoPrefix = true; - /** * Constructor * @@ -47,16 +41,13 @@ class Href implements Element, HtmlOutput { * and not relative to the servers base uri. * * @param string|string[] $href - * @param bool $autoPrefix */ - function __construct($hrefs, $autoPrefix = true) { + function __construct($hrefs) { if (is_string($hrefs)) { $hrefs = [$hrefs]; } $this->hrefs = $hrefs; - $this->autoPrefix = $autoPrefix; - } @@ -104,9 +95,7 @@ class Href implements Element, HtmlOutput { function xmlSerialize(Writer $writer) { foreach ($this->getHrefs() as $href) { - if ($this->autoPrefix) { - $href = $writer->contextUri . \Sabre\HTTP\encodePath($href); - } + $href = Uri\resolve($writer->contextUri, $href); $writer->writeElement('{DAV:}href', $href); } diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php b/vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php new file mode 100644 index 000000000..0616ff113 --- /dev/null +++ b/vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php @@ -0,0 +1,70 @@ +sharees = $sharees; + + } + + /** + * The xmlSerialize method is called during xml writing. + * + * Use the $writer argument to write its own xml serialization. + * + * An important note: do _not_ create a parent element. Any element + * implementing XmlSerializble should only ever write what's considered + * its 'inner xml'. + * + * The parent of the current element is responsible for writing a + * containing element. + * + * This allows serializers to be re-used for different element names. + * + * If you are opening new elements, you must also close them again. + * + * @param Writer $writer + * @return void + */ + function xmlSerialize(Writer $writer) { + + foreach ($this->sharees as $sharee) { + $writer->writeElement('{DAV:}sharee', $sharee); + } + + } + +} diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php b/vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php new file mode 100644 index 000000000..76a27b95d --- /dev/null +++ b/vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php @@ -0,0 +1,48 @@ +value = $shareAccess; + + } + + /** + * Returns the current value. + * + * @return int + */ + function getValue() { + + return $this->value; + + } + + /** + * The xmlSerialize method is called during xml writing. + * + * Use the $writer argument to write its own xml serialization. + * + * An important note: do _not_ create a parent element. Any element + * implementing XmlSerializble should only ever write what's considered + * its 'inner xml'. + * + * The parent of the current element is responsible for writing a + * containing element. + * + * This allows serializers to be re-used for different element names. + * + * If you are opening new elements, you must also close them again. + * + * @param Writer $writer + * @return void + */ + function xmlSerialize(Writer $writer) { + + switch ($this->value) { + + case SharingPlugin::ACCESS_NOTSHARED : + $writer->writeElement('{DAV:}not-shared'); + break; + case SharingPlugin::ACCESS_SHAREDOWNER : + $writer->writeElement('{DAV:}shared-owner'); + break; + case SharingPlugin::ACCESS_READ : + $writer->writeElement('{DAV:}read'); + break; + case SharingPlugin::ACCESS_READWRITE : + $writer->writeElement('{DAV:}read-write'); + break; + case SharingPlugin::ACCESS_NOACCESS : + $writer->writeElement('{DAV:}no-access'); + break; + + } + + } + + /** + * 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) { + + $elems = $reader->parseInnerTree(); + foreach ($elems as $elem) { + switch ($elem['name']) { + case '{DAV:}not-shared' : + return new self(SharingPlugin::ACCESS_NOTSHARED); + case '{DAV:}sharedowner' : + return new self(SharingPlugin::ACCESS_SHAREDOWNER); + case '{DAV:}read' : + return new self(SharingPlugin::ACCESS_READ); + case '{DAV:}read-write' : + return new self(SharingPlugin::ACCESS_READWRITE); + case '{DAV:}no-access' : + return new self(SharingPlugin::ACCESS_NOACCESS); + } + } + throw new BadRequest('Invalid value for {DAV:}share-access element'); + + } +} diff --git a/vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php b/vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php new file mode 100644 index 000000000..965e5857c --- /dev/null +++ b/vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php @@ -0,0 +1,81 @@ +sharees = $sharees; + + } + + /** + * 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) { + + $elems = $reader->parseInnerTree([ + '{DAV:}sharee' => 'Sabre\DAV\Xml\Element\Sharee', + '{DAV:}share-access' => 'Sabre\DAV\Xml\Property\ShareAccess', + '{DAV:}prop' => 'Sabre\Xml\Deserializer\keyValue', + ]); + + $sharees = []; + + foreach ($elems as $elem) { + if ($elem['name'] !== '{DAV:}sharee') continue; + $sharees[] = $elem['value']; + + } + + return new self($sharees); + + } + +} diff --git a/vendor/sabre/dav/lib/DAVACL/ACLTrait.php b/vendor/sabre/dav/lib/DAVACL/ACLTrait.php new file mode 100644 index 000000000..602654a2e --- /dev/null +++ b/vendor/sabre/dav/lib/DAVACL/ACLTrait.php @@ -0,0 +1,100 @@ + '{DAV:}all', + 'principal' => '{DAV:}owner', + 'protected' => true, + ] + ]; + + } + + /** + * Updates the ACL + * + * This method will receive a list of new ACE's as an array argument. + * + * @param array $acl + * @return void + */ + function setACL(array $acl) { + + throw new \Sabre\DAV\Exception\Forbidden('Setting ACL is not supported on this node'); + } + + /** + * 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; + + } + +} diff --git a/vendor/sabre/dav/lib/DAVACL/AbstractPrincipalCollection.php b/vendor/sabre/dav/lib/DAVACL/AbstractPrincipalCollection.php index 460f78981..9d2026380 100644 --- a/vendor/sabre/dav/lib/DAVACL/AbstractPrincipalCollection.php +++ b/vendor/sabre/dav/lib/DAVACL/AbstractPrincipalCollection.php @@ -110,7 +110,7 @@ abstract class AbstractPrincipalCollection extends DAV\Collection implements IPr * * @param string $name * @throws DAV\Exception\NotFound - * @return IPrincipal + * @return DAV\INode */ function getChild($name) { diff --git a/vendor/sabre/dav/lib/DAVACL/FS/Collection.php b/vendor/sabre/dav/lib/DAVACL/FS/Collection.php index 5fab4768c..1c08b43b1 100644 --- a/vendor/sabre/dav/lib/DAVACL/FS/Collection.php +++ b/vendor/sabre/dav/lib/DAVACL/FS/Collection.php @@ -3,6 +3,7 @@ namespace Sabre\DAVACL\FS; use Sabre\DAV\FSExt\Directory as BaseCollection; +use Sabre\DAVACL\ACLTrait; use Sabre\DAVACL\IACL; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; @@ -16,6 +17,8 @@ use Sabre\DAV\Exception\NotFound; */ class Collection extends BaseCollection implements IACL { + use ACLTrait; + /** * A list of ACL rules. * @@ -52,8 +55,8 @@ class Collection extends BaseCollection implements IACL { * exist. * * @param string $name - * @throws DAV\Exception\NotFound - * @return DAV\INode + * @throws NotFound + * @return \Sabre\DAV\INode */ function getChild($name) { @@ -87,19 +90,6 @@ class Collection extends BaseCollection implements IACL { } - /** - * 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. * @@ -118,36 +108,4 @@ class Collection extends BaseCollection implements IACL { } - /** - * Updates the ACL - * - * This method will receive a list of new ACE's as an array argument. - * - * @param array $acl - * @return void - */ - function setACL(array $acl) { - - throw new Forbidden('Setting ACL is not allowed here'); - - } - - /** - * 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; - - } - } diff --git a/vendor/sabre/dav/lib/DAVACL/FS/File.php b/vendor/sabre/dav/lib/DAVACL/FS/File.php index 0d549528b..387597bf7 100644 --- a/vendor/sabre/dav/lib/DAVACL/FS/File.php +++ b/vendor/sabre/dav/lib/DAVACL/FS/File.php @@ -4,7 +4,7 @@ namespace Sabre\DAVACL\FS; use Sabre\DAV\FSExt\File as BaseFile; use Sabre\DAVACL\IACL; -use Sabre\DAV\Exception\Forbidden; +use Sabre\DAVACL\ACLTrait; /** * This is an ACL-enabled file node. @@ -15,6 +15,8 @@ use Sabre\DAV\Exception\Forbidden; */ class File extends BaseFile implements IACL { + use ACLTrait; + /** * A list of ACL rules. * @@ -57,19 +59,6 @@ class File extends BaseFile implements IACL { } - /** - * 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. * @@ -88,36 +77,4 @@ class File extends BaseFile implements IACL { } - /** - * Updates the ACL - * - * This method will receive a list of new ACE's as an array argument. - * - * @param array $acl - * @return void - */ - function setACL(array $acl) { - - throw new Forbidden('Setting ACL is not allowed here'); - - } - - /** - * 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; - - } - } diff --git a/vendor/sabre/dav/lib/DAVACL/FS/HomeCollection.php b/vendor/sabre/dav/lib/DAVACL/FS/HomeCollection.php index c27616770..9e21353ea 100644 --- a/vendor/sabre/dav/lib/DAVACL/FS/HomeCollection.php +++ b/vendor/sabre/dav/lib/DAVACL/FS/HomeCollection.php @@ -2,8 +2,8 @@ namespace Sabre\DAVACL\FS; -use Sabre\DAV\Exception\Forbidden; use Sabre\DAVACL\AbstractPrincipalCollection; +use Sabre\DAVACL\ACLTrait; use Sabre\DAVACL\IACL; use Sabre\DAVACL\PrincipalBackend\BackendInterface; use Sabre\Uri; @@ -21,6 +21,8 @@ use Sabre\Uri; */ class HomeCollection extends AbstractPrincipalCollection implements IACL { + use ACLTrait; + /** * Name of this collection. * @@ -70,20 +72,15 @@ class HomeCollection extends AbstractPrincipalCollection implements IACL { * supplied by the authentication backend. * * @param array $principalInfo - * @return void + * @return \Sabre\DAVACL\INode */ function getChildForPrincipal(array $principalInfo) { $owner = $principalInfo['uri']; $acl = [ [ - 'privilege' => '{DAV:}read', - 'principal' => $owner, - 'protected' => true, - ], - [ - 'privilege' => '{DAV:}write', - 'principal' => $owner, + 'privilege' => '{DAV:}all', + 'principal' => '{DAV:}owner', 'protected' => true, ], ]; @@ -103,31 +100,6 @@ class HomeCollection extends AbstractPrincipalCollection implements IACL { } - /** - * 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 null; - - } - - /** - * 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. @@ -153,36 +125,4 @@ class HomeCollection extends AbstractPrincipalCollection implements IACL { } - /** - * Updates the ACL - * - * This method will receive a list of new ACE's as an array argument. - * - * @param array $acl - * @return void - */ - function setACL(array $acl) { - - throw new Forbidden('Setting ACL is not allowed here'); - - } - - /** - * 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; - - } - } diff --git a/vendor/sabre/dav/lib/DAVACL/IACL.php b/vendor/sabre/dav/lib/DAVACL/IACL.php index 81908d08f..f7a138665 100644 --- a/vendor/sabre/dav/lib/DAVACL/IACL.php +++ b/vendor/sabre/dav/lib/DAVACL/IACL.php @@ -71,5 +71,4 @@ interface IACL extends DAV\INode { */ function getSupportedPrivilegeSet(); - } diff --git a/vendor/sabre/dav/lib/DAVACL/Plugin.php b/vendor/sabre/dav/lib/DAVACL/Plugin.php index 601dffecc..59a7b0922 100644 --- a/vendor/sabre/dav/lib/DAVACL/Plugin.php +++ b/vendor/sabre/dav/lib/DAVACL/Plugin.php @@ -4,7 +4,11 @@ namespace Sabre\DAVACL; use Sabre\DAV; use Sabre\DAV\INode; +use Sabre\DAV\Xml\Property\Href; use Sabre\DAV\Exception\BadRequest; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\Exception\NotAuthenticated; +use Sabre\DAVACL\Exception\NeedPrivileges; use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; use Sabre\Uri; @@ -63,18 +67,6 @@ class Plugin extends DAV\ServerPlugin { 'principals', ]; - /** - * By default ACL is only enforced for nodes that have ACL support (the - * ones that implement IACL). For any other node, access is - * always granted. - * - * To override this behaviour you can turn this setting off. This is useful - * if you plan to fully support ACL in the entire tree. - * - * @var bool - */ - public $allowAccessToNodesWithoutACL = true; - /** * By default nodes that are inaccessible by the user, can still be seen * in directory listings (PROPFIND on parent with Depth: 1) @@ -108,6 +100,18 @@ class Plugin extends DAV\ServerPlugin { */ public $adminPrincipals = []; + /** + * The ACL plugin allows privileges to be assigned to users that are not + * logged in. To facilitate that, it modifies the auth plugin's behavior + * to only require login when a privileged operation was denied. + * + * Unauthenticated access can be considered a security concern, so it's + * possible to turn this feature off to harden the server's security. + * + * @var bool + */ + public $allowUnauthenticatedAccess = true; + /** * Returns a list of features added by this plugin. * @@ -161,6 +165,7 @@ class Plugin extends DAV\ServerPlugin { return [ '{DAV:}expand-property', + '{DAV:}principal-match', '{DAV:}principal-property-search', '{DAV:}principal-search-property-set', ]; @@ -179,7 +184,8 @@ class Plugin extends DAV\ServerPlugin { * @param array|string $privileges * @param int $recursion * @param bool $throwExceptions if set to false, this method won't throw exceptions. - * @throws Sabre\DAVACL\Exception\NeedPrivileges + * @throws NeedPrivileges + * @throws NotAuthenticated * @return bool */ function checkPrivileges($uri, $privileges, $recursion = self::R_PARENT, $throwExceptions = true) { @@ -188,18 +194,6 @@ class Plugin extends DAV\ServerPlugin { $acl = $this->getCurrentUserPrivilegeSet($uri); - if (is_null($acl)) { - if ($this->allowAccessToNodesWithoutACL) { - return true; - } else { - if ($throwExceptions) - throw new Exception\NeedPrivileges($uri, $privileges); - else - return false; - - } - } - $failed = []; foreach ($privileges as $priv) { @@ -210,10 +204,22 @@ class Plugin extends DAV\ServerPlugin { } if ($failed) { - if ($throwExceptions) - throw new Exception\NeedPrivileges($uri, $failed); - else + if ($this->allowUnauthenticatedAccess && is_null($this->getCurrentUserPrincipal())) { + // We are not authenticated. Kicking in the Auth plugin. + $authPlugin = $this->server->getPlugin('auth'); + $reasons = $authPlugin->getLoginFailedReasons(); + $authPlugin->challenge( + $this->server->httpRequest, + $this->server->httpResponse + ); + throw new notAuthenticated(implode(', ', $reasons) . '. Login was needed for privilege: ' . implode(', ', $failed) . ' on ' . $uri); + } + if ($throwExceptions) { + + throw new NeedPrivileges($uri, $failed); + } else { return false; + } } return true; @@ -229,10 +235,11 @@ class Plugin extends DAV\ServerPlugin { */ function getCurrentUserPrincipal() { - $authPlugin = $this->server->getPlugin('auth'); - if (is_null($authPlugin)) return null; /** @var $authPlugin Sabre\DAV\Auth\Plugin */ - + $authPlugin = $this->server->getPlugin('auth'); + if (!$authPlugin) { + return null; + } return $authPlugin->getCurrentPrincipal(); } @@ -257,6 +264,56 @@ class Plugin extends DAV\ServerPlugin { } + /** + * Sets the default ACL rules. + * + * These rules are used for all nodes that don't implement the IACL interface. + * + * @param array $acl + * @return void + */ + function setDefaultAcl(array $acl) { + + $this->defaultAcl = $acl; + + } + + /** + * Returns the default ACL rules. + * + * These rules are used for all nodes that don't implement the IACL interface. + * + * @param array $acl + * @return void + */ + function getDefaultAcl() { + + return $this->defaultAcl; + + } + + /** + * The default ACL rules. + * + * These rules are used for nodes that don't implement IACL. These default + * set of rules allow anyone to do anything, as long as they are + * authenticated. + * + * var array + */ + protected $defaultAcl = [ + [ + 'principal' => '{DAV:}authenticated', + 'protected' => true, + 'privilege' => '{DAV:}all', + ], + [ + 'principal' => '{DAV:}unauthenticated', + 'protected' => true, + 'privilege' => '{DAV:}read', + ], + ]; + /** * This array holds a cache for all the principals that are associated with * a single principal. @@ -311,13 +368,77 @@ class Plugin extends DAV\ServerPlugin { } /** - * Returns the supported privilege structure for this ACL plugin. + * Find out of a principal equals another principal. + * + * This is a quick way to find out wether a principal URI is part of a + * group, or any subgroups. * - * See RFC3744 for more details. Currently we default on a simple, - * standard structure. + * The first argument is the principal URI you want to check against. For + * example the principal group, and the second argument is the principal of + * which you want to find out of it is the same as the first principal, or + * in a member of the first principal's group or subgroups. * - * You can either get the list of privileges by a uri (path) or by - * specifying a Node. + * So the arguments are not interchangable. If principal A is in group B, + * passing 'B', 'A' will yield true, but 'A', 'B' is false. + * + * If the sceond argument is not passed, we will use the current user + * principal. + * + * @param string $checkPrincipal + * @param string $currentPrincipal + * @return bool + */ + function principalMatchesPrincipal($checkPrincipal, $currentPrincipal = null) { + + if (is_null($currentPrincipal)) { + $currentPrincipal = $this->getCurrentUserPrincipal(); + } + if ($currentPrincipal === $checkPrincipal) { + return true; + } + return in_array( + $checkPrincipal, + $this->getPrincipalMembership($currentPrincipal) + ); + + } + + + /** + * Returns a tree of supported privileges for a resource. + * + * The returned array structure should be in this form: + * + * [ + * [ + * 'privilege' => '{DAV:}read', + * 'abstract' => false, + * 'aggregates' => [] + * ] + * ] + * + * Privileges can be nested using "aggregrates". Doing so means that + * if you assign someone the aggregrating privilege, all the + * sub-privileges will automatically be granted. + * + * Marking a privilege as abstract means that the privilege cannot be + * directly assigned, but must be assigned via the parent privilege. + * + * So a more complex version might look like this: + * + * [ + * [ + * 'privilege' => '{DAV:}read', + * 'abstract' => false, + * 'aggregates' => [ + * [ + * 'privilege' => '{DAV:}read-acl', + * 'abstract' => false, + * 'aggregates' => [], + * ] + * ] + * ] + * ] * * @param string|INode $node * @return array @@ -328,73 +449,71 @@ class Plugin extends DAV\ServerPlugin { $node = $this->server->tree->getNodeForPath($node); } + $supportedPrivileges = null; if ($node instanceof IACL) { - $result = $node->getSupportedPrivilegeSet(); - - if ($result) - return $result; + $supportedPrivileges = $node->getSupportedPrivilegeSet(); } - return self::getDefaultSupportedPrivilegeSet(); + if (is_null($supportedPrivileges)) { - } - - /** - * Returns a fairly standard set of privileges, which may be useful for - * other systems to use as a basis. - * - * @return array - */ - static function getDefaultSupportedPrivilegeSet() { - - return [ - 'privilege' => '{DAV:}all', - 'abstract' => true, - 'aggregates' => [ - [ - 'privilege' => '{DAV:}read', + // Default + $supportedPrivileges = [ + '{DAV:}read' => [ + 'abstract' => false, 'aggregates' => [ - [ - 'privilege' => '{DAV:}read-acl', - 'abstract' => false, + '{DAV:}read-acl' => [ + 'abstract' => false, + 'aggregates' => [], ], - [ - 'privilege' => '{DAV:}read-current-user-privilege-set', - 'abstract' => false, + '{DAV:}read-current-user-privilege-set' => [ + 'abstract' => false, + 'aggregates' => [], ], ], - ], // {DAV:}read - [ - 'privilege' => '{DAV:}write', + ], + '{DAV:}write' => [ + 'abstract' => false, 'aggregates' => [ - [ - 'privilege' => '{DAV:}write-acl', - 'abstract' => false, - ], - [ - 'privilege' => '{DAV:}write-properties', - 'abstract' => false, - ], - [ - 'privilege' => '{DAV:}write-content', - 'abstract' => false, + '{DAV:}write-properties' => [ + 'abstract' => false, + 'aggregates' => [], ], - [ - 'privilege' => '{DAV:}bind', - 'abstract' => false, + '{DAV:}write-content' => [ + 'abstract' => false, + 'aggregates' => [], ], - [ - 'privilege' => '{DAV:}unbind', - 'abstract' => false, - ], - [ - 'privilege' => '{DAV:}unlock', - 'abstract' => false, + '{DAV:}unlock' => [ + 'abstract' => false, + 'aggregates' => [], ], ], - ], // {DAV:}write - ], - ]; // {DAV:}all + ], + ]; + if ($node instanceof \Sabre\DAV\ICollection) { + $supportedPrivileges['{DAV:}write']['aggregates']['{DAV:}bind'] = [ + 'abstract' => false, + 'aggregates' => [], + ]; + $supportedPrivileges['{DAV:}write']['aggregates']['{DAV:}unbind'] = [ + 'abstract' => false, + 'aggregates' => [], + ]; + } + if ($node instanceof \Sabre\DAVACL\IACL) { + $supportedPrivileges['{DAV:}write']['aggregates']['{DAV:}write-acl'] = [ + 'abstract' => false, + 'aggregates' => [], + ]; + } + + } + + $this->server->emit( + 'getSupportedPrivilegeSet', + [$node, &$supportedPrivileges] + ); + + return $supportedPrivileges; } @@ -414,35 +533,38 @@ class Plugin extends DAV\ServerPlugin { */ final function getFlatPrivilegeSet($node) { - $privs = $this->getSupportedPrivilegeSet($node); + $privs = [ + 'abstract' => false, + 'aggregates' => $this->getSupportedPrivilegeSet($node) + ]; $fpsTraverse = null; - $fpsTraverse = function($priv, $concrete, &$flat) use (&$fpsTraverse) { + $fpsTraverse = function($privName, $privInfo, $concrete, &$flat) use (&$fpsTraverse) { $myPriv = [ - 'privilege' => $priv['privilege'], - 'abstract' => isset($priv['abstract']) && $priv['abstract'], + 'privilege' => $privName, + 'abstract' => isset($privInfo['abstract']) && $privInfo['abstract'], 'aggregates' => [], - 'concrete' => isset($priv['abstract']) && $priv['abstract'] ? $concrete : $priv['privilege'], + 'concrete' => isset($privInfo['abstract']) && $privInfo['abstract'] ? $concrete : $privName, ]; - if (isset($priv['aggregates'])) { + if (isset($privInfo['aggregates'])) { - foreach ($priv['aggregates'] as $subPriv) { + foreach ($privInfo['aggregates'] as $subPrivName => $subPrivInfo) { - $myPriv['aggregates'][] = $subPriv['privilege']; + $myPriv['aggregates'][] = $subPrivName; } } - $flat[$priv['privilege']] = $myPriv; + $flat[$privName] = $myPriv; - if (isset($priv['aggregates'])) { + if (isset($privInfo['aggregates'])) { - foreach ($priv['aggregates'] as $subPriv) { + foreach ($privInfo['aggregates'] as $subPrivName => $subPrivInfo) { - $fpsTraverse($subPriv, $myPriv['concrete'], $flat); + $fpsTraverse($subPrivName, $subPrivInfo, $myPriv['concrete'], $flat); } @@ -451,7 +573,7 @@ class Plugin extends DAV\ServerPlugin { }; $flat = []; - $fpsTraverse($privs, null, $flat); + $fpsTraverse('{DAV:}all', $privs, null, $flat); return $flat; @@ -467,13 +589,13 @@ class Plugin extends DAV\ServerPlugin { * @param string|DAV\INode $node * @return array */ - function getACL($node) { + function getAcl($node) { if (is_string($node)) { $node = $this->server->tree->getNodeForPath($node); } if (!$node instanceof IACL) { - return null; + return $this->getDefaultAcl(); } $acl = $node->getACL(); foreach ($this->adminPrincipals as $adminPrincipal) { @@ -506,12 +628,10 @@ class Plugin extends DAV\ServerPlugin { $acl = $this->getACL($node); - if (is_null($acl)) return null; - - $principals = $this->getCurrentUserPrincipals(); - $collected = []; + $isAuthenticated = $this->getCurrentUserPrincipal() !== null; + foreach ($acl as $ace) { $principal = $ace['principal']; @@ -520,7 +640,7 @@ class Plugin extends DAV\ServerPlugin { case '{DAV:}owner' : $owner = $node->getOwner(); - if ($owner && in_array($owner, $principals)) { + if ($owner && $this->principalMatchesPrincipal($owner)) { $collected[] = $ace; } break; @@ -528,21 +648,25 @@ class Plugin extends DAV\ServerPlugin { // 'all' matches for every user case '{DAV:}all' : + $collected[] = $ace; + break; - // 'authenticated' matched for every user that's logged in. - // Since it's not possible to use ACL while not being logged - // in, this is also always true. case '{DAV:}authenticated' : - $collected[] = $ace; + // Authenticated users only + if ($isAuthenticated) { + $collected[] = $ace; + } break; - // 'unauthenticated' can never occur either, so we simply - // ignore these. case '{DAV:}unauthenticated' : + // Unauthenticated users only + if (!$isAuthenticated) { + $collected[] = $ace; + } break; default : - if (in_array($ace['principal'], $principals)) { + if ($this->principalMatchesPrincipal($ace['principal'])) { $collected[] = $ace; } break; @@ -561,6 +685,11 @@ class Plugin extends DAV\ServerPlugin { $current = array_pop($collected); $collected2[] = $current['privilege']; + if (!isset($flat[$current['privilege']])) { + // Ignoring privileges that are not in the supported-privileges list. + $this->server->getLogger()->debug('A node has the "' . $current['privilege'] . '" in its ACL list, but this privilege was not reported in the supportedPrivilegeSet list. This will be ignored.'); + continue; + } foreach ($flat[$current['privilege']]['aggregates'] as $subPriv) { $collected2[] = $subPriv; $collected[] = $flat[$subPriv]; @@ -587,7 +716,13 @@ class Plugin extends DAV\ServerPlugin { $collections = $this->principalCollectionSet; foreach ($collections as $collection) { - $principalCollection = $this->server->tree->getNodeForPath($collection); + try { + $principalCollection = $this->server->tree->getNodeForPath($collection); + } catch (NotFound $e) { + // Ignore and move on + continue; + } + if (!$principalCollection instanceof IPrincipalCollection) { // Not a principal collection, we're simply going to ignore // this. @@ -673,6 +808,14 @@ class Plugin extends DAV\ServerPlugin { */ function initialize(DAV\Server $server) { + if ($this->allowUnauthenticatedAccess) { + $authPlugin = $server->getPlugin('auth'); + if (!$authPlugin) { + throw new \Exception('The Auth plugin must be loaded before the ACL plugin if you want to allow unauthenticated access.'); + } + $authPlugin->autoRequireLogin = false; + } + $this->server = $server; $server->on('propFind', [$this, 'propFind'], 20); $server->on('beforeMethod', [$this, 'beforeMethod'], 20); @@ -683,6 +826,14 @@ class Plugin extends DAV\ServerPlugin { $server->on('report', [$this, 'report']); $server->on('method:ACL', [$this, 'httpAcl']); $server->on('onHTMLActionsPanel', [$this, 'htmlActionsPanel']); + $server->on('getPrincipalByUri', function($principal, &$uri) { + + $uri = $this->getPrincipalByUri($principal); + + // Break event chain + if ($uri) return false; + + }); array_push($server->protectedProperties, '{DAV:}alternate-URI-set', @@ -707,9 +858,11 @@ class Plugin extends DAV\ServerPlugin { // class. $server->xml->elementMap['{DAV:}group-member-set'] = 'Sabre\\DAV\\Xml\\Property\\Href'; $server->xml->elementMap['{DAV:}acl'] = 'Sabre\\DAVACL\\Xml\\Property\\Acl'; + $server->xml->elementMap['{DAV:}acl-principal-prop-set'] = 'Sabre\\DAVACL\\Xml\\Request\\AclPrincipalPropSetReport'; $server->xml->elementMap['{DAV:}expand-property'] = 'Sabre\\DAVACL\\Xml\\Request\\ExpandPropertyReport'; $server->xml->elementMap['{DAV:}principal-property-search'] = 'Sabre\\DAVACL\\Xml\\Request\\PrincipalPropertySearchReport'; $server->xml->elementMap['{DAV:}principal-search-property-set'] = 'Sabre\\DAVACL\\Xml\\Request\\PrincipalSearchPropertySetReport'; + $server->xml->elementMap['{DAV:}principal-match'] = 'Sabre\\DAVACL\\Xml\\Request\\PrincipalMatchReport'; } @@ -743,7 +896,6 @@ class Plugin extends DAV\ServerPlugin { case 'PUT' : case 'LOCK' : - case 'UNLOCK' : // This method requires the write-content priv if the node // already exists, and bind on the parent if the node is being // created. @@ -751,6 +903,9 @@ class Plugin extends DAV\ServerPlugin { $this->checkPrivileges($path, '{DAV:}write-content'); break; + case 'UNLOCK' : + // Unlock is always allowed at the moment. + break; case 'PROPPATCH' : $this->checkPrivileges($path, '{DAV:}write-properties'); @@ -774,7 +929,6 @@ class Plugin extends DAV\ServerPlugin { // If MOVE is used beforeUnbind will also be used to check if // the sourcenode can be deleted. $this->checkPrivileges($path, '{DAV:}read', self::R_RECURSIVE); - break; } @@ -864,24 +1018,24 @@ class Plugin extends DAV\ServerPlugin { if ($node instanceof IPrincipal) { $propFind->handle('{DAV:}alternate-URI-set', function() use ($node) { - return new DAV\Xml\Property\Href($node->getAlternateUriSet()); + return new Href($node->getAlternateUriSet()); }); $propFind->handle('{DAV:}principal-URL', function() use ($node) { - return new DAV\Xml\Property\Href($node->getPrincipalUrl() . '/'); + return new Href($node->getPrincipalUrl() . '/'); }); $propFind->handle('{DAV:}group-member-set', function() use ($node) { $members = $node->getGroupMemberSet(); foreach ($members as $k => $member) { $members[$k] = rtrim($member, '/') . '/'; } - return new DAV\Xml\Property\Href($members); + return new Href($members); }); $propFind->handle('{DAV:}group-membership', function() use ($node) { $members = $node->getGroupMembership(); foreach ($members as $k => $member) { $members[$k] = rtrim($member, '/') . '/'; } - return new DAV\Xml\Property\Href($members); + return new Href($members); }); $propFind->handle('{DAV:}displayname', [$node, 'getDisplayName']); @@ -892,7 +1046,7 @@ class Plugin extends DAV\ServerPlugin { $val = $this->principalCollectionSet; // Ensuring all collections end with a slash foreach ($val as $k => $v) $val[$k] = $v . '/'; - return new DAV\Xml\Property\Href($val); + return new Href($val); }); $propFind->handle('{DAV:}current-user-principal', function() { @@ -910,9 +1064,7 @@ class Plugin extends DAV\ServerPlugin { $propFind->set('{DAV:}current-user-privilege-set', null, 403); } else { $val = $this->getCurrentUserPrivilegeSet($node); - if (!is_null($val)) { - return new Xml\Property\CurrentUserPrivilegeSet($val); - } + return new Xml\Property\CurrentUserPrivilegeSet($val); } }); $propFind->handle('{DAV:}acl', function() use ($node, $propFind, $path) { @@ -921,9 +1073,7 @@ class Plugin extends DAV\ServerPlugin { $propFind->set('{DAV:}acl', null, 403); } else { $acl = $this->getACL($node); - if (!is_null($acl)) { - return new Xml\Property\Acl($this->getACL($node)); - } + return new Xml\Property\Acl($this->getACL($node)); } }); $propFind->handle('{DAV:}acl-restrictions', function() { @@ -933,7 +1083,7 @@ class Plugin extends DAV\ServerPlugin { /* Adding ACL properties */ if ($node instanceof IACL) { $propFind->handle('{DAV:}owner', function() use ($node) { - return new DAV\Xml\Property\Href($node->getOwner() . '/'); + return new Href($node->getOwner() . '/'); }); } @@ -952,7 +1102,7 @@ class Plugin extends DAV\ServerPlugin { $propPatch->handle('{DAV:}group-member-set', function($value) use ($path) { if (is_null($value)) { $memberSet = []; - } elseif ($value instanceof DAV\Xml\Property\Href) { + } elseif ($value instanceof Href) { $memberSet = array_map( [$this->server, 'calculateUri'], $value->getHrefs() @@ -990,15 +1140,23 @@ class Plugin extends DAV\ServerPlugin { case '{DAV:}principal-property-search' : $this->server->transactionType = 'report-principal-property-search'; - $this->principalPropertySearchReport($report); + $this->principalPropertySearchReport($path, $report); return false; case '{DAV:}principal-search-property-set' : $this->server->transactionType = 'report-principal-search-property-set'; - $this->principalSearchPropertySetReport($report); + $this->principalSearchPropertySetReport($path, $report); return false; case '{DAV:}expand-property' : $this->server->transactionType = 'report-expand-property'; - $this->expandPropertyReport($report); + $this->expandPropertyReport($path, $report); + return false; + case '{DAV:}principal-match' : + $this->server->transactionType = 'report-principal-match'; + $this->principalMatchReport($path, $report); + return false; + case '{DAV:}acl-principal-prop-set' : + $this->server->transactionType = 'acl-principal-prop-set'; + $this->aclPrincipalPropSetReport($path, $report); return false; } @@ -1073,7 +1231,7 @@ class Plugin extends DAV\ServerPlugin { // Looking up the principal try { $principal = $this->server->tree->getNodeForPath($newAce['principal']); - } catch (DAV\Exception\NotFound $e) { + } catch (NotFound $e) { throw new Exception\NotRecognizedPrincipal('The specified principal (' . $newAce['principal'] . ') does not exist'); } if (!($principal instanceof IPrincipal)) { @@ -1095,7 +1253,110 @@ class Plugin extends DAV\ServerPlugin { /* Reports {{{ */ /** - * The expand-property report is defined in RFC3253 section 3-8. + * The principal-match report is defined in RFC3744, section 9.3. + * + * This report allows a client to figure out based on the current user, + * or a principal URL, the principal URL and principal URLs of groups that + * principal belongs to. + * + * @param string $path + * @param Xml\Request\PrincipalMatchReport $report + * @return void + */ + protected function principalMatchReport($path, Xml\Request\PrincipalMatchReport $report) { + + $depth = $this->server->getHTTPDepth(0); + if ($depth !== 0) { + throw new BadRequest('The principal-match report is only defined on Depth: 0'); + } + + $currentPrincipals = $this->getCurrentUserPrincipals(); + + $result = []; + + if ($report->type === Xml\Request\PrincipalMatchReport::SELF) { + + // Finding all principals under the request uri that match the + // current principal. + foreach ($currentPrincipals as $currentPrincipal) { + + if ($currentPrincipal === $path || strpos($currentPrincipal, $path . '/') === 0) { + $result[] = $currentPrincipal; + } + + } + + } else { + + // We need to find all resources that have a property that matches + // one of the current principals. + $candidates = $this->server->getPropertiesForPath( + $path, + [$report->principalProperty], + 1 + ); + + foreach ($candidates as $candidate) { + + if (!isset($candidate[200][$report->principalProperty])) { + continue; + } + + $hrefs = $candidate[200][$report->principalProperty]; + + if (!$hrefs instanceof Href) { + continue; + } + + foreach ($hrefs->getHrefs() as $href) { + if (in_array(trim($href, '/'), $currentPrincipals)) { + $result[] = $candidate['href']; + continue 2; + } + } + } + + } + + $responses = []; + + foreach ($result as $item) { + + $properties = []; + + if ($report->properties) { + + $foo = $this->server->getPropertiesForPath($item, $report->properties); + $foo = $foo[0]; + $item = $foo['href']; + unset($foo['href']); + $properties = $foo; + + } + + $responses[] = new DAV\Xml\Element\Response( + $item, + $properties, + '200' + ); + + } + + $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); + $this->server->httpResponse->setStatus(207); + $this->server->httpResponse->setBody( + $this->server->xml->write( + '{DAV:}multistatus', + $responses, + $this->server->getBaseUri() + ) + ); + + + } + + /** + * The expand-property report is defined in RFC3253 section 3.8. * * This report is very similar to a standard PROPFIND. The difference is * that it has the additional ability to look at properties containing a @@ -1105,15 +1366,15 @@ class Plugin extends DAV\ServerPlugin { * Other rfc's, such as ACL rely on this report, so it made sense to put * it in this plugin. * + * @param string $path * @param Xml\Request\ExpandPropertyReport $report * @return void */ - protected function expandPropertyReport($report) { + protected function expandPropertyReport($path, $report) { $depth = $this->server->getHTTPDepth(0); - $requestUri = $this->server->getRequestUri(); - $result = $this->expandProperties($requestUri, $report->properties, $depth); + $result = $this->expandProperties($path, $report->properties, $depth); $xml = $this->server->xml->write( '{DAV:}multistatus', @@ -1187,10 +1448,11 @@ class Plugin extends DAV\ServerPlugin { * of properties the client may search on, using the * {DAV:}principal-property-search report. * + * @param string $path * @param Xml\Request\PrincipalSearchPropertySetReport $report * @return void */ - protected function principalSearchPropertySetReport($report) { + protected function principalSearchPropertySetReport($path, $report) { $httpDepth = $this->server->getHTTPDepth(0); if ($httpDepth !== 0) { @@ -1241,14 +1503,14 @@ class Plugin extends DAV\ServerPlugin { * clients to search for groups of principals, based on the value of one * or more properties. * + * @param string $path * @param Xml\Request\PrincipalPropertySearchReport $report * @return void */ - protected function principalPropertySearchReport($report) { + protected function principalPropertySearchReport($path, Xml\Request\PrincipalPropertySearchReport $report) { - $uri = null; - if (!$report->applyToPrincipalCollectionSet) { - $uri = $this->server->httpRequest->getPath(); + if ($report->applyToPrincipalCollectionSet) { + $path = null; } if ($this->server->getHttpDepth('0') !== 0) { throw new BadRequest('Depth must be 0'); @@ -1256,7 +1518,7 @@ class Plugin extends DAV\ServerPlugin { $result = $this->principalSearch( $report->searchProperties, $report->properties, - $uri, + $path, $report->test ); @@ -1269,6 +1531,64 @@ class Plugin extends DAV\ServerPlugin { } + /** + * aclPrincipalPropSet REPORT + * + * This method is responsible for handling the {DAV:}acl-principal-prop-set + * REPORT, as defined in: + * + * https://tools.ietf.org/html/rfc3744#section-9.2 + * + * This REPORT allows a user to quickly fetch information about all + * principals specified in the access control list. Most commonly this + * is used to for example generate a UI with ACL rules, allowing you + * to show names for principals for every entry. + * + * @param string $path + * @param Xml\Request\AclPrincipalPropSetReport $report + * @return void + */ + protected function aclPrincipalPropSetReport($path, Xml\Request\AclPrincipalPropSetReport $report) { + + if ($this->server->getHTTPDepth(0) !== 0) { + throw new BadRequest('The {DAV:}acl-principal-prop-set REPORT only supports Depth 0'); + } + + // Fetching ACL rules for the given path. We're using the property + // API and not the local getACL, because it will ensure that all + // business rules and restrictions are applied. + $acl = $this->server->getProperties($path, '{DAV:}acl'); + + if (!$acl || !isset($acl['{DAV:}acl'])) { + throw new Forbidden('Could not fetch ACL rules for this path'); + } + + $principals = []; + foreach ($acl['{DAV:}acl']->getPrivileges() as $ace) { + + if ($ace['principal'][0] === '{') { + // It's not a principal, it's one of the special rules such as {DAV:}authenticated + continue; + } + + $principals[] = $ace['principal']; + + } + + $properties = $this->server->getPropertiesForMultiplePaths( + $principals, + $report->properties + ); + + $this->server->httpResponse->setStatus(207); + $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); + $this->server->httpResponse->setBody( + $this->server->generateMultiStatus($properties) + ); + + } + + /* }}} */ /** diff --git a/vendor/sabre/dav/lib/DAVACL/Principal.php b/vendor/sabre/dav/lib/DAVACL/Principal.php index 16375d3fc..6ebb30907 100644 --- a/vendor/sabre/dav/lib/DAVACL/Principal.php +++ b/vendor/sabre/dav/lib/DAVACL/Principal.php @@ -22,6 +22,8 @@ use Sabre\HTTP\URLUtil; */ class Principal extends DAV\Node implements IPrincipal, DAV\IProperties, IACL { + use ACLTrait; + /** * Struct with principal information. * @@ -216,73 +218,4 @@ class Principal extends DAV\Node implements IPrincipal, DAV\IProperties, IACL { } - /** - * 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, - ], - ]; - - } - - /** - * 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('Updating ACLs is not allowed here'); - - } - - /** - * 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; - - } - } diff --git a/vendor/sabre/dav/lib/DAVACL/PrincipalBackend/PDO.php b/vendor/sabre/dav/lib/DAVACL/PrincipalBackend/PDO.php index 01b7a175c..a491dc88f 100644 --- a/vendor/sabre/dav/lib/DAVACL/PrincipalBackend/PDO.php +++ b/vendor/sabre/dav/lib/DAVACL/PrincipalBackend/PDO.php @@ -300,7 +300,7 @@ class PDO extends AbstractBackend implements CreatePrincipalSupport { $value = null; $scheme = null; list($scheme, $value) = explode(":", $uri, 2); - if ($value == null) return null; + if (empty($value)) return null; $uri = null; switch ($scheme){ diff --git a/vendor/sabre/dav/lib/DAVACL/PrincipalCollection.php b/vendor/sabre/dav/lib/DAVACL/PrincipalCollection.php index 54911e7b5..d8a90153a 100644 --- a/vendor/sabre/dav/lib/DAVACL/PrincipalCollection.php +++ b/vendor/sabre/dav/lib/DAVACL/PrincipalCollection.php @@ -3,7 +3,6 @@ namespace Sabre\DAVACL; use Sabre\DAV\Exception\InvalidResourceType; -use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\IExtendedCollection; use Sabre\DAV\MkCol; @@ -19,6 +18,8 @@ use Sabre\DAV\MkCol; */ class PrincipalCollection extends AbstractPrincipalCollection implements IExtendedCollection, IACL { + use ACLTrait; + /** * This method returns a node for a principal. * @@ -72,28 +73,6 @@ class PrincipalCollection extends AbstractPrincipalCollection implements IExtend } - /** - * 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 null; - } - - /** - * 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. * @@ -116,36 +95,4 @@ class PrincipalCollection extends AbstractPrincipalCollection implements IExtend ]; } - /** - * Updates the ACL - * - * This method will receive a list of new ACE's as an array argument. - * - * @param array $acl - * @return void - */ - function setACL(array $acl) { - - throw new Forbidden('Updating ACLs is not allowed on this node'); - - } - - /** - * 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; - - } - } diff --git a/vendor/sabre/dav/lib/DAVACL/Xml/Property/SupportedPrivilegeSet.php b/vendor/sabre/dav/lib/DAVACL/Xml/Property/SupportedPrivilegeSet.php index 572bed4dd..55e7783ae 100644 --- a/vendor/sabre/dav/lib/DAVACL/Xml/Property/SupportedPrivilegeSet.php +++ b/vendor/sabre/dav/lib/DAVACL/Xml/Property/SupportedPrivilegeSet.php @@ -73,7 +73,7 @@ class SupportedPrivilegeSet implements XmlSerializable, HtmlOutput { */ function xmlSerialize(Writer $writer) { - $this->serializePriv($writer, $this->privileges); + $this->serializePriv($writer, '{DAV:}all', [ 'aggregates' => $this->privileges]); } @@ -93,9 +93,9 @@ class SupportedPrivilegeSet implements XmlSerializable, HtmlOutput { */ function toHtml(HtmlOutputHelper $html) { - $traverse = function($priv) use (&$traverse, $html) { + $traverse = function($privName, $priv) use (&$traverse, $html) { echo "
  • "; - echo $html->xmlName($priv['privilege']); + echo $html->xmlName($privName); if (isset($priv['abstract']) && $priv['abstract']) { echo " (abstract)"; } @@ -104,8 +104,8 @@ class SupportedPrivilegeSet implements XmlSerializable, HtmlOutput { } if (isset($priv['aggregates'])) { echo "\n
      \n"; - foreach ($priv['aggregates'] as $subPriv) { - $traverse($subPriv); + foreach ($priv['aggregates'] as $subPrivName => $subPriv) { + $traverse($subPrivName, $subPriv); } echo "
    "; } @@ -114,7 +114,7 @@ class SupportedPrivilegeSet implements XmlSerializable, HtmlOutput { ob_start(); echo "
      "; - $traverse($this->getValue()); + $traverse('{DAV:}all', [ 'aggregates' => $this->getValue() ]); echo "
    \n"; return ob_get_clean(); @@ -132,12 +132,12 @@ class SupportedPrivilegeSet implements XmlSerializable, HtmlOutput { * @param array $privilege * @return void */ - private function serializePriv(Writer $writer, $privilege) { + private function serializePriv(Writer $writer, $privName, $privilege) { $writer->startElement('{DAV:}supported-privilege'); $writer->startElement('{DAV:}privilege'); - $writer->writeElement($privilege['privilege']); + $writer->writeElement($privName); $writer->endElement(); // privilege if (!empty($privilege['abstract'])) { @@ -147,8 +147,8 @@ class SupportedPrivilegeSet implements XmlSerializable, HtmlOutput { $writer->writeElement('{DAV:}description', $privilege['description']); } if (isset($privilege['aggregates'])) { - foreach ($privilege['aggregates'] as $subPrivilege) { - $this->serializePriv($writer, $subPrivilege); + foreach ($privilege['aggregates'] as $subPrivName => $subPrivilege) { + $this->serializePriv($writer, $subPrivName, $subPrivilege); } } diff --git a/vendor/sabre/dav/lib/DAVACL/Xml/Request/AclPrincipalPropSetReport.php b/vendor/sabre/dav/lib/DAVACL/Xml/Request/AclPrincipalPropSetReport.php new file mode 100644 index 000000000..f01c1e6ab --- /dev/null +++ b/vendor/sabre/dav/lib/DAVACL/Xml/Request/AclPrincipalPropSetReport.php @@ -0,0 +1,67 @@ +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) { + + $reader->pushContext(); + $reader->elementMap['{DAV:}prop'] = 'Sabre\Xml\Deserializer\enum'; + + $elems = Deserializer\keyValue( + $reader, + 'DAV:' + ); + + $reader->popContext(); + + $report = new self(); + + if (!empty($elems['prop'])) { + $report->properties = $elems['prop']; + } + + return $report; + + } + +} diff --git a/vendor/sabre/dav/lib/DAVACL/Xml/Request/PrincipalMatchReport.php b/vendor/sabre/dav/lib/DAVACL/Xml/Request/PrincipalMatchReport.php new file mode 100644 index 000000000..5c4e88189 --- /dev/null +++ b/vendor/sabre/dav/lib/DAVACL/Xml/Request/PrincipalMatchReport.php @@ -0,0 +1,107 @@ +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) { + + $reader->pushContext(); + $reader->elementMap['{DAV:}prop'] = 'Sabre\Xml\Deserializer\enum'; + + $elems = Deserializer\keyValue( + $reader, + 'DAV:' + ); + + $reader->popContext(); + + $principalMatch = new self(); + + if (array_key_exists('self', $elems)) { + $principalMatch->type = self::SELF; + } + + if (array_key_exists('principal-property', $elems)) { + $principalMatch->type = self::PRINCIPAL_PROPERTY; + $principalMatch->principalProperty = $elems['principal-property'][0]['name']; + } + + if (!empty($elems['prop'])) { + $principalMatch->properties = $elems['prop']; + } + + return $principalMatch; + + } + +} diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/AbstractPDOTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/AbstractPDOTest.php index 25f8b1794..35d6da353 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/AbstractPDOTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/AbstractPDOTest.php @@ -5,11 +5,30 @@ namespace Sabre\CalDAV\Backend; use Sabre\CalDAV; use Sabre\DAV; use Sabre\DAV\PropPatch; +use Sabre\DAV\Xml\Element\Sharee; abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { + use DAV\DbTestHelperTrait; + protected $pdo; + function setUp() { + + $this->dropTables([ + 'calendarobjects', + 'calendars', + 'calendarinstances', + 'calendarchanges', + 'calendarsubscriptions', + 'schedulingobjects', + ]); + $this->createSchema('calendars'); + + $this->pdo = $this->getDb(); + + } + function testConstruct() { $backend = new PDO($this->pdo); @@ -42,11 +61,11 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $calendars = $backend->getCalendarsForUser('principals/user2'); $elementCheck = [ - 'id' => $returnedId, 'uri' => 'somerandomid', '{DAV:}displayname' => 'Hello!', '{urn:ietf:params:xml:ns:caldav}calendar-description' => '', '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp' => new CalDAV\Xml\Property\ScheduleCalendarTransp('transparent'), + 'share-access' => \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER, ]; $this->assertInternalType('array', $calendars); @@ -109,6 +128,27 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { } + /** + * @depends testConstruct + * @expectedException \InvalidArgumentException + */ + function testUpdateCalendarBadId() { + + $backend = new PDO($this->pdo); + + //Creating a new calendar + $newId = $backend->createCalendar('principals/user2', 'somerandomid', []); + + $propPatch = new PropPatch([ + '{DAV:}displayname' => 'myCalendar', + '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp' => new CalDAV\Xml\Property\ScheduleCalendarTransp('transparent'), + ]); + + // Updating the calendar + $backend->updateCalendar('raaaa', $propPatch); + + } + /** * @depends testUpdateCalendarAndFetch */ @@ -154,6 +194,22 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { } + /** + * @depends testCreateCalendarAndFetch + * @expectedException \InvalidArgumentException + */ + function testDeleteCalendarBadID() { + + $backend = new PDO($this->pdo); + $returnedId = $backend->createCalendar('principals/user2', 'somerandomid', [ + '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new CalDAV\Xml\Property\SupportedCalendarComponentSet(['VEVENT']), + '{DAV:}displayname' => 'Hello!', + ]); + + $backend->deleteCalendar('bad-id'); + + } + /** * @depends testCreateCalendarAndFetch * @expectedException \Sabre\DAV\Exception @@ -178,7 +234,13 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $backend->createCalendarObject($returnedId, 'random-id', $object); - $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = "random-id"'); + $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = \'random-id\''); + + $row = $result->fetch(\PDO::FETCH_ASSOC); + if (is_resource($row['calendardata'])) { + $row['calendardata'] = stream_get_contents($row['calendardata']); + } + $this->assertEquals([ 'etag' => md5($object), 'size' => strlen($object), @@ -186,7 +248,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'firstoccurence' => strtotime('20120101'), 'lastoccurence' => strtotime('20120101') + (3600 * 24), 'componenttype' => 'VEVENT', - ], $result->fetch(\PDO::FETCH_ASSOC)); + ], $row); } function testGetMultipleObjects() { @@ -207,7 +269,6 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'size' => strlen($object), 'calendardata' => $object, 'lastmodified' => null, - 'calendarid' => $returnedId, ], [ 'id' => 2, @@ -216,7 +277,6 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'size' => strlen($object), 'calendardata' => $object, 'lastmodified' => null, - 'calendarid' => $returnedId, ], ]; @@ -224,12 +284,22 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { foreach ($check as $index => $props) { - foreach ($props as $key => $value) { + foreach ($props as $key => $expected) { + + $actual = $result[$index][$key]; + + switch ($key) { + case 'lastmodified' : + $this->assertInternalType('int', $actual); + break; + case 'calendardata' : + if (is_resource($actual)) { + $actual = stream_get_contents($actual); + } + // no break intentional + default : + $this->assertEquals($expected, $actual); - if ($key !== 'lastmodified') { - $this->assertEquals($value, $result[$index][$key]); - } else { - $this->assertTrue(isset($result[$index][$key])); } } @@ -238,6 +308,17 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { } + /** + * @depends testGetMultipleObjects + * @expectedException \InvalidArgumentException + */ + function testGetMultipleObjectsBadId() { + + $backend = new PDO($this->pdo); + $backend->getMultipleCalendarObjects('bad-id', ['foo-bar']); + + } + /** * @expectedException Sabre\DAV\Exception\BadRequest * @depends testCreateCalendarObject @@ -265,7 +346,13 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $backend->createCalendarObject($returnedId, 'random-id', $object); - $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = "random-id"'); + $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = \'random-id\''); + + $row = $result->fetch(\PDO::FETCH_ASSOC); + if (is_resource($row['calendardata'])) { + $row['calendardata'] = stream_get_contents($row['calendardata']); + } + $this->assertEquals([ 'etag' => md5($object), 'size' => strlen($object), @@ -273,10 +360,26 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'firstoccurence' => strtotime('20120101'), 'lastoccurence' => strtotime('20120101') + (3600 * 48), 'componenttype' => 'VEVENT', - ], $result->fetch(\PDO::FETCH_ASSOC)); + ], $row); + + } + + /** + * @depends testCreateCalendarObject + * @expectedException \InvalidArgumentException + */ + function testCreateCalendarObjectBadId() { + + $backend = new PDO($this->pdo); + $returnedId = $backend->createCalendar('principals/user2', 'somerandomid', []); + + $object = "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART;VALUE=DATE:20120101\r\nDURATION:P2D\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"; + + $backend->createCalendarObject('bad-id', 'random-id', $object); } + /** * @depends testCreateCalendarObject */ @@ -289,7 +392,12 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $backend->createCalendarObject($returnedId, 'random-id', $object); - $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = "random-id"'); + $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = \'random-id\''); + $row = $result->fetch(\PDO::FETCH_ASSOC); + if (is_resource($row['calendardata'])) { + $row['calendardata'] = stream_get_contents($row['calendardata']); + } + $this->assertEquals([ 'etag' => md5($object), 'size' => strlen($object), @@ -297,7 +405,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'firstoccurence' => strtotime('2012-01-01 10:00:00'), 'lastoccurence' => strtotime('2012-01-01 10:00:00'), 'componenttype' => 'VEVENT', - ], $result->fetch(\PDO::FETCH_ASSOC)); + ], $row); } @@ -313,7 +421,12 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $backend->createCalendarObject($returnedId, 'random-id', $object); - $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = "random-id"'); + $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = \'random-id\''); + $row = $result->fetch(\PDO::FETCH_ASSOC); + if (is_resource($row['calendardata'])) { + $row['calendardata'] = stream_get_contents($row['calendardata']); + } + $this->assertEquals([ 'etag' => md5($object), 'size' => strlen($object), @@ -321,7 +434,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'firstoccurence' => strtotime('2012-01-01 10:00:00'), 'lastoccurence' => strtotime('2012-01-01 11:00:00'), 'componenttype' => 'VEVENT', - ], $result->fetch(\PDO::FETCH_ASSOC)); + ], $row); } @@ -337,7 +450,12 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $backend->createCalendarObject($returnedId, 'random-id', $object); - $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = "random-id"'); + $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = \'random-id\''); + $row = $result->fetch(\PDO::FETCH_ASSOC); + if (is_resource($row['calendardata'])) { + $row['calendardata'] = stream_get_contents($row['calendardata']); + } + $this->assertEquals([ 'etag' => md5($object), 'size' => strlen($object), @@ -345,7 +463,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'firstoccurence' => strtotime('2012-01-01 10:00:00'), 'lastoccurence' => strtotime(PDO::MAX_DATE), 'componenttype' => 'VEVENT', - ], $result->fetch(\PDO::FETCH_ASSOC)); + ], $row); } @@ -361,7 +479,12 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $backend->createCalendarObject($returnedId, 'random-id', $object); - $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = "random-id"'); + $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = \'random-id\''); + $row = $result->fetch(\PDO::FETCH_ASSOC); + if (is_resource($row['calendardata'])) { + $row['calendardata'] = stream_get_contents($row['calendardata']); + } + $this->assertEquals([ 'etag' => md5($object), 'size' => strlen($object), @@ -369,7 +492,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'firstoccurence' => strtotime('2012-01-01 10:00:00'), 'lastoccurence' => strtotime('2012-01-01 11:00:00') + (3600 * 24 * 999), 'componenttype' => 'VEVENT', - ], $result->fetch(\PDO::FETCH_ASSOC)); + ], $row); } @@ -385,7 +508,12 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $backend->createCalendarObject($returnedId, 'random-id', $object); - $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = "random-id"'); + $result = $this->pdo->query('SELECT etag, size, calendardata, firstoccurence, lastoccurence, componenttype FROM calendarobjects WHERE uri = \'random-id\''); + $row = $result->fetch(\PDO::FETCH_ASSOC); + if (is_resource($row['calendardata'])) { + $row['calendardata'] = stream_get_contents($row['calendardata']); + } + $this->assertEquals([ 'etag' => md5($object), 'size' => strlen($object), @@ -393,7 +521,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'firstoccurence' => null, 'lastoccurence' => null, 'componenttype' => 'VTODO', - ], $result->fetch(\PDO::FETCH_ASSOC)); + ], $row); } @@ -408,17 +536,38 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $object = "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART;VALUE=DATE:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"; $backend->createCalendarObject($returnedId, 'random-id', $object); - $data = $backend->getCalendarObjects($returnedId, 'random-id'); + $data = $backend->getCalendarObjects($returnedId); $this->assertEquals(1, count($data)); $data = $data[0]; - $this->assertEquals($returnedId, $data['calendarid']); $this->assertEquals('random-id', $data['uri']); $this->assertEquals(strlen($object), $data['size']); + } + + /** + * @depends testGetCalendarObjects + * @expectedException \InvalidArgumentException + */ + function testGetCalendarObjectsBadId() { + + $backend = new PDO($this->pdo); + $backend->getCalendarObjects('bad-id'); } + + /** + * @depends testGetCalendarObjects + * @expectedException \InvalidArgumentException + */ + function testGetCalendarObjectBadId() { + + $backend = new PDO($this->pdo); + $backend->getCalendarObject('bad-id', 'foo-bar'); + + } + /** * @depends testCreateCalendarObject */ @@ -455,13 +604,27 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $data = $backend->getCalendarObject($returnedId, 'random-id'); + if (is_resource($data['calendardata'])) { + $data['calendardata'] = stream_get_contents($data['calendardata']); + } + $this->assertEquals($object2, $data['calendardata']); - $this->assertEquals($returnedId, $data['calendarid']); $this->assertEquals('random-id', $data['uri']); } + /** + * @depends testUpdateCalendarObject + * @expectedException \InvalidArgumentException + */ + function testUpdateCalendarObjectBadId() { + + $backend = new PDO($this->pdo); + $backend->updateCalendarObject('bad-id', 'object-id', 'objectdata'); + + } + /** * @depends testCreateCalendarObject */ @@ -479,6 +642,21 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { } + /** + * @depends testDeleteCalendarObject + * @expectedException \InvalidArgumentException + */ + function testDeleteCalendarObjectBadId() { + + $backend = new PDO($this->pdo); + $returnedId = $backend->createCalendar('principals/user2', 'somerandomid', []); + + $object = "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART;VALUE=DATE:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"; + $backend->createCalendarObject($returnedId, 'random-id', $object); + $backend->deleteCalendarObject('bad-id', 'random-id'); + + } + function testCalendarQueryNoResult() { $abstract = new PDO($this->pdo); @@ -499,15 +677,42 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { ]; $this->assertEquals([ - ], $abstract->calendarQuery(1, $filters)); + ], $abstract->calendarQuery([1, 1], $filters)); + + } + + /** + * @expectedException \InvalidArgumentException + * @depends testCalendarQueryNoResult + */ + function testCalendarQueryBadId() { + + $abstract = new PDO($this->pdo); + $filters = [ + 'name' => 'VCALENDAR', + 'comp-filters' => [ + [ + 'name' => 'VJOURNAL', + 'comp-filters' => [], + 'prop-filters' => [], + 'is-not-defined' => false, + 'time-range' => null, + ], + ], + 'prop-filters' => [], + 'is-not-defined' => false, + 'time-range' => null, + ]; + + $abstract->calendarQuery('bad-id', $filters); } function testCalendarQueryTodo() { $backend = new PDO($this->pdo); - $backend->createCalendarObject(1, "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); - $backend->createCalendarObject(1, "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $filters = [ 'name' => 'VCALENDAR', @@ -527,14 +732,14 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $this->assertEquals([ "todo", - ], $backend->calendarQuery(1, $filters)); + ], $backend->calendarQuery([1, 1], $filters)); } function testCalendarQueryTodoNotMatch() { $backend = new PDO($this->pdo); - $backend->createCalendarObject(1, "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); - $backend->createCalendarObject(1, "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $filters = [ 'name' => 'VCALENDAR', @@ -561,15 +766,15 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { ]; $this->assertEquals([ - ], $backend->calendarQuery(1, $filters)); + ], $backend->calendarQuery([1, 1], $filters)); } function testCalendarQueryNoFilter() { $backend = new PDO($this->pdo); - $backend->createCalendarObject(1, "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); - $backend->createCalendarObject(1, "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $filters = [ 'name' => 'VCALENDAR', @@ -579,7 +784,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { 'time-range' => null, ]; - $result = $backend->calendarQuery(1, $filters); + $result = $backend->calendarQuery([1, 1], $filters); $this->assertTrue(in_array('todo', $result)); $this->assertTrue(in_array('event', $result)); @@ -588,9 +793,9 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { function testCalendarQueryTimeRange() { $backend = new PDO($this->pdo); - $backend->createCalendarObject(1, "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); - $backend->createCalendarObject(1, "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART;VALUE=DATE:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); - $backend->createCalendarObject(1, "event2", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART;VALUE=DATE:20120103\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART;VALUE=DATE:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "event2", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART;VALUE=DATE:20120103\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $filters = [ 'name' => 'VCALENDAR', @@ -613,15 +818,15 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $this->assertEquals([ "event2", - ], $backend->calendarQuery(1, $filters)); + ], $backend->calendarQuery([1, 1], $filters)); } function testCalendarQueryTimeRangeNoEnd() { $backend = new PDO($this->pdo); - $backend->createCalendarObject(1, "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); - $backend->createCalendarObject(1, "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); - $backend->createCalendarObject(1, "event2", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120103\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "todo", "BEGIN:VCALENDAR\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "event", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $backend->createCalendarObject([1, 1], "event2", "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDTSTART:20120103\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $filters = [ 'name' => 'VCALENDAR', @@ -644,7 +849,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $this->assertEquals([ "event2", - ], $backend->calendarQuery(1, $filters)); + ], $backend->calendarQuery([1, 1], $filters)); } @@ -694,6 +899,22 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { ], $result); } + /** + * @depends testGetChanges + * @expectedException \InvalidArgumentException + */ + function testGetChangesBadId() { + + $backend = new PDO($this->pdo); + $id = $backend->createCalendar( + 'principals/user1', + 'bla', + [] + ); + $backend->getChangesForCalendar('bad-id', null, 1); + + } + function testCreateSubscriptions() { $props = [ @@ -862,6 +1083,9 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $result = $backend->getSchedulingObject('principals/user1', 'schedule1.ics'); foreach ($expected as $k => $v) { $this->assertArrayHasKey($k, $result); + if (is_resource($result[$k])) { + $result[$k] = stream_get_contents($result[$k]); + } $this->assertEquals($v, $result[$k]); } @@ -870,6 +1094,9 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $this->assertEquals(1, count($results)); $result = $results[0]; foreach ($expected as $k => $v) { + if (is_resource($result[$k])) { + $result[$k] = stream_get_contents($result[$k]); + } $this->assertEquals($v, $result[$k]); } @@ -880,4 +1107,315 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { } + function testGetInvites() { + + $backend = new PDO($this->pdo); + + // creating a new calendar + $backend->createCalendar('principals/user1', 'somerandomid', []); + $calendar = $backend->getCalendarsForUser('principals/user1')[0]; + + $result = $backend->getInvites($calendar['id']); + $expected = [ + new Sharee([ + 'href' => 'principals/user1', + 'principal' => 'principals/user1', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + ]) + ]; + + $this->assertEquals($expected, $result); + + } + + /** + * @depends testGetInvites + * @expectedException \InvalidArgumentException + */ + function testGetInvitesBadId() { + + $backend = new PDO($this->pdo); + + // creating a new calendar + $backend->createCalendar('principals/user1', 'somerandomid', []); + $calendar = $backend->getCalendarsForUser('principals/user1')[0]; + + $backend->getInvites('bad-id'); + + } + + /** + * @depends testCreateCalendarAndFetch + */ + function testUpdateInvites() { + + $backend = new PDO($this->pdo); + + // creating a new calendar + $backend->createCalendar('principals/user1', 'somerandomid', []); + $calendar = $backend->getCalendarsForUser('principals/user1')[0]; + + $ownerSharee = new Sharee([ + 'href' => 'principals/user1', + 'principal' => 'principals/user1', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + ]); + + // Add a new invite + $backend->updateInvites( + $calendar['id'], + [ + new Sharee([ + 'href' => 'mailto:user@example.org', + 'principal' => 'principals/user2', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READ, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + 'properties' => ['{DAV:}displayname' => 'User 2'], + ]) + ] + ); + + $result = $backend->getInvites($calendar['id']); + $expected = [ + $ownerSharee, + new Sharee([ + 'href' => 'mailto:user@example.org', + 'principal' => 'principals/user2', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READ, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + 'properties' => [ + '{DAV:}displayname' => 'User 2', + ], + ]) + ]; + $this->assertEquals($expected, $result); + + // Checking calendar_instances too + $expectedCalendar = [ + 'id' => [1,2], + 'principaluri' => 'principals/user2', + '{http://calendarserver.org/ns/}getctag' => 'http://sabre.io/ns/sync/1', + '{http://sabredav.org/ns}sync-token' => '1', + 'share-access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READ, + 'read-only' => true, + 'share-resource-uri' => '/ns/share/1', + ]; + $calendars = $backend->getCalendarsForUser('principals/user2'); + + foreach ($expectedCalendar as $k => $v) { + $this->assertEquals( + $v, + $calendars[0][$k], + "Key " . $k . " in calendars array did not have the expected value." + ); + } + + + // Updating an invite + $backend->updateInvites( + $calendar['id'], + [ + new Sharee([ + 'href' => 'mailto:user@example.org', + 'principal' => 'principals/user2', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + ]) + ] + ); + + $result = $backend->getInvites($calendar['id']); + $expected = [ + $ownerSharee, + new Sharee([ + 'href' => 'mailto:user@example.org', + 'principal' => 'principals/user2', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + 'properties' => [ + '{DAV:}displayname' => 'User 2', + ], + ]) + ]; + $this->assertEquals($expected, $result); + + // Removing an invite + $backend->updateInvites( + $calendar['id'], + [ + new Sharee([ + 'href' => 'mailto:user@example.org', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS, + ]) + ] + ); + + $result = $backend->getInvites($calendar['id']); + $expected = [ + $ownerSharee + ]; + $this->assertEquals($expected, $result); + + // Preventing the owner share from being removed + $backend->updateInvites( + $calendar['id'], + [ + new Sharee([ + 'href' => 'principals/user2', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS, + ]) + ] + ); + + $result = $backend->getInvites($calendar['id']); + $expected = [ + new Sharee([ + 'href' => 'principals/user1', + 'principal' => 'principals/user1', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + ]), + ]; + $this->assertEquals($expected, $result); + + } + + /** + * @depends testUpdateInvites + * @expectedException \InvalidArgumentException + */ + function testUpdateInvitesBadId() { + + $backend = new PDO($this->pdo); + // Add a new invite + $backend->updateInvites( + 'bad-id', + [] + ); + + } + + /** + * @depends testUpdateInvites + */ + function testUpdateInvitesNoPrincipal() { + + $backend = new PDO($this->pdo); + + // creating a new calendar + $backend->createCalendar('principals/user1', 'somerandomid', []); + $calendar = $backend->getCalendarsForUser('principals/user1')[0]; + + $ownerSharee = new Sharee([ + 'href' => 'principals/user1', + 'principal' => 'principals/user1', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + ]); + + // Add a new invite + $backend->updateInvites( + $calendar['id'], + [ + new Sharee([ + 'href' => 'mailto:user@example.org', + 'principal' => null, + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READ, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + 'properties' => ['{DAV:}displayname' => 'User 2'], + ]) + ] + ); + + $result = $backend->getInvites($calendar['id']); + $expected = [ + $ownerSharee, + new Sharee([ + 'href' => 'mailto:user@example.org', + 'principal' => null, + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READ, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_INVALID, + 'properties' => [ + '{DAV:}displayname' => 'User 2', + ], + ]) + ]; + $this->assertEquals($expected, $result, null, 0.0, 10, true); // Last argument is $canonicalize = true, which allows us to compare, ignoring the order, because it's different between MySQL and Sqlite. + + } + + /** + * @depends testUpdateInvites + */ + function testDeleteSharedCalendar() { + + $backend = new PDO($this->pdo); + + // creating a new calendar + $backend->createCalendar('principals/user1', 'somerandomid', []); + $calendar = $backend->getCalendarsForUser('principals/user1')[0]; + + $ownerSharee = new Sharee([ + 'href' => 'principals/user1', + 'principal' => 'principals/user1', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + ]); + + // Add a new invite + $backend->updateInvites( + $calendar['id'], + [ + new Sharee([ + 'href' => 'mailto:user@example.org', + 'principal' => 'principals/user2', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READ, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + 'properties' => ['{DAV:}displayname' => 'User 2'], + ]) + ] + ); + + $expectedCalendar = [ + 'id' => [1,2], + 'principaluri' => 'principals/user2', + '{http://calendarserver.org/ns/}getctag' => 'http://sabre.io/ns/sync/1', + '{http://sabredav.org/ns}sync-token' => '1', + 'share-access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READ, + 'read-only' => true, + 'share-resource-uri' => '/ns/share/1', + ]; + $calendars = $backend->getCalendarsForUser('principals/user2'); + + foreach ($expectedCalendar as $k => $v) { + $this->assertEquals( + $v, + $calendars[0][$k], + "Key " . $k . " in calendars array did not have the expected value." + ); + } + + // Removing the shared calendar. + $backend->deleteCalendar($calendars[0]['id']); + + $this->assertEquals( + [], + $backend->getCalendarsForUser('principals/user2') + ); + + $result = $backend->getInvites($calendar['id']); + $expected = [ + new Sharee([ + 'href' => 'principals/user1', + 'principal' => 'principals/user1', + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED, + ]), + ]; + $this->assertEquals($expected, $result); + + } + } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/Mock.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/Mock.php index 4412e5531..d4dcc07dc 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/Mock.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/Mock.php @@ -81,6 +81,46 @@ class Mock extends AbstractBackend { } + /** + * 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 documentation for more info and examples. + * + * @param mixed $calendarId + * @param \Sabre\DAV\PropPatch $propPatch + * @return void + */ + function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) { + + $propPatch->handleRemaining(function($props) use ($calendarId) { + + foreach ($this->calendars as $k => $calendar) { + + if ($calendar['id'] === $calendarId) { + foreach ($props as $propName => $propValue) { + if (is_null($propValue)) { + unset($this->calendars[$k][$propName]); + } else { + $this->calendars[$k][$propName] = $propValue; + } + } + return true; + + } + + } + + }); + + } + /** * Delete a calendar and all it's objects * @@ -139,18 +179,22 @@ class Mock extends AbstractBackend { * 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. * - * @param string $calendarId + * This method must return null if the object did not exist. + * + * @param mixed $calendarId * @param string $objectUri - * @return array + * @return array|null */ function getCalendarObject($calendarId, $objectUri) { if (!isset($this->calendarData[$calendarId][$objectUri])) { - throw new DAV\Exception\NotFound('Object could not be found'); + return null; } $object = $this->calendarData[$calendarId][$objectUri]; $object['calendarid'] = $calendarId; @@ -207,8 +251,7 @@ class Mock extends AbstractBackend { */ function deleteCalendarObject($calendarId, $objectUri) { - throw new Exception('Not implemented'); - + unset($this->calendarData[$calendarId][$objectUri]); } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/PDOMySQLTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/PDOMySQLTest.php index c215ca171..e068ff1e7 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/PDOMySQLTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/PDOMySQLTest.php @@ -2,38 +2,8 @@ namespace Sabre\CalDAV\Backend; -require_once 'Sabre/TestUtil.php'; -require_once 'Sabre/CalDAV/TestUtil.php'; -require_once 'Sabre/CalDAV/Backend/AbstractPDOTest.php'; - class PDOMySQLTest extends AbstractPDOTest { - function setup() { - - if (!SABRE_HASMYSQL) $this->markTestSkipped('MySQL driver is not available, or not properly configured'); - $pdo = \Sabre\TestUtil::getMySQLDB(); - if (!$pdo) $this->markTestSkipped('Could not connect to mysql database'); - - $pdo->query('DROP TABLE IF EXISTS calendarobjects, calendars, calendarchanges, calendarsubscriptions, schedulingobjects'); - - $queries = explode( - ';', - file_get_contents(__DIR__ . '/../../../../examples/sql/mysql.calendars.sql') - ); - - foreach ($queries as $query) { - $query = trim($query, " \r\n\t"); - if ($query) - $pdo->exec($query); - } - $this->pdo = $pdo; - - } - - function teardown() { - - $this->pdo = null; - - } + public $driver = 'mysql'; } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/PDOSqliteTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/PDOSqliteTest.php index 4074259f2..90ad5a171 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/PDOSqliteTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/PDOSqliteTest.php @@ -2,36 +2,8 @@ namespace Sabre\CalDAV\Backend; -use Sabre\CalDAV; - -require_once 'Sabre/CalDAV/Backend/AbstractPDOTest.php'; - class PDOSqliteTest extends AbstractPDOTest { - function setup() { - - if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available'); - - if (file_exists(SABRE_TEMPDIR . '/testdb.sqlite')) - unlink(SABRE_TEMPDIR . '/testdb.sqlite'); - - $pdo = new \PDO('sqlite:' . SABRE_TEMPDIR . '/testdb.sqlite'); - $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - - // Yup this is definitely not 'fool proof', but good enough for now. - $queries = explode(';', file_get_contents(__DIR__ . '/../../../../examples/sql/sqlite.calendars.sql')); - foreach ($queries as $query) { - $pdo->exec($query); - } - $this->pdo = $pdo; - - } - - function teardown() { - - $this->pdo = null; - unlink(SABRE_TEMPDIR . '/testdb.sqlite'); - - } + public $driver = 'sqlite'; } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarObjectTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarObjectTest.php index 9fc1eee4c..0d98922ff 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarObjectTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarObjectTest.php @@ -1,7 +1,6 @@ markTestSkipped('SQLite driver is not available'); $this->backend = TestUtil::getBackend(); $calendars = $this->backend->getCalendarsForUser('principals/user1'); - $this->assertEquals(2,count($calendars)); + $this->assertEquals(2, count($calendars)); $this->calendar = new Calendar($this->backend, $calendars[0]); } @@ -40,10 +38,10 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { $children = $this->calendar->getChildren(); $this->assertTrue($children[0] instanceof CalendarObject); - $this->assertInternalType('string',$children[0]->getName()); - $this->assertInternalType('string',$children[0]->get()); - $this->assertInternalType('string',$children[0]->getETag()); - $this->assertEquals('text/calendar; charset=utf-8; component=vevent', $children[0]->getContentType()); + $this->assertInternalType('string', $children[0]->getName()); + $this->assertInternalType('string', $children[0]->get()); + $this->assertInternalType('string', $children[0]->getETag()); + $this->assertEquals('text/calendar; charset=utf-8', $children[0]->getContentType()); } @@ -53,9 +51,9 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { function testInvalidArg1() { $obj = new CalendarObject( - new Backend\Mock(array(),array()), - array(), - array() + new Backend\Mock([], []), + [], + [] ); } @@ -66,9 +64,9 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { function testInvalidArg2() { $obj = new CalendarObject( - new Backend\Mock(array(),array()), - array(), - array('calendarid' => '1') + new Backend\Mock([], []), + [], + ['calendarid' => '1'] ); } @@ -96,7 +94,7 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { $this->assertTrue($children[0] instanceof CalendarObject); $newData = TestUtil::getTestCalendarData(); - $stream = fopen('php://temp','r+'); + $stream = fopen('php://temp', 'r+'); fwrite($stream, $newData); rewind($stream); $children[0]->put($stream); @@ -117,7 +115,7 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { $obj->delete(); $children2 = $this->calendar->getChildren(); - $this->assertEquals(count($children)-1, count($children2)); + $this->assertEquals(count($children) - 1, count($children2)); } @@ -132,7 +130,7 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { $obj = $children[0]; $lastMod = $obj->getLastModified(); - $this->assertTrue(is_int($lastMod) || ctype_digit($lastMod)); + $this->assertTrue(is_int($lastMod) || ctype_digit($lastMod) || is_null($lastMod)); } @@ -173,33 +171,33 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { function testGetACL() { - $expected = array( - array( + $expected = [ + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1/calendar-proxy-write', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1/calendar-proxy-read', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}write', 'principal' => 'principals/user1', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}write', 'principal' => 'principals/user1/calendar-proxy-write', 'protected' => true, - ), - ); + ], + ]; $children = $this->calendar->getChildren(); $this->assertTrue($children[0] instanceof CalendarObject); @@ -213,40 +211,30 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { $backend = new Backend\Mock([], []); $calendarObject = new CalendarObject($backend, ['principaluri' => 'principals/user1'], ['calendarid' => 1, 'uri' => 'foo']); - $expected = array( - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/user1', - 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', + $expected = [ + [ + 'privilege' => '{DAV:}all', 'principal' => 'principals/user1', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}read', + ], + [ + 'privilege' => '{DAV:}all', 'principal' => 'principals/user1/calendar-proxy-write', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', - 'principal' => 'principals/user1/calendar-proxy-write', - 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1/calendar-proxy-read', 'protected' => true, - ), - ); + ], + ]; $this->assertEquals($expected, $calendarObject->getACL()); } /** - * @expectedException Sabre\DAV\Exception\MethodNotAllowed + * @expectedException \Sabre\DAV\Exception\Forbidden */ function testSetACL() { @@ -254,7 +242,7 @@ class CalendarObjectTest extends \PHPUnit_Framework_TestCase { $this->assertTrue($children[0] instanceof CalendarObject); $obj = $children[0]; - $obj->setACL(array()); + $obj->setACL([]); } @@ -306,15 +294,15 @@ END:VCALENDAR"; function testGetRefetch() { - $backend = new Backend\Mock(array(), array( - 1 => array( - 'foo' => array( + $backend = new Backend\Mock([], [ + 1 => [ + 'foo' => [ 'calendardata' => 'foo', - 'uri' => 'foo' - ), - ) - )); - $obj = new CalendarObject($backend, array('id' => 1), array('uri' => 'foo')); + 'uri' => 'foo' + ], + ] + ]); + $obj = new CalendarObject($backend, ['id' => 1], ['uri' => 'foo']); $this->assertEquals('foo', $obj->get()); @@ -322,15 +310,15 @@ END:VCALENDAR"; function testGetEtag1() { - $objectInfo = array( + $objectInfo = [ 'calendardata' => 'foo', - 'uri' => 'foo', - 'etag' => 'bar', - 'calendarid' => 1 - ); + 'uri' => 'foo', + 'etag' => 'bar', + 'calendarid' => 1 + ]; - $backend = new Backend\Mock(array(), array()); - $obj = new CalendarObject($backend, array(), $objectInfo); + $backend = new Backend\Mock([], []); + $obj = new CalendarObject($backend, [], $objectInfo); $this->assertEquals('bar', $obj->getETag()); @@ -338,14 +326,14 @@ END:VCALENDAR"; function testGetEtag2() { - $objectInfo = array( + $objectInfo = [ 'calendardata' => 'foo', - 'uri' => 'foo', - 'calendarid' => 1 - ); + 'uri' => 'foo', + 'calendarid' => 1 + ]; - $backend = new Backend\Mock(array(), array()); - $obj = new CalendarObject($backend, array(), $objectInfo); + $backend = new Backend\Mock([], []); + $obj = new CalendarObject($backend, [], $objectInfo); $this->assertEquals('"' . md5('foo') . '"', $obj->getETag()); @@ -353,42 +341,42 @@ END:VCALENDAR"; function testGetSupportedPrivilegesSet() { - $objectInfo = array( + $objectInfo = [ 'calendardata' => 'foo', - 'uri' => 'foo', - 'calendarid' => 1 - ); + 'uri' => 'foo', + 'calendarid' => 1 + ]; - $backend = new Backend\Mock(array(), array()); - $obj = new CalendarObject($backend, array(), $objectInfo); + $backend = new Backend\Mock([], []); + $obj = new CalendarObject($backend, [], $objectInfo); $this->assertNull($obj->getSupportedPrivilegeSet()); } function testGetSize1() { - $objectInfo = array( + $objectInfo = [ 'calendardata' => 'foo', - 'uri' => 'foo', - 'calendarid' => 1 - ); + 'uri' => 'foo', + 'calendarid' => 1 + ]; - $backend = new Backend\Mock(array(), array()); - $obj = new CalendarObject($backend, array(), $objectInfo); + $backend = new Backend\Mock([], []); + $obj = new CalendarObject($backend, [], $objectInfo); $this->assertEquals(3, $obj->getSize()); } function testGetSize2() { - $objectInfo = array( - 'uri' => 'foo', + $objectInfo = [ + 'uri' => 'foo', 'calendarid' => 1, - 'size' => 4, - ); + 'size' => 4, + ]; - $backend = new Backend\Mock(array(), array()); - $obj = new CalendarObject($backend, array(), $objectInfo); + $backend = new Backend\Mock([], []); + $obj = new CalendarObject($backend, [], $objectInfo); $this->assertEquals(4, $obj->getSize()); } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarQueryVAlarmTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarQueryVAlarmTest.php index 9de24d3aa..ca06d8ffa 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarQueryVAlarmTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarQueryVAlarmTest.php @@ -26,32 +26,32 @@ class CalendarQueryVAlarmTest extends \PHPUnit_Framework_TestCase { $vcalendar->add($vevent); - $filter = array( - 'name' => 'VCALENDAR', + $filter = [ + 'name' => 'VCALENDAR', 'is-not-defined' => false, - 'time-range' => null, - 'prop-filters' => array(), - 'comp-filters' => array( - array( - 'name' => 'VEVENT', + 'time-range' => null, + 'prop-filters' => [], + 'comp-filters' => [ + [ + 'name' => 'VEVENT', 'is-not-defined' => false, - 'time-range' => null, - 'prop-filters' => array(), - 'comp-filters' => array( - array( - 'name' => 'VALARM', + 'time-range' => null, + 'prop-filters' => [], + 'comp-filters' => [ + [ + 'name' => 'VALARM', 'is-not-defined' => false, - 'prop-filters' => array(), - 'comp-filters' => array(), - 'time-range' => array( + 'prop-filters' => [], + 'comp-filters' => [], + 'time-range' => [ 'start' => new \DateTime('2012-05-10'), - 'end' => new \DateTime('2012-05-20'), - ), - ), - ), - ), - ), - ); + 'end' => new \DateTime('2012-05-20'), + ], + ], + ], + ], + ], + ]; $validator = new CalendarQueryValidator(); $this->assertTrue($validator->validate($vcalendar, $filter)); @@ -87,32 +87,32 @@ class CalendarQueryVAlarmTest extends \PHPUnit_Framework_TestCase { $vcalendar->add($vevent); - $filter = array( - 'name' => 'VCALENDAR', + $filter = [ + 'name' => 'VCALENDAR', 'is-not-defined' => false, - 'time-range' => null, - 'prop-filters' => array(), - 'comp-filters' => array( - array( - 'name' => 'VEVENT', + 'time-range' => null, + 'prop-filters' => [], + 'comp-filters' => [ + [ + 'name' => 'VEVENT', 'is-not-defined' => false, - 'time-range' => null, - 'prop-filters' => array(), - 'comp-filters' => array( - array( - 'name' => 'VALARM', + 'time-range' => null, + 'prop-filters' => [], + 'comp-filters' => [ + [ + 'name' => 'VALARM', 'is-not-defined' => false, - 'prop-filters' => array(), - 'comp-filters' => array(), - 'time-range' => array( + 'prop-filters' => [], + 'comp-filters' => [], + 'time-range' => [ 'start' => new \DateTime('2011-12-10'), - 'end' => new \DateTime('2011-12-20'), - ), - ), - ), - ), - ), - ); + 'end' => new \DateTime('2011-12-20'), + ], + ], + ], + ], + ], + ]; $validator = new CalendarQueryValidator(); $this->assertTrue($validator->validate($vcalendar, $filter)); diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php index 9822e82e2..4c2558a9b 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarQueryValidatorTest.php @@ -1,8 +1,8 @@ 'VCALENDAR', - 'comp-filters' => array($filters), - 'prop-filters' => array(), + $filters = [ + 'name' => 'VCALENDAR', + 'comp-filters' => [$filters], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => null, - ); + 'time-range' => null, + ]; $vObject = VObject\Reader::read($icalObject); - switch($outcome) { + switch ($outcome) { case 0 : $this->assertFalse($validator->validate($vObject, $filters)); break; @@ -392,13 +392,13 @@ END:VEVENT END:VCALENDAR yow; - $filter1 = array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filter1 = [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => null, - ); + 'time-range' => null, + ]; $filter2 = $filter1; $filter2['name'] = 'VTODO'; @@ -410,25 +410,25 @@ yow; $filter4['is-not-defined'] = true; $filter5 = $filter1; - $filter5['comp-filters'] = array( - array( - 'name' => 'VALARM', + $filter5['comp-filters'] = [ + [ + 'name' => 'VALARM', 'is-not-defined' => false, - 'comp-filters' => array(), - 'prop-filters' => array(), - 'time-range' => null, - ), - ); + 'comp-filters' => [], + 'prop-filters' => [], + 'time-range' => null, + ], + ]; $filter6 = $filter1; - $filter6['prop-filters'] = array( - array( - 'name' => 'SUMMARY', + $filter6['prop-filters'] = [ + [ + 'name' => 'SUMMARY', 'is-not-defined' => false, - 'param-filters' => array(), - 'time-range' => null, - 'text-match' => null, - ), - ); + 'param-filters' => [], + 'time-range' => null, + 'text-match' => null, + ], + ]; $filter7 = $filter6; $filter7['prop-filters'][0]['name'] = 'DESCRIPTION'; @@ -443,21 +443,21 @@ yow; // Param filters $filter11 = $filter1; - $filter11['prop-filters'] = array( - array( - 'name' => 'DTSTART', + $filter11['prop-filters'] = [ + [ + 'name' => 'DTSTART', 'is-not-defined' => false, - 'param-filters' => array( - array( - 'name' => 'VALUE', + 'param-filters' => [ + [ + 'name' => 'VALUE', 'is-not-defined' => false, - 'text-match' => null, - ), - ), + 'text-match' => null, + ], + ], 'time-range' => null, 'text-match' => null, - ), - ); + ], + ]; $filter12 = $filter11; $filter12['prop-filters'][0]['param-filters'][0]['name'] = 'TZID'; @@ -470,11 +470,11 @@ yow; // Param text filter $filter15 = $filter11; - $filter15['prop-filters'][0]['param-filters'][0]['text-match'] = array( - 'collation' => 'i;ascii-casemap', - 'value' => 'dAtE', + $filter15['prop-filters'][0]['param-filters'][0]['text-match'] = [ + 'collation' => 'i;ascii-casemap', + 'value' => 'dAtE', 'negate-condition' => false, - ); + ]; $filter16 = $filter15; $filter16['prop-filters'][0]['param-filters'][0]['text-match']['collation'] = 'i;octet'; @@ -487,31 +487,31 @@ yow; // prop + text $filter19 = $filter5; - $filter19['comp-filters'][0]['prop-filters'] = array( - array( - 'name' => 'action', + $filter19['comp-filters'][0]['prop-filters'] = [ + [ + 'name' => 'action', 'is-not-defined' => false, - 'time-range' => null, - 'param-filters' => array(), - 'text-match' => array( - 'collation' => 'i;ascii-casemap', - 'value' => 'display', + 'time-range' => null, + 'param-filters' => [], + 'text-match' => [ + 'collation' => 'i;ascii-casemap', + 'value' => 'display', 'negate-condition' => false, - ), - ), - ); + ], + ], + ]; // Time range - $filter20 = array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filter20 = [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2011-01-01 10:00:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 13:00:00', new \DateTimeZone('GMT')), - ), - ); + 'end' => new \DateTime('2011-01-01 13:00:00', new \DateTimeZone('GMT')), + ], + ]; // Time range, no end date $filter21 = $filter20; $filter21['time-range']['end'] = null; @@ -522,105 +522,105 @@ yow; // Time range, other dates $filter23 = $filter20; - $filter23['time-range'] = array( + $filter23['time-range'] = [ 'start' => new \DateTime('2011-02-01 10:00:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-02-01 13:00:00', new \DateTimeZone('GMT')), - ); + 'end' => new \DateTime('2011-02-01 13:00:00', new \DateTimeZone('GMT')), + ]; // Time range - $filter24 = array( - 'name' => 'VTODO', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filter24 = [ + 'name' => 'VTODO', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2011-01-01 12:45:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 13:15:00', new \DateTimeZone('GMT')), - ), - ); + 'end' => new \DateTime('2011-01-01 13:15:00', new \DateTimeZone('GMT')), + ], + ]; // Time range, other dates (1 month in the future) $filter25 = $filter24; - $filter25['time-range'] = array( + $filter25['time-range'] = [ 'start' => new \DateTime('2011-02-01 10:00:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-02-01 13:00:00', new \DateTimeZone('GMT')), - ); + 'end' => new \DateTime('2011-02-01 13:00:00', new \DateTimeZone('GMT')), + ]; $filter26 = $filter24; - $filter26['time-range'] = array( + $filter26['time-range'] = [ 'start' => new \DateTime('2011-01-01 11:45:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 12:15:00', new \DateTimeZone('GMT')), - ); + 'end' => new \DateTime('2011-01-01 12:15:00', new \DateTimeZone('GMT')), + ]; // Time range for VJOURNAL - $filter27 = array( - 'name' => 'VJOURNAL', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filter27 = [ + 'name' => 'VJOURNAL', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2011-01-01 12:45:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 13:15:00', new \DateTimeZone('GMT')), - ), - ); + 'end' => new \DateTime('2011-01-01 13:15:00', new \DateTimeZone('GMT')), + ], + ]; $filter28 = $filter27; - $filter28['time-range'] = array( + $filter28['time-range'] = [ 'start' => new \DateTime('2011-01-01 11:45:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 12:15:00', new \DateTimeZone('GMT')), - ); + 'end' => new \DateTime('2011-01-01 12:15:00', new \DateTimeZone('GMT')), + ]; // Time range for VFREEBUSY - $filter29 = array( - 'name' => 'VFREEBUSY', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filter29 = [ + 'name' => 'VFREEBUSY', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2011-01-01 12:45:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 13:15:00', new \DateTimeZone('GMT')), - ), - ); + 'end' => new \DateTime('2011-01-01 13:15:00', new \DateTimeZone('GMT')), + ], + ]; // Time range filter on property - $filter30 = array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array( - array( - 'name' => 'DTSTART', + $filter30 = [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [ + [ + 'name' => 'DTSTART', 'is-not-defined' => false, - 'param-filters' => array(), - 'time-range' => array( + 'param-filters' => [], + 'time-range' => [ 'start' => new \DateTime('2011-01-01 10:00:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 13:00:00', new \DateTimeZone('GMT')), - ), + 'end' => new \DateTime('2011-01-01 13:00:00', new \DateTimeZone('GMT')), + ], 'text-match' => null, - ), - ), + ], + ], 'is-not-defined' => false, - 'time-range' => null, - ); + 'time-range' => null, + ]; // Time range for alarm - $filter31 = array( - 'name' => 'VEVENT', - 'prop-filters' => array(), - 'comp-filters' => array( - array( - 'name' => 'VALARM', + $filter31 = [ + 'name' => 'VEVENT', + 'prop-filters' => [], + 'comp-filters' => [ + [ + 'name' => 'VALARM', 'is-not-defined' => false, - 'comp-filters' => array(), - 'prop-filters' => array(), - 'time-range' => array( + 'comp-filters' => [], + 'prop-filters' => [], + 'time-range' => [ 'start' => new \DateTime('2011-01-01 10:45:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 11:15:00', new \DateTimeZone('GMT')), - ), + 'end' => new \DateTime('2011-01-01 11:15:00', new \DateTimeZone('GMT')), + ], 'text-match' => null, - ), - ), + ], + ], 'is-not-defined' => false, - 'time-range' => null, - ); + 'time-range' => null, + ]; $filter32 = $filter31; - $filter32['comp-filters'][0]['time-range'] = array( + $filter32['comp-filters'][0]['time-range'] = [ 'start' => new \DateTime('2011-01-01 11:45:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 12:15:00', new \DateTimeZone('GMT')), - ); + 'end' => new \DateTime('2011-01-01 12:15:00', new \DateTimeZone('GMT')), + ]; $filter33 = $filter31; $filter33['name'] = 'VTODO'; @@ -632,194 +632,194 @@ yow; $filter36['name'] = 'VJOURNAL'; // Time range filter on non-datetime property - $filter37 = array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array( - array( - 'name' => 'SUMMARY', + $filter37 = [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [ + [ + 'name' => 'SUMMARY', 'is-not-defined' => false, - 'param-filters' => array(), - 'time-range' => array( + 'param-filters' => [], + 'time-range' => [ 'start' => new \DateTime('2011-01-01 10:00:00', new \DateTimeZone('GMT')), - 'end' => new \DateTime('2011-01-01 13:00:00', new \DateTimeZone('GMT')), - ), + 'end' => new \DateTime('2011-01-01 13:00:00', new \DateTimeZone('GMT')), + ], 'text-match' => null, - ), - ), + ], + ], 'is-not-defined' => false, - 'time-range' => null, - ); + 'time-range' => null, + ]; - $filter38 = array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filter38 = [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2012-07-01 00:00:00', new \DateTimeZone('UTC')), - 'end' => new \DateTime('2012-08-01 00:00:00', new \DateTimeZone('UTC')), - ) - ); - $filter39 = array( - 'name' => 'VEVENT', - 'comp-filters' => array( - array( - 'name' => 'VALARM', - 'comp-filters' => array(), - 'prop-filters' => array(), + 'end' => new \DateTime('2012-08-01 00:00:00', new \DateTimeZone('UTC')), + ] + ]; + $filter39 = [ + 'name' => 'VEVENT', + 'comp-filters' => [ + [ + 'name' => 'VALARM', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2012-09-01 00:00:00', new \DateTimeZone('UTC')), - 'end' => new \DateTime('2012-10-01 00:00:00', new \DateTimeZone('UTC')), - ) - ), - ), - 'prop-filters' => array(), + 'end' => new \DateTime('2012-10-01 00:00:00', new \DateTimeZone('UTC')), + ] + ], + ], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => null, - ); + 'time-range' => null, + ]; - return array( + return [ // Component check - array($blob1, $filter1, 1), - array($blob1, $filter2, 0), - array($blob1, $filter3, 0), - array($blob1, $filter4, 1), + [$blob1, $filter1, 1], + [$blob1, $filter2, 0], + [$blob1, $filter3, 0], + [$blob1, $filter4, 1], // Subcomponent check (4) - array($blob1, $filter5, 0), - array($blob2, $filter5, 1), + [$blob1, $filter5, 0], + [$blob2, $filter5, 1], // Property checki (6) - array($blob1, $filter6, 1), - array($blob1, $filter7, 0), - array($blob1, $filter8, 0), - array($blob1, $filter9, 1), + [$blob1, $filter6, 1], + [$blob1, $filter7, 0], + [$blob1, $filter8, 0], + [$blob1, $filter9, 1], // Subcomponent + property (10) - array($blob2, $filter10, 1), + [$blob2, $filter10, 1], // Param filter (11) - array($blob3, $filter11, 1), - array($blob3, $filter12, 0), - array($blob3, $filter13, 0), - array($blob3, $filter14, 1), + [$blob3, $filter11, 1], + [$blob3, $filter12, 0], + [$blob3, $filter13, 0], + [$blob3, $filter14, 1], // Param + text (15) - array($blob3, $filter15, 1), - array($blob3, $filter16, 0), - array($blob3, $filter17, 0), - array($blob3, $filter18, 1), + [$blob3, $filter15, 1], + [$blob3, $filter16, 0], + [$blob3, $filter17, 0], + [$blob3, $filter18, 1], // Prop + text (19) - array($blob2, $filter19, 1), + [$blob2, $filter19, 1], // Incorrect object (vcard) (20) - array($blob4, $filter1, -1), + [$blob4, $filter1, -1], // Time-range for event (21) - array($blob5, $filter20, 1), - array($blob6, $filter20, 1), - array($blob7, $filter20, 1), - array($blob8, $filter20, 1), + [$blob5, $filter20, 1], + [$blob6, $filter20, 1], + [$blob7, $filter20, 1], + [$blob8, $filter20, 1], - array($blob5, $filter21, 1), - array($blob5, $filter22, 1), + [$blob5, $filter21, 1], + [$blob5, $filter22, 1], - array($blob5, $filter23, 0), - array($blob6, $filter23, 0), - array($blob7, $filter23, 0), - array($blob8, $filter23, 0), + [$blob5, $filter23, 0], + [$blob6, $filter23, 0], + [$blob7, $filter23, 0], + [$blob8, $filter23, 0], // Time-range for todo (31) - array($blob9, $filter24, 1), - array($blob9, $filter25, 0), - array($blob9, $filter26, 1), - array($blob10, $filter24, 1), - array($blob10, $filter25, 0), - array($blob10, $filter26, 1), + [$blob9, $filter24, 1], + [$blob9, $filter25, 0], + [$blob9, $filter26, 1], + [$blob10, $filter24, 1], + [$blob10, $filter25, 0], + [$blob10, $filter26, 1], - array($blob11, $filter24, 0), - array($blob11, $filter25, 0), - array($blob11, $filter26, 1), + [$blob11, $filter24, 0], + [$blob11, $filter25, 0], + [$blob11, $filter26, 1], - array($blob12, $filter24, 1), - array($blob12, $filter25, 0), - array($blob12, $filter26, 0), + [$blob12, $filter24, 1], + [$blob12, $filter25, 0], + [$blob12, $filter26, 0], - array($blob13, $filter24, 1), - array($blob13, $filter25, 0), - array($blob13, $filter26, 1), + [$blob13, $filter24, 1], + [$blob13, $filter25, 0], + [$blob13, $filter26, 1], - array($blob14, $filter24, 1), - array($blob14, $filter25, 0), - array($blob14, $filter26, 0), + [$blob14, $filter24, 1], + [$blob14, $filter25, 0], + [$blob14, $filter26, 0], - array($blob15, $filter24, 1), - array($blob15, $filter25, 1), - array($blob15, $filter26, 1), + [$blob15, $filter24, 1], + [$blob15, $filter25, 1], + [$blob15, $filter26, 1], - array($blob16, $filter24, 1), - array($blob16, $filter25, 1), - array($blob16, $filter26, 1), + [$blob16, $filter24, 1], + [$blob16, $filter25, 1], + [$blob16, $filter26, 1], // Time-range for journals (55) - array($blob17, $filter27, 0), - array($blob17, $filter28, 0), - array($blob18, $filter27, 0), - array($blob18, $filter28, 1), - array($blob19, $filter27, 1), - array($blob19, $filter28, 1), + [$blob17, $filter27, 0], + [$blob17, $filter28, 0], + [$blob18, $filter27, 0], + [$blob18, $filter28, 1], + [$blob19, $filter27, 1], + [$blob19, $filter28, 1], // Time-range for free-busy (61) - array($blob20, $filter29, -1), + [$blob20, $filter29, -1], // Time-range on property (62) - array($blob5, $filter30, 1), - array($blob3, $filter37, -1), - array($blob3, $filter30, 0), + [$blob5, $filter30, 1], + [$blob3, $filter37, -1], + [$blob3, $filter30, 0], // Time-range on alarm in vevent (65) - array($blob21, $filter31, 1), - array($blob21, $filter32, 0), - array($blob22, $filter31, 1), - array($blob22, $filter32, 0), - array($blob23, $filter31, 1), - array($blob23, $filter32, 0), - array($blob24, $filter31, 1), - array($blob24, $filter32, 0), - array($blob25, $filter31, 1), - array($blob25, $filter32, 0), - array($blob26, $filter31, 1), - array($blob26, $filter32, 0), + [$blob21, $filter31, 1], + [$blob21, $filter32, 0], + [$blob22, $filter31, 1], + [$blob22, $filter32, 0], + [$blob23, $filter31, 1], + [$blob23, $filter32, 0], + [$blob24, $filter31, 1], + [$blob24, $filter32, 0], + [$blob25, $filter31, 1], + [$blob25, $filter32, 0], + [$blob26, $filter31, 1], + [$blob26, $filter32, 0], // Time-range on alarm for vtodo (77) - array($blob27, $filter33, 1), - array($blob27, $filter34, 0), + [$blob27, $filter33, 1], + [$blob27, $filter34, 0], // Time-range on alarm for vjournal (79) - array($blob28, $filter35, -1), - array($blob28, $filter36, -1), + [$blob28, $filter35, -1], + [$blob28, $filter36, -1], // Time-range on alarm with duration (81) - array($blob29, $filter31, 1), - array($blob29, $filter32, 0), - array($blob30, $filter31, 0), - array($blob30, $filter32, 0), + [$blob29, $filter31, 1], + [$blob29, $filter32, 0], + [$blob30, $filter31, 0], + [$blob30, $filter32, 0], // Time-range with RRULE (85) - array($blob31, $filter20, 1), - array($blob32, $filter20, 0), + [$blob31, $filter20, 1], + [$blob32, $filter20, 0], // Bug reported on mailing list, related to all-day events (87) //array($blob33, $filter38, 1), // Event in timerange, but filtered alarm is in the far future (88). - array($blob34, $filter39, 0), - ); + [$blob34, $filter39, 0], + ]; } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarTest.php index ea744d2cf..df85b6ded 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/CalendarTest.php @@ -3,7 +3,6 @@ namespace Sabre\CalDAV; use Sabre\DAV\PropPatch; -use Sabre\DAVACL; require_once 'Sabre/CalDAV/TestUtil.php'; @@ -25,8 +24,6 @@ class CalendarTest extends \PHPUnit_Framework_TestCase { function setup() { - if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available'); - $this->backend = TestUtil::getBackend(); $this->calendars = $this->backend->getCalendarsForUser('principals/user1'); @@ -63,7 +60,7 @@ class CalendarTest extends \PHPUnit_Framework_TestCase { $this->assertEquals(true, $result); $calendars2 = $this->backend->getCalendarsForUser('principals/user1'); - $this->assertEquals('NewName',$calendars2[0]['{DAV:}displayname']); + $this->assertEquals('NewName', $calendars2[0]['{DAV:}displayname']); } @@ -72,15 +69,15 @@ class CalendarTest extends \PHPUnit_Framework_TestCase { */ function testGetProperties() { - $question = array( + $question = [ '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set', - ); + ]; $result = $this->calendar->getProperties($question); - foreach($question as $q) $this->assertArrayHasKey($q,$result); + foreach ($question as $q) $this->assertArrayHasKey($q, $result); - $this->assertEquals(array('VEVENT','VTODO'), $result['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']->getValue()); + $this->assertEquals(['VEVENT', 'VTODO'], $result['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']->getValue()); } @@ -100,7 +97,7 @@ class CalendarTest extends \PHPUnit_Framework_TestCase { function testGetChildren() { $children = $this->calendar->getChildren(); - $this->assertEquals(1,count($children)); + $this->assertEquals(1, count($children)); $this->assertTrue($children[0] instanceof CalendarObject); @@ -145,11 +142,11 @@ class CalendarTest extends \PHPUnit_Framework_TestCase { function testCreateFile() { - $file = fopen('php://memory','r+'); - fwrite($file,TestUtil::getTestCalendarData()); + $file = fopen('php://memory', 'r+'); + fwrite($file, TestUtil::getTestCalendarData()); rewind($file); - $this->calendar->createFile('hello',$file); + $this->calendar->createFile('hello', $file); $file = $this->calendar->getChild('hello'); $this->assertTrue($file instanceof CalendarObject); @@ -158,12 +155,12 @@ class CalendarTest extends \PHPUnit_Framework_TestCase { function testCreateFileNoSupportedComponents() { - $file = fopen('php://memory','r+'); - fwrite($file,TestUtil::getTestCalendarData()); + $file = fopen('php://memory', 'r+'); + fwrite($file, TestUtil::getTestCalendarData()); rewind($file); $calendar = new Calendar($this->backend, $this->calendars[1]); - $calendar->createFile('hello',$file); + $calendar->createFile('hello', $file); $file = $calendar->getChild('hello'); $this->assertTrue($file instanceof CalendarObject); @@ -180,7 +177,7 @@ class CalendarTest extends \PHPUnit_Framework_TestCase { function testGetOwner() { - $this->assertEquals('principals/user1',$this->calendar->getOwner()); + $this->assertEquals('principals/user1', $this->calendar->getOwner()); } @@ -192,98 +189,68 @@ class CalendarTest extends \PHPUnit_Framework_TestCase { function testGetACL() { - $expected = array( - array( + $expected = [ + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1/calendar-proxy-write', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1/calendar-proxy-read', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy', 'principal' => '{DAV:}authenticated', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}write', 'principal' => 'principals/user1', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}write', 'principal' => 'principals/user1/calendar-proxy-write', 'protected' => true, - ), - ); + ], + ]; $this->assertEquals($expected, $this->calendar->getACL()); } /** - * @expectedException Sabre\DAV\Exception\MethodNotAllowed + * @expectedException \Sabre\DAV\Exception\Forbidden */ function testSetACL() { - $this->calendar->setACL(array()); - - } - - function testGetSupportedPrivilegesSet() { - - $result = $this->calendar->getSupportedPrivilegeSet(); - - $this->assertEquals( - '{' . Plugin::NS_CALDAV . '}read-free-busy', - $result['aggregates'][0]['aggregates'][2]['privilege'] - ); + $this->calendar->setACL([]); } function testGetSyncToken() { - $this->assertEquals(2, $this->calendar->getSyncToken()); - - } - function testGetSyncToken2() { - - $calendar = new Calendar(new Backend\Mock([],[]), [ - '{DAV:}sync-token' => 2 - ]); - $this->assertEquals(2, $this->calendar->getSyncToken()); + $this->assertNull($this->calendar->getSyncToken()); } function testGetSyncTokenNoSyncSupport() { - $calendar = new Calendar(new Backend\Mock([],[]), []); + $calendar = new Calendar(new Backend\Mock([], []), []); $this->assertNull($calendar->getSyncToken()); } function testGetChanges() { - $this->assertEquals([ - 'syncToken' => 2, - 'modified' => [], - 'deleted' => [], - 'added' => ['UUID-2345'], - ], $this->calendar->getChanges(1, 1)); + $this->assertNull($this->calendar->getChanges(1, 1)); } - function testGetChangesNoSyncSupport() { - - $calendar = new Calendar(new Backend\Mock([],[]), []); - $this->assertNull($calendar->getChanges(1,null)); - - } } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/ExpandEventsDoubleEventsTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/ExpandEventsDoubleEventsTest.php index b64fb122a..3a22e03d4 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/ExpandEventsDoubleEventsTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/ExpandEventsDoubleEventsTest.php @@ -19,18 +19,18 @@ class ExpandEventsDoubleEventsTest extends \Sabre\DAVServerTest { protected $setupCalDAV = true; - protected $caldavCalendars = array( - array( - 'id' => 1, - 'name' => 'Calendar', + protected $caldavCalendars = [ + [ + 'id' => 1, + 'name' => 'Calendar', 'principaluri' => 'principals/user1', - 'uri' => 'calendar1', - ) - ); + 'uri' => 'calendar1', + ] + ]; - protected $caldavCalendarObjects = array( - 1 => array( - 'event.ics' => array( + protected $caldavCalendarObjects = [ + 1 => [ + 'event.ics' => [ 'calendardata' => 'BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT @@ -50,17 +50,17 @@ RECURRENCE-ID;TZID=Europe/Berlin:20120208T181500 END:VEVENT END:VCALENDAR ', - ), - ), - ); + ], + ], + ]; function testExpand() { $request = HTTP\Sapi::createFromServerArray([ - 'REQUEST_METHOD' => 'REPORT', + 'REQUEST_METHOD' => 'REPORT', 'HTTP_CONTENT_TYPE' => 'application/xml', - 'REQUEST_URI' => '/calendars/user1/calendar1', - 'HTTP_DEPTH' => '1', + 'REQUEST_URI' => '/calendars/user1/calendar1', + 'HTTP_DEPTH' => '1', ]); $request->setBody(' @@ -88,12 +88,12 @@ END:VCALENDAR $start = strpos($response->body, 'BEGIN:VCALENDAR'), strpos($response->body, 'END:VCALENDAR') - $start + 13 ); - $body = str_replace(' ','',$body); + $body = str_replace(' ', '', $body); $vObject = VObject\Reader::read($body); // We only expect 3 events - $this->assertEquals(3, count($vObject->VEVENT),'We got 6 events instead of 3. Output: ' . $body); + $this->assertEquals(3, count($vObject->VEVENT), 'We got 6 events instead of 3. Output: ' . $body); // TZID should be gone $this->assertFalse(isset($vObject->VEVENT->DTSTART['TZID'])); @@ -101,4 +101,3 @@ END:VCALENDAR } } - diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/FreeBusyReportTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/FreeBusyReportTest.php index 84f05f3c0..7a756774f 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/FreeBusyReportTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/FreeBusyReportTest.php @@ -3,7 +3,6 @@ namespace Sabre\CalDAV; use Sabre\DAV; -use Sabre\DAVACL; use Sabre\HTTP; require_once 'Sabre/CalDAV/Backend/Mock.php'; @@ -31,8 +30,8 @@ END:VEVENT END:VCALENDAR ics; - $obj2 = fopen('php://memory','r+'); - fwrite($obj2,<< [ 'obj1' => [ - 'calendarid' => 1, - 'uri' => 'event1.ics', + 'calendarid' => 1, + 'uri' => 'event1.ics', 'calendardata' => $obj1, ], 'obj2' => [ - 'calendarid' => 1, - 'uri' => 'event2.ics', + 'calendarid' => 1, + 'uri' => 'event2.ics', 'calendardata' => $obj2 ], 'obj3' => [ - 'calendarid' => 1, - 'uri' => 'event3.ics', + 'calendarid' => 1, + 'uri' => 'event3.ics', 'calendardata' => $obj3 ] ], @@ -76,9 +75,9 @@ ics; $caldavBackend = new Backend\Mock([], $calendarData); $calendar = new Calendar($caldavBackend, [ - 'id' => 1, - 'uri' => 'calendar', - 'principaluri' => 'principals/user1', + 'id' => 1, + 'uri' => 'calendar', + 'principaluri' => 'principals/user1', '{' . Plugin::NS_CALDAV . '}calendar-timezone' => "BEGIN:VCALENDAR\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nEND:VTIMEZONE\r\nEND:VCALENDAR", ]); @@ -105,13 +104,13 @@ ics; XML; $report = $this->server->xml->parse($reportXML, null, $rootElem); - $this->plugin->report($rootElem, $report); + $this->plugin->report($rootElem, $report, null); $this->assertEquals(200, $this->server->httpResponse->status); $this->assertEquals('text/calendar', $this->server->httpResponse->getHeader('Content-Type')); - $this->assertTrue(strpos($this->server->httpResponse->body, 'BEGIN:VFREEBUSY')!==false); - $this->assertTrue(strpos($this->server->httpResponse->body, '20111005T120000Z/20111005T130000Z')!==false); - $this->assertTrue(strpos($this->server->httpResponse->body, '20111006T100000Z/20111006T110000Z')!==false); + $this->assertTrue(strpos($this->server->httpResponse->body, 'BEGIN:VFREEBUSY') !== false); + $this->assertTrue(strpos($this->server->httpResponse->body, '20111005T120000Z/20111005T130000Z') !== false); + $this->assertTrue(strpos($this->server->httpResponse->body, '20111006T100000Z/20111006T110000Z') !== false); } @@ -127,7 +126,6 @@ XML; XML; $report = $this->server->xml->parse($reportXML, null, $rootElem); - $this->plugin->report($rootElem, $report); } @@ -136,9 +134,9 @@ XML; */ function testFreeBusyReportWrongNode() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_URI' => '/', - )); + ]); $this->server->httpRequest = $request; $reportXML = <<server->xml->parse($reportXML, null, $rootElem); - $this->plugin->report($rootElem, $report); + $this->plugin->report($rootElem, $report, null); } @@ -170,7 +168,7 @@ XML; XML; $report = $this->server->xml->parse($reportXML, null, $rootElem); - $this->plugin->report($rootElem, $report); + $this->plugin->report($rootElem, $report, null); } } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/GetEventsByTimerangeTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/GetEventsByTimerangeTest.php index c3c97e8f6..5fd8d29a1 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/GetEventsByTimerangeTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/GetEventsByTimerangeTest.php @@ -75,7 +75,7 @@ END:VCALENDAR $response = $this->request($request); - $this->assertTrue(strpos($response->body, 'BEGIN:VCALENDAR')!==false); + $this->assertTrue(strpos($response->body, 'BEGIN:VCALENDAR') !== false); } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/ICSExportPluginTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/ICSExportPluginTest.php index c123bd0c1..9719529fb 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/ICSExportPluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/ICSExportPluginTest.php @@ -7,657 +7,380 @@ use Sabre\HTTP; use Sabre\VObject; use Sabre\DAVACL; -require_once 'Sabre/CalDAV/TestUtil.php'; -require_once 'Sabre/HTTP/ResponseMock.php'; +class ICSExportPluginTest extends \Sabre\DAVServerTest { -class ICSExportPluginTest extends \PHPUnit_Framework_TestCase { + protected $setupCalDAV = true; + + protected $icsExportPlugin; function setUp() { - if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available'); + parent::setUp(); + $this->icsExportPlugin = new ICSExportPlugin(); + $this->server->addPlugin( + $this->icsExportPlugin + ); - } + $id = $this->caldavBackend->createCalendar( + 'principals/admin', + 'UUID-123467', + [ + '{DAV:}displayname' => 'Hello!', + '{http://apple.com/ns/ical/}calendar-color' => '#AA0000FF', + ] + ); - function testInit() { + $this->caldavBackend->createCalendarObject( + $id, + 'event-1', + <<caldavBackend->createCalendarObject( + $id, + 'todo-1', + <<addPlugin($p); - $this->assertEquals($p, $s->getPlugin('ics-export')); - $this->assertEquals('ics-export', $p->getPluginInfo()['name']); } - function testBeforeMethod() { + function testInit() { - $cbackend = TestUtil::getBackend(); - - $props = [ - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, - '{DAV:}displayname' => 'Hello!', - '{http://apple.com/ns/ical/}calendar-color' => '#AA0000FF', - ]; - $tree = [ - new Calendar($cbackend,$props), - ]; - - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export', - 'REQUEST_METHOD' => 'GET', - ]); - - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $this->assertFalse($p->httpGet($h, $s->httpResponse)); - - $this->assertEquals(200, $s->httpResponse->status); - $this->assertEquals([ - 'Content-Type' => ['text/calendar'], - ], $s->httpResponse->getHeaders()); - - $obj = VObject\Reader::read($s->httpResponse->body); - - $this->assertEquals(7,count($obj->children())); - $this->assertEquals(1,count($obj->VERSION)); - $this->assertEquals(1,count($obj->CALSCALE)); - $this->assertEquals(1,count($obj->PRODID)); - $this->assertTrue(strpos((string)$obj->PRODID, DAV\Version::VERSION)!==false); - $this->assertEquals(1,count($obj->VTIMEZONE)); - $this->assertEquals(1,count($obj->VEVENT)); - $this->assertEquals("Hello!", $obj->{"X-WR-CALNAME"}); - $this->assertEquals("#AA0000FF", $obj->{"X-APPLE-CALENDAR-COLOR"}); + $this->assertEquals( + $this->icsExportPlugin, + $this->server->getPlugin('ics-export') + ); + $this->assertEquals($this->icsExportPlugin, $this->server->getPlugin('ics-export')); + $this->assertEquals('ics-export', $this->icsExportPlugin->getPluginInfo()['name']); } - function testBeforeMethodNoVersion() { - if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available'); - $cbackend = TestUtil::getBackend(); + function testBeforeMethod() { - $props = [ - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, - ]; - $tree = [ - new Calendar($cbackend,$props), - ]; + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export' + ); - $p = new ICSExportPlugin(); + $response = $this->request($request); - $s = new DAV\Server($tree); + $this->assertEquals(200, $response->getStatus()); + $this->assertEquals('text/calendar', $response->getHeader('Content-Type')); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); + $obj = VObject\Reader::read($response->body); - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export', - 'REQUEST_METHOD' => 'GET', - ]); + $this->assertEquals(8, count($obj->children())); + $this->assertEquals(1, count($obj->VERSION)); + $this->assertEquals(1, count($obj->CALSCALE)); + $this->assertEquals(1, count($obj->PRODID)); + $this->assertTrue(strpos((string)$obj->PRODID, DAV\Version::VERSION) !== false); + $this->assertEquals(1, count($obj->VTIMEZONE)); + $this->assertEquals(1, count($obj->VEVENT)); + $this->assertEquals("Hello!", $obj->{"X-WR-CALNAME"}); + $this->assertEquals("#AA0000FF", $obj->{"X-APPLE-CALENDAR-COLOR"}); - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); + } + function testBeforeMethodNoVersion() { + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export' + ); DAV\Server::$exposeVersion = false; - $this->assertFalse($p->httpGet($h, $s->httpResponse)); + $response = $this->request($request); DAV\Server::$exposeVersion = true; - $this->assertEquals(200, $s->httpResponse->status); - $this->assertEquals([ - 'Content-Type' => ['text/calendar'], - ], $s->httpResponse->getHeaders()); + $this->assertEquals(200, $response->getStatus()); + $this->assertEquals('text/calendar', $response->getHeader('Content-Type')); - $obj = VObject\Reader::read($s->httpResponse->body); + $obj = VObject\Reader::read($response->body); - $this->assertEquals(5,count($obj->children())); - $this->assertEquals(1,count($obj->VERSION)); - $this->assertEquals(1,count($obj->CALSCALE)); - $this->assertEquals(1,count($obj->PRODID)); - $this->assertFalse(strpos((string)$obj->PRODID, DAV\Version::VERSION)!==false); - $this->assertEquals(1,count($obj->VTIMEZONE)); - $this->assertEquals(1,count($obj->VEVENT)); + $this->assertEquals(8, count($obj->children())); + $this->assertEquals(1, count($obj->VERSION)); + $this->assertEquals(1, count($obj->CALSCALE)); + $this->assertEquals(1, count($obj->PRODID)); + $this->assertFalse(strpos((string)$obj->PRODID, DAV\Version::VERSION) !== false); + $this->assertEquals(1, count($obj->VTIMEZONE)); + $this->assertEquals(1, count($obj->VEVENT)); } function testBeforeMethodNoExport() { - $p = new ICSExportPlugin(); - - $s = new DAV\Server(); - $s->addPlugin($p); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467', - 'REQUEST_METHOD' => 'GET', - ]); - $this->assertNull($p->httpGet($h, $s->httpResponse)); + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467' + ); + $response = new HTTP\Response(); + $this->assertNull($this->icsExportPlugin->httpGet($request, $response)); } function testACLIntegrationBlocked() { - $cbackend = TestUtil::getBackend(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, + $aclPlugin = new DAVACL\Plugin(); + $aclPlugin->allowUnauthenticatedAccess = false; + $this->server->addPlugin( + $aclPlugin ); - $tree = array( - new Calendar($cbackend,$props), - ); - - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - $s->addPlugin(new DAVACL\Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export', - ]); - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $p->httpGet($h, $s->httpResponse); + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export' + ); - // If the ACL system blocked this request, the effect will be that - // there's no response, because the calendar information could not be - // fetched. - $this->assertNull($s->httpResponse->getStatus()); + $this->request($request, 403); } function testACLIntegrationNotBlocked() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, + $aclPlugin = new DAVACL\Plugin(); + $aclPlugin->allowUnauthenticatedAccess = false; + $this->server->addPlugin( + $aclPlugin ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), + $this->server->addPlugin( + new Plugin() ); - $p = new ICSExportPlugin(); + $this->autoLogin('admin'); - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - $s->addPlugin(new DAVACL\Plugin()); - $s->addPlugin(new DAV\Auth\Plugin(new DAV\Auth\Backend\Mock(),'SabreDAV')); - - // Forcing login - $s->getPlugin('acl')->adminPrincipals = array('principals/admin'); - - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export', - 'REQUEST_METHOD' => 'GET', - ]); - - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $s->exec(); + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export' + ); - $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); - $this->assertEquals(array( - 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['text/calendar'], - ), $s->httpResponse->getHeaders()); + $response = $this->request($request, 200); + $this->assertEquals('text/calendar', $response->getHeader('Content-Type')); - $obj = VObject\Reader::read($s->httpResponse->body); + $obj = VObject\Reader::read($response->body); - $this->assertEquals(5,count($obj->children())); - $this->assertEquals(1,count($obj->VERSION)); - $this->assertEquals(1,count($obj->CALSCALE)); - $this->assertEquals(1,count($obj->PRODID)); - $this->assertEquals(1,count($obj->VTIMEZONE)); - $this->assertEquals(1,count($obj->VEVENT)); + $this->assertEquals(8, count($obj->children())); + $this->assertEquals(1, count($obj->VERSION)); + $this->assertEquals(1, count($obj->CALSCALE)); + $this->assertEquals(1, count($obj->PRODID)); + $this->assertTrue(strpos((string)$obj->PRODID, DAV\Version::VERSION) !== false); + $this->assertEquals(1, count($obj->VTIMEZONE)); + $this->assertEquals(1, count($obj->VEVENT)); } function testBadStartParam() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, - ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&start=foo' ); - - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&start=foo', - 'REQUEST_METHOD' => 'GET', - ]); - - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $s->exec(); - - $this->assertEquals(400, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); + $this->request($request, 400); } function testBadEndParam() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&end=foo' ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), - ); - - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&end=foo', - 'REQUEST_METHOD' => 'GET', - ]); - - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $s->exec(); - - $this->assertEquals(400, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); + $this->request($request, 400); } function testFilterStartEnd() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&start=1&end=2' ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), - ); - - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&start=1&end=2', - 'REQUEST_METHOD' => 'GET', - ]); + $response = $this->request($request, 200); - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); + $obj = VObject\Reader::read($response->getBody()); - $s->exec(); - - $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); - $obj = VObject\Reader::read($s->httpResponse->body); - - $this->assertEquals(0,count($obj->VTIMEZONE)); - $this->assertEquals(0,count($obj->VEVENT)); + $this->assertEquals(0, count($obj->VTIMEZONE)); + $this->assertEquals(0, count($obj->VEVENT)); } function testExpandNoStart() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&expand=1&end=2' ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), - ); - - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&expand=1&end=1', - 'REQUEST_METHOD' => 'GET', - ]); - - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $s->exec(); - - $this->assertEquals(400, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); + $this->request($request, 400); } function testExpand() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&start=1&end=2000000000&expand=1' ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), - ); - - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&start=1&end=2000000000&expand=1', - 'REQUEST_METHOD' => 'GET', - ]); + $response = $this->request($request, 200); - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); + $obj = VObject\Reader::read($response->getBody()); - $s->exec(); - - $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); - $obj = VObject\Reader::read($s->httpResponse->body); - - $this->assertEquals(0,count($obj->VTIMEZONE)); - $this->assertEquals(1,count($obj->VEVENT)); + $this->assertEquals(0, count($obj->VTIMEZONE)); + $this->assertEquals(1, count($obj->VEVENT)); } function testJCal() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export', + ['Accept' => 'application/calendar+json'] ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), - ); - - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export', - 'REQUEST_METHOD' => 'GET', - 'HTTP_ACCEPT' => 'application/calendar+json', - ]); - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $s->exec(); - - $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); - $this->assertEquals('application/calendar+json', $s->httpResponse->getHeader('Content-Type')); + $response = $this->request($request, 200); + $this->assertEquals('application/calendar+json', $response->getHeader('Content-Type')); } function testJCalInUrl() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, - ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&accept=jcal' ); - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&accept=jcal', - 'REQUEST_METHOD' => 'GET', - ]); - - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $s->exec(); - - $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); - $this->assertEquals('application/calendar+json', $s->httpResponse->getHeader('Content-Type')); + $response = $this->request($request, 200); + $this->assertEquals('application/calendar+json', $response->getHeader('Content-Type')); } function testNegotiateDefault() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, - ); - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export', + ['Accept' => 'text/plain'] ); - $p = new ICSExportPlugin(); - - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export', - 'REQUEST_METHOD' => 'GET', - 'HTTP_ACCEPT' => 'text/plain', - ]); - - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $s->exec(); - - $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); - $this->assertEquals('text/calendar', $s->httpResponse->getHeader('Content-Type')); + $response = $this->request($request, 200); + $this->assertEquals('text/calendar', $response->getHeader('Content-Type')); } function testFilterComponentVEVENT() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); - - $props = array( - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, - ); - // add a todo to the calendar (see /tests/Sabre/TestUtil) - $cbackend->createCalendarObject(1, 'UUID-3456', TestUtil::getTestTODO()); - - $tree = array( - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&componentType=VEVENT' ); - $p = new ICSExportPlugin(); + $response = $this->request($request, 200); - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); - - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&componentType=VEVENT', - 'REQUEST_METHOD' => 'GET', - ]); - - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); - - $s->exec(); - - $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); - $obj = VObject\Reader::read($s->httpResponse->body); - - $this->assertEquals(1,count($obj->VTIMEZONE)); - $this->assertEquals(1,count($obj->VEVENT)); - $this->assertEquals(0,count($obj->VTODO)); + $obj = VObject\Reader::read($response->body); + $this->assertEquals(1, count($obj->VTIMEZONE)); + $this->assertEquals(1, count($obj->VEVENT)); + $this->assertEquals(0, count($obj->VTODO)); } function testFilterComponentVTODO() { - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&componentType=VTODO' + ); - $props = [ - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, - ]; - // add a todo to the calendar (see /tests/Sabre/TestUtil) - $cbackend->createCalendarObject(1, 'UUID-3456', TestUtil::getTestTODO()); + $response = $this->request($request, 200); - $tree = [ - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), - ]; + $obj = VObject\Reader::read($response->body); - $p = new ICSExportPlugin(); + $this->assertEquals(0, count($obj->VTIMEZONE)); + $this->assertEquals(0, count($obj->VEVENT)); + $this->assertEquals(1, count($obj->VTODO)); - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); + } - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&componentType=VTODO', - 'REQUEST_METHOD' => 'GET', - ]); + function testFilterComponentBadComponent() { - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export&componentType=VVOODOO' + ); - $s->exec(); + $response = $this->request($request, 400); - $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); - $obj = VObject\Reader::read($s->httpResponse->body); + } - $this->assertEquals(0,count($obj->VTIMEZONE)); - $this->assertEquals(0,count($obj->VEVENT)); - $this->assertEquals(1,count($obj->VTODO)); + function testContentDisposition() { - } + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export' + ); - function testFilterComponentBadComponent() { + $response = $this->request($request, 200); + $this->assertEquals('text/calendar', $response->getHeader('Content-Type')); + $this->assertEquals( + 'attachment; filename="UUID-123467-' . date('Y-m-d') . '.ics"', + $response->getHeader('Content-Disposition') + ); - $cbackend = TestUtil::getBackend(); - $pbackend = new DAVACL\PrincipalBackend\Mock(); + } - $props = [ - 'uri'=>'UUID-123467', - 'principaluri' => 'admin', - 'id' => 1, - ]; - // add a todo to the calendar (see /tests/Sabre/TestUtil) - $cbackend->createCalendarObject(1, 'UUID-3456', TestUtil::getTestTODO()); + function testContentDispositionJson() { - $tree = [ - new Calendar($cbackend,$props), - new DAVACL\PrincipalCollection($pbackend), - ]; + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-123467?export', + ['Accept' => 'application/calendar+json'] + ); - $p = new ICSExportPlugin(); + $response = $this->request($request, 200); + $this->assertEquals('application/calendar+json', $response->getHeader('Content-Type')); + $this->assertEquals( + 'attachment; filename="UUID-123467-' . date('Y-m-d') . '.json"', + $response->getHeader('Content-Disposition') + ); - $s = new DAV\Server($tree); - $s->sapi = new HTTP\SapiMock(); - $s->addPlugin($p); - $s->addPlugin(new Plugin()); + } - $h = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/UUID-123467?export&componentType=VVOODOO', - 'REQUEST_METHOD' => 'GET', - ]); + function testContentDispositionBadChars() { - $s->httpRequest = $h; - $s->httpResponse = new HTTP\ResponseMock(); + $this->caldavBackend->createCalendar( + 'principals/admin', + 'UUID-b_ad"(ch)ars', + [ + '{DAV:}displayname' => 'Test bad characters', + '{http://apple.com/ns/ical/}calendar-color' => '#AA0000FF', + ] + ); - $s->exec(); + $request = new HTTP\Request( + 'GET', + '/calendars/admin/UUID-b_ad"(ch)ars?export', + ['Accept' => 'application/calendar+json'] + ); - $this->assertEquals(400, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body); + $response = $this->request($request, 200); + $this->assertEquals('application/calendar+json', $response->getHeader('Content-Type')); + $this->assertEquals( + 'attachment; filename="UUID-b_adchars-' . date('Y-m-d') . '.json"', + $response->getHeader('Content-Disposition') + ); } + } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue166Test.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue166Test.php index f925224f2..a1a9b7c04 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue166Test.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue166Test.php @@ -1,8 +1,8 @@ 'VCALENDAR', - 'comp-filters' => array( - array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filters = [ + 'name' => 'VCALENDAR', + 'comp-filters' => [ + [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2011-12-01'), 'end' => new \DateTime('2012-02-01'), - ), - ), - ), - 'prop-filters' => array(), + ], + ], + ], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => null, - ); + 'time-range' => null, + ]; $input = VObject\Reader::read($input); - $this->assertTrue($validator->validate($input,$filters)); + $this->assertTrue($validator->validate($input, $filters)); } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue172Test.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue172Test.php index ce6d364f6..e2b85c2bc 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue172Test.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue172Test.php @@ -1,8 +1,8 @@ 'VCALENDAR', - 'comp-filters' => array( - array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filters = [ + 'name' => 'VCALENDAR', + 'comp-filters' => [ + [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2012-01-18 21:00:00 GMT-08:00'), 'end' => new \DateTime('2012-01-18 21:00:00 GMT-08:00'), - ), - ), - ), - 'prop-filters' => array(), - ); + ], + ], + ], + 'prop-filters' => [], + ]; $input = VObject\Reader::read($input); - $this->assertTrue($validator->validate($input,$filters)); + $this->assertTrue($validator->validate($input, $filters)); } // Pacific Standard Time, translates to America/Los_Angeles (GMT-8 in January) @@ -65,24 +65,24 @@ END:VEVENT END:VCALENDAR HI; $validator = new CalendarQueryValidator(); - $filters = array( - 'name' => 'VCALENDAR', - 'comp-filters' => array( - array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filters = [ + 'name' => 'VCALENDAR', + 'comp-filters' => [ + [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2012-01-13 10:30:00 GMT-08:00'), 'end' => new \DateTime('2012-01-13 10:30:00 GMT-08:00'), - ), - ), - ), - 'prop-filters' => array(), - ); + ], + ], + ], + 'prop-filters' => [], + ]; $input = VObject\Reader::read($input); - $this->assertTrue($validator->validate($input,$filters)); + $this->assertTrue($validator->validate($input, $filters)); } // X-LIC-LOCATION, translates to America/Los_Angeles (GMT-8 in January) @@ -113,23 +113,23 @@ END:VEVENT END:VCALENDAR HI; $validator = new CalendarQueryValidator(); - $filters = array( - 'name' => 'VCALENDAR', - 'comp-filters' => array( - array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), + $filters = [ + 'name' => 'VCALENDAR', + 'comp-filters' => [ + [ + 'name' => 'VEVENT', + 'comp-filters' => [], + 'prop-filters' => [], 'is-not-defined' => false, - 'time-range' => array( + 'time-range' => [ 'start' => new \DateTime('2012-01-13 10:30:00 GMT-08:00'), 'end' => new \DateTime('2012-01-13 10:30:00 GMT-08:00'), - ), - ), - ), - 'prop-filters' => array(), - ); + ], + ], + ], + 'prop-filters' => [], + ]; $input = VObject\Reader::read($input); - $this->assertTrue($validator->validate($input,$filters)); + $this->assertTrue($validator->validate($input, $filters)); } } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue205Test.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue205Test.php index 4a53fcbe2..ce40a90b0 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue205Test.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue205Test.php @@ -1,6 +1,7 @@ 1, - 'name' => 'Calendar', + protected $caldavCalendars = [ + [ + 'id' => 1, + 'name' => 'Calendar', 'principaluri' => 'principals/user1', - 'uri' => 'calendar1', - ) - ); + 'uri' => 'calendar1', + ] + ]; - protected $caldavCalendarObjects = array( - 1 => array( - 'event.ics' => array( + protected $caldavCalendarObjects = [ + 1 => [ + 'event.ics' => [ 'calendardata' => 'BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT @@ -44,18 +45,18 @@ END:VALARM END:VEVENT END:VCALENDAR ', - ), - ), - ); + ], + ], + ]; function testIssue205() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'REPORT', + $request = HTTP\Sapi::createFromServerArray([ + 'REQUEST_METHOD' => 'REPORT', 'HTTP_CONTENT_TYPE' => 'application/xml', - 'REQUEST_URI' => '/calendars/user1/calendar1', - 'HTTP_DEPTH' => '1', - )); + 'REQUEST_URI' => '/calendars/user1/calendar1', + 'HTTP_DEPTH' => '1', + ]); $request->setBody(' @@ -87,7 +88,7 @@ END:VCALENDAR $start = strpos($response->body, 'BEGIN:VCALENDAR'), strpos($response->body, 'END:VCALENDAR') - $start + 13 ); - $body = str_replace(' ','',$body); + $body = str_replace(' ', '', $body); $vObject = VObject\Reader::read($body); diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue211Test.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue211Test.php index f291e5e57..950629fd8 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue211Test.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue211Test.php @@ -1,8 +1,8 @@ 1, - 'name' => 'Calendar', + protected $caldavCalendars = [ + [ + 'id' => 1, + 'name' => 'Calendar', 'principaluri' => 'principals/user1', - 'uri' => 'calendar1', - ) - ); + 'uri' => 'calendar1', + ] + ]; - protected $caldavCalendarObjects = array( - 1 => array( - 'event.ics' => array( + protected $caldavCalendarObjects = [ + 1 => [ + 'event.ics' => [ 'calendardata' => 'BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT @@ -49,18 +49,18 @@ END:VALARM END:VEVENT END:VCALENDAR ', - ), - ), - ); + ], + ], + ]; function testIssue211() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'REPORT', + $request = HTTP\Sapi::createFromServerArray([ + 'REQUEST_METHOD' => 'REPORT', 'HTTP_CONTENT_TYPE' => 'application/xml', - 'REQUEST_URI' => '/calendars/user1/calendar1', - 'HTTP_DEPTH' => '1', - )); + 'REQUEST_URI' => '/calendars/user1/calendar1', + 'HTTP_DEPTH' => '1', + ]); $request->setBody(' diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue220Test.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue220Test.php index 7b5dbfe63..c3c0b5b48 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue220Test.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue220Test.php @@ -15,18 +15,18 @@ class Issue220Test extends \Sabre\DAVServerTest { protected $setupCalDAV = true; - protected $caldavCalendars = array( - array( - 'id' => 1, - 'name' => 'Calendar', + protected $caldavCalendars = [ + [ + 'id' => 1, + 'name' => 'Calendar', 'principaluri' => 'principals/user1', - 'uri' => 'calendar1', - ) - ); + 'uri' => 'calendar1', + ] + ]; - protected $caldavCalendarObjects = array( - 1 => array( - 'event.ics' => array( + protected $caldavCalendarObjects = [ + 1 => [ + 'event.ics' => [ 'calendardata' => 'BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT @@ -59,18 +59,18 @@ UID:b64f14c5-dccc-4eda-947f-bdb1f763fbcd END:VEVENT END:VCALENDAR ', - ), - ), - ); + ], + ], + ]; function testIssue220() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'REPORT', + $request = HTTP\Sapi::createFromServerArray([ + 'REQUEST_METHOD' => 'REPORT', 'HTTP_CONTENT_TYPE' => 'application/xml', - 'REQUEST_URI' => '/calendars/user1/calendar1', - 'HTTP_DEPTH' => '1', - )); + 'REQUEST_URI' => '/calendars/user1/calendar1', + 'HTTP_DEPTH' => '1', + ]); $request->setBody(' diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue228Test.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue228Test.php index ccc6b303a..d0783701d 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Issue228Test.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Issue228Test.php @@ -1,6 +1,7 @@ 1, - 'name' => 'Calendar', + protected $caldavCalendars = [ + [ + 'id' => 1, + 'name' => 'Calendar', 'principaluri' => 'principals/user1', - 'uri' => 'calendar1', - ) - ); + 'uri' => 'calendar1', + ] + ]; - protected $caldavCalendarObjects = array( - 1 => array( - 'event.ics' => array( + protected $caldavCalendarObjects = [ + 1 => [ + 'event.ics' => [ 'calendardata' => 'BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT @@ -38,18 +39,18 @@ TRANSP:TRANSPARENT END:VEVENT END:VCALENDAR ', - ), - ), - ); + ], + ], + ]; function testIssue228() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'REPORT', + $request = HTTP\Sapi::createFromServerArray([ + 'REQUEST_METHOD' => 'REPORT', 'HTTP_CONTENT_TYPE' => 'application/xml', - 'REQUEST_URI' => '/calendars/user1/calendar1', - 'HTTP_DEPTH' => '1', - )); + 'REQUEST_URI' => '/calendars/user1/calendar1', + 'HTTP_DEPTH' => '1', + ]); $request->setBody(' diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Notifications/CollectionTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Notifications/CollectionTest.php index 68035184f..6585f85c3 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Notifications/CollectionTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Notifications/CollectionTest.php @@ -14,13 +14,13 @@ class CollectionTest extends \PHPUnit_Framework_TestCase { $this->principalUri = 'principals/user1'; - $this->notification = new CalDAV\Xml\Notification\SystemStatus(1,'"1"'); + $this->notification = new CalDAV\Xml\Notification\SystemStatus(1, '"1"'); - $this->caldavBackend = new CalDAV\Backend\MockSharing(array(),array(), array( - 'principals/user1' => array( + $this->caldavBackend = new CalDAV\Backend\MockSharing([], [], [ + 'principals/user1' => [ $this->notification - ) - )); + ] + ]); return new Collection($this->caldavBackend, $this->principalUri); @@ -31,9 +31,9 @@ class CollectionTest extends \PHPUnit_Framework_TestCase { $col = $this->getInstance(); $this->assertEquals('notifications', $col->getName()); - $this->assertEquals(array( + $this->assertEquals([ new Node($this->caldavBackend, $this->principalUri, $this->notification) - ), $col->getChildren()); + ], $col->getChildren()); } @@ -54,30 +54,25 @@ class CollectionTest extends \PHPUnit_Framework_TestCase { function testGetACL() { $col = $this->getInstance(); - $expected = array( - array( - 'privilege' => '{DAV:}read', - 'principal' => $this->principalUri, + $expected = [ + [ + 'privilege' => '{DAV:}all', + 'principal' => '{DAV:}owner', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', - 'principal' => $this->principalUri, - 'protected' => true, - ), - ); + ], + ]; $this->assertEquals($expected, $col->getACL()); } /** - * @expectedException Sabre\DAV\Exception\NotImplemented + * @expectedException \Sabre\DAV\Exception\Forbidden */ function testSetACL() { $col = $this->getInstance(); - $col->setACL(array()); + $col->setACL([]); } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Notifications/NodeTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Notifications/NodeTest.php index d546116fc..6c6e02da8 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Notifications/NodeTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Notifications/NodeTest.php @@ -13,7 +13,7 @@ class NodeTest extends \PHPUnit_Framework_TestCase { $principalUri = 'principals/user1'; - $this->systemStatus = new CalDAV\Xml\Notification\SystemStatus(1,'"1"'); + $this->systemStatus = new CalDAV\Xml\Notification\SystemStatus(1, '"1"'); $this->caldavBackend = new CalDAV\Backend\MockSharing([], [], [ 'principals/user1' => [ @@ -51,7 +51,7 @@ class NodeTest extends \PHPUnit_Framework_TestCase { $node = $this->getInstance(); $node->delete(); - $this->assertEquals(array(), $this->caldavBackend->getNotificationsForPrincipal('principals/user1')); + $this->assertEquals([], $this->caldavBackend->getNotificationsForPrincipal('principals/user1')); } @@ -65,30 +65,25 @@ class NodeTest extends \PHPUnit_Framework_TestCase { function testGetACL() { $node = $this->getInstance(); - $expected = array( - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/user1', + $expected = [ + [ + 'privilege' => '{DAV:}all', + 'principal' => '{DAV:}owner', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', - 'principal' => 'principals/user1', - 'protected' => true, - ), - ); + ], + ]; $this->assertEquals($expected, $node->getACL()); } /** - * @expectedException Sabre\DAV\Exception\NotImplemented + * @expectedException \Sabre\DAV\Exception\Forbidden */ function testSetACL() { $node = $this->getInstance(); - $node->setACL(array()); + $node->setACL([]); } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/PluginTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/PluginTest.php index 138012ffa..8d538dee5 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/PluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/PluginTest.php @@ -81,12 +81,14 @@ class PluginTest extends \PHPUnit_Framework_TestCase { $this->server->addPlugin($this->plugin); // Adding ACL plugin - $this->server->addPlugin(new DAVACL\Plugin()); + $aclPlugin = new DAVACL\Plugin(); + $aclPlugin->allowUnauthenticatedAccess = false; + $this->server->addPlugin($aclPlugin); // Adding Auth plugin, and ensuring that we are logged in. $authBackend = new DAV\Auth\Backend\Mock(); $authBackend->setPrincipal('principals/user1'); - $authPlugin = new DAV\Auth\Plugin($authBackend, 'SabreDAV'); + $authPlugin = new DAV\Auth\Plugin($authBackend); $authPlugin->beforeMethod(new \Sabre\HTTP\Request(), new \Sabre\HTTP\Response()); $this->server->addPlugin($authPlugin); @@ -480,8 +482,9 @@ END:VCALENDAR'; $this->assertInstanceOf('\\Sabre\\DAV\\Xml\\Property\\SupportedReportSet', $prop); $value = [ '{DAV:}expand-property', + '{DAV:}principal-match', '{DAV:}principal-property-search', - '{DAV:}principal-search-property-set' + '{DAV:}principal-search-property-set', ]; $this->assertEquals($value, $prop->getValue()); @@ -508,6 +511,7 @@ END:VCALENDAR'; '{urn:ietf:params:xml:ns:caldav}calendar-query', '{urn:ietf:params:xml:ns:caldav}free-busy-query', '{DAV:}expand-property', + '{DAV:}principal-match', '{DAV:}principal-property-search', '{DAV:}principal-search-property-set' ]; @@ -533,6 +537,7 @@ END:VCALENDAR'; $value = [ '{DAV:}sync-collection', '{DAV:}expand-property', + '{DAV:}principal-match', '{DAV:}principal-property-search', '{DAV:}principal-search-property-set', ]; @@ -719,7 +724,7 @@ XML; ''; $request = new HTTP\Request('REPORT', '/calendars/user1/UUID-123467', [ - 'Depth' => '0', + 'Depth' => '0', 'User-Agent' => 'MSFT-WP/8.10.14219 (gzip)', ]); diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/CollectionTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/CollectionTest.php index 625f64211..23c248825 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/CollectionTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/CollectionTest.php @@ -1,6 +1,7 @@ getChildForPrincipal(array( + $r = $col->getChildForPrincipal([ 'uri' => 'principals/admin', - )); + ]); $this->assertInstanceOf('Sabre\\CalDAV\\Principal\\User', $r); } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/ProxyReadTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/ProxyReadTest.php index 1ee999a92..fe07f0131 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/ProxyReadTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/ProxyReadTest.php @@ -1,6 +1,7 @@ 'principal/user', - )); + ]); $this->backend = $backend; return $principal; @@ -61,7 +62,7 @@ class ProxyReadTest extends \PHPUnit_Framework_TestCase { function testGetAlternateUriSet() { $i = $this->getInstance(); - $this->assertEquals(array(), $i->getAlternateUriSet()); + $this->assertEquals([], $i->getAlternateUriSet()); } @@ -75,25 +76,25 @@ class ProxyReadTest extends \PHPUnit_Framework_TestCase { function testGetGroupMemberSet() { $i = $this->getInstance(); - $this->assertEquals(array(), $i->getGroupMemberSet()); + $this->assertEquals([], $i->getGroupMemberSet()); } function testGetGroupMembership() { $i = $this->getInstance(); - $this->assertEquals(array(), $i->getGroupMembership()); + $this->assertEquals([], $i->getGroupMembership()); } function testSetGroupMemberSet() { $i = $this->getInstance(); - $i->setGroupMemberSet(array('principals/foo')); + $i->setGroupMemberSet(['principals/foo']); - $expected = array( - $i->getPrincipalUrl() => array('principals/foo') - ); + $expected = [ + $i->getPrincipalUrl() => ['principals/foo'] + ]; $this->assertEquals($expected, $this->backend->groupMembers); diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/ProxyWriteTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/ProxyWriteTest.php index c0186ff0d..6cdb9b30e 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/ProxyWriteTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/ProxyWriteTest.php @@ -1,6 +1,7 @@ 'principal/user', - )); + ]); $this->backend = $backend; return $principal; diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/UserTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/UserTest.php index 37b5eae97..420bb3b1a 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/UserTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Principal/UserTest.php @@ -1,6 +1,7 @@ addPrincipal(array( + $backend->addPrincipal([ 'uri' => 'principals/user/calendar-proxy-read', - )); - $backend->addPrincipal(array( + ]); + $backend->addPrincipal([ 'uri' => 'principals/user/calendar-proxy-write', - )); - $backend->addPrincipal(array( + ]); + $backend->addPrincipal([ 'uri' => 'principals/user/random', - )); - return new User($backend, array( + ]); + return new User($backend, [ 'uri' => 'principals/user', - )); + ]); } @@ -100,23 +101,23 @@ class UserTest extends \PHPUnit_Framework_TestCase { function testGetACL() { - $expected = array( - array( - 'privilege' => '{DAV:}read', - 'principal' => '{DAV:}authenticated', + $expected = [ + [ + 'privilege' => '{DAV:}all', + 'principal' => '{DAV:}owner', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user/calendar-proxy-read', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user/calendar-proxy-write', 'protected' => true, - ), - ); + ], + ]; $u = $this->getInstance(); $this->assertEquals($expected, $u->getACL()); diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Schedule/OutboxTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Schedule/OutboxTest.php index 933c7157b..04d4b1237 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Schedule/OutboxTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Schedule/OutboxTest.php @@ -1,6 +1,7 @@ assertEquals('outbox', $outbox->getName()); - $this->assertEquals(array(), $outbox->getChildren()); + $this->assertEquals([], $outbox->getChildren()); $this->assertEquals('principals/user1', $outbox->getOwner()); $this->assertEquals(null, $outbox->getGroup()); - $this->assertEquals(array( - array( - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy', - 'principal' => 'principals/user1', - 'protected' => true, - ), - - array( - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent', + $this->assertEquals([ + [ + 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-send', 'principal' => 'principals/user1', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1', 'protected' => true, - ), - array( - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy', + ], + [ + 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-send', 'principal' => 'principals/user1/calendar-proxy-write', 'protected' => true, - ), - array( - 'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent', - 'principal' => 'principals/user1/calendar-proxy-write', - 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1/calendar-proxy-read', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1/calendar-proxy-write', 'protected' => true, - ), - ), $outbox->getACL()); - - $ok = false; - try { - $outbox->setACL(array()); - } catch (DAV\Exception\MethodNotAllowed $e) { - $ok = true; - } - if (!$ok) { - $this->fail('Exception was not emitted'); - } - - } - - function testGetSupportedPrivilegeSet() { - - $outbox = new Outbox('principals/user1'); - $r = $outbox->getSupportedPrivilegeSet(); - - $ok = 0; - foreach($r['aggregates'] as $priv) { - - if ($priv['privilege'] == '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy') { - $ok++; - } - if ($priv['privilege'] == '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent') { - $ok++; - } - } - - $this->assertEquals(2, $ok, "We're missing one or more privileges"); + ], + ], $outbox->getACL()); } - } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/SharedCalendarTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/SharedCalendarTest.php index 337b658f4..f71c19523 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/SharedCalendarTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/SharedCalendarTest.php @@ -2,7 +2,8 @@ namespace Sabre\CalDAV; -use Sabre\DAVACL; +use Sabre\DAV\Sharing; +use Sabre\DAV\Xml\Element\Sharee; class SharedCalendarTest extends \PHPUnit_Framework_TestCase { @@ -11,96 +12,95 @@ class SharedCalendarTest extends \PHPUnit_Framework_TestCase { function getInstance(array $props = null) { if (is_null($props)) { - $props = array( - 'id' => 1, + $props = [ + 'id' => 1, '{http://calendarserver.org/ns/}shared-url' => 'calendars/owner/original', - '{http://sabredav.org/ns}owner-principal' => 'principals/owner', - '{http://sabredav.org/ns}read-only' => false, - 'principaluri' => 'principals/sharee', - ); + '{http://sabredav.org/ns}owner-principal' => 'principals/owner', + '{http://sabredav.org/ns}read-only' => false, + 'share-access' => Sharing\Plugin::ACCESS_READWRITE, + 'principaluri' => 'principals/sharee', + ]; } $this->backend = new Backend\MockSharing( - array($props), - array(), - array() + [$props], + [], + [] ); - $this->backend->updateShares(1, array( - array( - 'href' => 'mailto:removeme@example.org', - 'commonName' => 'To be removed', - 'readOnly' => true, - ), - ), array()); + + $sharee = new Sharee(); + $sharee->href = 'mailto:removeme@example.org'; + $sharee->properties['{DAV:}displayname'] = 'To be removed'; + $sharee->access = Sharing\Plugin::ACCESS_READ; + $this->backend->updateInvites(1, [$sharee]); return new SharedCalendar($this->backend, $props); } - function testGetSharedUrl() { - $this->assertEquals('calendars/owner/original', $this->getInstance()->getSharedUrl()); - } + function testGetInvites() { - function testGetShares() { + $sharee = new Sharee(); + $sharee->href = 'mailto:removeme@example.org'; + $sharee->properties['{DAV:}displayname'] = 'To be removed'; + $sharee->access = Sharing\Plugin::ACCESS_READ; + $sharee->inviteStatus = Sharing\Plugin::INVITE_NORESPONSE; - $this->assertEquals(array(array( - 'href' => 'mailto:removeme@example.org', - 'commonName' => 'To be removed', - 'readOnly' => true, - 'status' => SharingPlugin::STATUS_NORESPONSE, - )), $this->getInstance()->getShares()); + $this->assertEquals( + [$sharee], + $this->getInstance()->getInvites() + ); } function testGetOwner() { - $this->assertEquals('principals/owner', $this->getInstance()->getOwner()); + $this->assertEquals('principals/sharee', $this->getInstance()->getOwner()); } function testGetACL() { - $expected = array( - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner', + $expected = [ + [ + 'privilege' => '{DAV:}write', + 'principal' => 'principals/sharee', 'protected' => true, - ), - - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner/calendar-proxy-write', + ], + [ + 'privilege' => '{DAV:}write', + 'principal' => 'principals/sharee/calendar-proxy-write', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner/calendar-proxy-read', + ], + [ + 'privilege' => '{DAV:}write-properties', + 'principal' => 'principals/sharee', 'protected' => true, - ), - array( - 'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy', - 'principal' => '{DAV:}authenticated', + ], + [ + 'privilege' => '{DAV:}write-properties', + 'principal' => 'principals/sharee/calendar-proxy-write', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', - 'principal' => 'principals/owner', + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => 'principals/sharee', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', - 'principal' => 'principals/owner/calendar-proxy-write', + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => 'principals/sharee/calendar-proxy-read', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', - 'principal' => 'principals/sharee', + 'principal' => 'principals/sharee/calendar-proxy-write', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', - 'principal' => 'principals/sharee', + ], + [ + 'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy', + 'principal' => '{DAV:}authenticated', 'protected' => true, - ), - ); + ], + ]; $this->assertEquals($expected, $this->getInstance()->getACL()); @@ -108,96 +108,69 @@ class SharedCalendarTest extends \PHPUnit_Framework_TestCase { function testGetChildACL() { - $expected = array( - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner', - 'protected' => true, - ), - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner/calendar-proxy-write', - 'protected' => true, - ), - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner/calendar-proxy-read', - 'protected' => true, - ), - array( + $expected = [ + [ 'privilege' => '{DAV:}write', - 'principal' => 'principals/owner', + 'principal' => 'principals/sharee', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}write', - 'principal' => 'principals/owner/calendar-proxy-write', + 'principal' => 'principals/sharee/calendar-proxy-write', 'protected' => true, - ), - array( + ], + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/sharee', 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', - 'principal' => 'principals/sharee', + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => 'principals/sharee/calendar-proxy-write', 'protected' => true, - ), - ); + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => 'principals/sharee/calendar-proxy-read', + 'protected' => true, + ], + + ]; $this->assertEquals($expected, $this->getInstance()->getChildACL()); } - function testGetChildACLReadOnly() { + function testUpdateInvites() { - $expected = array( - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner', - 'protected' => true, - ), - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner/calendar-proxy-write', - 'protected' => true, - ), - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/owner/calendar-proxy-read', - 'protected' => true, - ), - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/sharee', - 'protected' => true, - ), - ); + $instance = $this->getInstance(); + $newSharees = [ + new Sharee(), + new Sharee() + ]; + $newSharees[0]->href = 'mailto:test@example.org'; + $newSharees[0]->properties['{DAV:}displayname'] = 'Foo Bar'; + $newSharees[0]->comment = 'Booh'; + $newSharees[0]->access = Sharing\Plugin::ACCESS_READWRITE; - $props = array( - 'id' => 1, - '{http://calendarserver.org/ns/}shared-url' => 'calendars/owner/original', - '{http://sabredav.org/ns}owner-principal' => 'principals/owner', - '{http://sabredav.org/ns}read-only' => true, - 'principaluri' => 'principals/sharee', - ); - $this->assertEquals($expected, $this->getInstance($props)->getChildACL()); + $newSharees[1]->href = 'mailto:removeme@example.org'; + $newSharees[1]->access = Sharing\Plugin::ACCESS_NOACCESS; + + $instance->updateInvites($newSharees); + + $expected = [ + clone $newSharees[0] + ]; + $expected[0]->inviteStatus = Sharing\Plugin::INVITE_NORESPONSE; + $this->assertEquals($expected, $instance->getInvites()); } - /** - * @expectedException InvalidArgumentException - */ - public function testCreateInstanceMissingArg() { + function testPublish() { - $this->getInstance(array( - 'id' => 1, - '{http://calendarserver.org/ns/}shared-url' => 'calendars/owner/original', - '{http://sabredav.org/ns}read-only' => false, - 'principaluri' => 'principals/sharee', - )); + $instance = $this->getInstance(); + $this->assertNull($instance->setPublishStatus(true)); + $this->assertNull($instance->setPublishStatus(false)); } - } diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/SharingPluginTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/SharingPluginTest.php index b4270da7d..6e9e88419 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/SharingPluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/SharingPluginTest.php @@ -3,6 +3,7 @@ namespace Sabre\CalDAV; use Sabre\DAV; +use Sabre\DAV\Xml\Element\Sharee; use Sabre\HTTP; class SharingPluginTest extends \Sabre\DAVServerTest { @@ -14,31 +15,28 @@ class SharingPluginTest extends \Sabre\DAVServerTest { function setUp() { - $this->caldavCalendars = array( - array( + $this->caldavCalendars = [ + [ 'principaluri' => 'principals/user1', - 'id' => 1, - 'uri' => 'cal1', - ), - array( + 'id' => 1, + 'uri' => 'cal1', + ], + [ 'principaluri' => 'principals/user1', - 'id' => 2, - 'uri' => 'cal2', - '{' . Plugin::NS_CALENDARSERVER . '}shared-url' => 'calendars/user1/cal2', - '{http://sabredav.org/ns}owner-principal' => 'principals/user2', - '{http://sabredav.org/ns}read-only' => 'true', - ), - array( + 'id' => 2, + 'uri' => 'cal2', + 'share-access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE, + ], + [ 'principaluri' => 'principals/user1', - 'id' => 3, - 'uri' => 'cal3', - ), - ); + 'id' => 3, + 'uri' => 'cal3', + ], + ]; parent::setUp(); // Making the logged in user an admin, for full access: - $this->aclPlugin->adminPrincipals[] = 'principals/user1'; $this->aclPlugin->adminPrincipals[] = 'principals/user2'; } @@ -53,9 +51,21 @@ class SharingPluginTest extends \Sabre\DAVServerTest { } + /** + * @expectedException \LogicException + */ + function testSetupWithoutCoreSharingPlugin() { + + $server = new DAV\Server(); + $server->addPlugin( + new SharingPlugin() + ); + + } + function testGetFeatures() { - $this->assertEquals(array('calendarserver-sharing'), $this->caldavSharingPlugin->getFeatures()); + $this->assertEquals(['calendarserver-sharing'], $this->caldavSharingPlugin->getFeatures()); } @@ -63,10 +73,10 @@ class SharingPluginTest extends \Sabre\DAVServerTest { // Forcing the server to authenticate: $this->authPlugin->beforeMethod(new HTTP\Request(), new HTTP\Response()); - $props = $this->server->getProperties('calendars/user1/cal1', array( + $props = $this->server->getProperties('calendars/user1/cal1', [ '{' . Plugin::NS_CALENDARSERVER . '}invite', '{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', - )); + ]); $this->assertInstanceOf('Sabre\\CalDAV\\Xml\\Property\\Invite', $props['{' . Plugin::NS_CALENDARSERVER . '}invite']); $this->assertInstanceOf('Sabre\\CalDAV\\Xml\\Property\\AllowedSharingModes', $props['{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes']); @@ -75,56 +85,55 @@ class SharingPluginTest extends \Sabre\DAVServerTest { function testBeforeGetSharedCalendar() { - $props = $this->server->getProperties('calendars/user1/cal2', array( + $props = $this->server->getProperties('calendars/user1/cal2', [ '{' . Plugin::NS_CALENDARSERVER . '}shared-url', '{' . Plugin::NS_CALENDARSERVER . '}invite', - )); + ]); $this->assertInstanceOf('Sabre\\CalDAV\\Xml\\Property\\Invite', $props['{' . Plugin::NS_CALENDARSERVER . '}invite']); - $this->assertInstanceOf('Sabre\\DAV\\Xml\\Property\\Href', $props['{' . Plugin::NS_CALENDARSERVER . '}shared-url']); + //$this->assertInstanceOf('Sabre\\DAV\\Xml\\Property\\Href', $props['{' . Plugin::NS_CALENDARSERVER . '}shared-url']); } - function testUpdateProperties() { + function testUpdateResourceType() { - $this->caldavBackend->updateShares(1, - array( - array( + $this->caldavBackend->updateInvites(1, + [ + new Sharee([ 'href' => 'mailto:joe@example.org', - ), - ), - array() + ]) + ] ); - $result = $this->server->updateProperties('calendars/user1/cal1', array( + $result = $this->server->updateProperties('calendars/user1/cal1', [ '{DAV:}resourcetype' => new DAV\Xml\Property\ResourceType(['{DAV:}collection']) - )); + ]); $this->assertEquals([ '{DAV:}resourcetype' => 200 ], $result); - $this->assertEquals(0, count($this->caldavBackend->getShares(1))); + $this->assertEquals(0, count($this->caldavBackend->getInvites(1))); } function testUpdatePropertiesPassThru() { - $result = $this->server->updateProperties('calendars/user1/cal3', array( + $result = $this->server->updateProperties('calendars/user1/cal3', [ '{DAV:}foo' => 'bar', - )); + ]); - $this->assertEquals(array( - '{DAV:}foo' => 403, - ), $result); + $this->assertEquals([ + '{DAV:}foo' => 200, + ], $result); } function testUnknownMethodNoPOST() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PATCH', 'REQUEST_URI' => '/', - )); + ]); $response = $this->request($request); @@ -134,11 +143,11 @@ class SharingPluginTest extends \Sabre\DAVServerTest { function testUnknownMethodNoXML() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'POST', 'REQUEST_URI' => '/', 'CONTENT_TYPE' => 'text/plain', - )); + ]); $response = $this->request($request); @@ -148,11 +157,11 @@ class SharingPluginTest extends \Sabre\DAVServerTest { function testUnknownMethodNoNode() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'POST', 'REQUEST_URI' => '/foo', 'CONTENT_TYPE' => 'text/xml', - )); + ]); $response = $this->request($request); @@ -162,11 +171,7 @@ class SharingPluginTest extends \Sabre\DAVServerTest { function testShareRequest() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/calendars/user1/cal1', - 'CONTENT_TYPE' => 'text/xml', - )); + $request = new HTTP\Request('POST', '/calendars/user1/cal1', ['Content-Type' => 'text/xml']); $xml = << @@ -184,19 +189,28 @@ RRR; $request->setBody($xml); - $response = $this->request($request); - $this->assertEquals(200, $response->status, $response->body); + $response = $this->request($request, 200); + + $this->assertEquals( + [ + new Sharee([ + 'href' => 'mailto:joe@example.org', + 'properties' => [ + '{DAV:}displayname' => 'Joe Shmoe', + ], + 'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE, + 'inviteStatus' => \Sabre\DAV\Sharing\Plugin::INVITE_NORESPONSE, + 'comment' => '', + ]), + ], + $this->caldavBackend->getInvites(1) + ); - $this->assertEquals(array(array( - 'href' => 'mailto:joe@example.org', - 'commonName' => 'Joe Shmoe', - 'readOnly' => false, - 'status' => SharingPlugin::STATUS_NORESPONSE, - 'summary' => '', - )), $this->caldavBackend->getShares(1)); + // Wiping out tree cache + $this->server->tree->markDirty(''); // Verifying that the calendar is now marked shared. - $props = $this->server->getProperties('calendars/user1/cal1', array('{DAV:}resourcetype')); + $props = $this->server->getProperties('calendars/user1/cal1', ['{DAV:}resourcetype']); $this->assertTrue( $props['{DAV:}resourcetype']->is('{http://calendarserver.org/ns/}shared-owner') ); @@ -205,11 +219,11 @@ RRR; function testShareRequestNoShareableCalendar() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/calendars/user1/cal2', - 'CONTENT_TYPE' => 'text/xml', - )); + $request = new HTTP\Request( + 'POST', + '/calendars/user1/cal2', + ['Content-Type' => 'text/xml'] + ); $xml = ' @@ -226,18 +240,17 @@ RRR; $request->setBody($xml); - $response = $this->request($request); - $this->assertEquals(501, $response->status, $response->body); + $response = $this->request($request, 403); } function testInviteReply() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'POST', 'REQUEST_URI' => '/calendars/user1', 'CONTENT_TYPE' => 'text/xml', - )); + ]); $xml = ' @@ -254,11 +267,11 @@ RRR; function testInviteBadXML() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'POST', 'REQUEST_URI' => '/calendars/user1', 'CONTENT_TYPE' => 'text/xml', - )); + ]); $xml = ' @@ -272,11 +285,11 @@ RRR; function testInviteWrongUrl() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'POST', 'REQUEST_URI' => '/calendars/user1/cal1', 'CONTENT_TYPE' => 'text/xml', - )); + ]); $xml = ' @@ -295,11 +308,7 @@ RRR; function testPublish() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/calendars/user1/cal1', - 'CONTENT_TYPE' => 'text/xml', - )); + $request = new HTTP\Request('POST', '/calendars/user1/cal1', ['Content-Type' => 'text/xml']); $xml = ' @@ -312,13 +321,14 @@ RRR; } + function testUnpublish() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/calendars/user1/cal1', - 'CONTENT_TYPE' => 'text/xml', - )); + $request = new HTTP\Request( + 'POST', + '/calendars/user1/cal1', + ['Content-Type' => 'text/xml'] + ); $xml = ' @@ -333,49 +343,46 @@ RRR; function testPublishWrongUrl() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/calendars/user1/cal2', - 'CONTENT_TYPE' => 'text/xml', - )); + $request = new HTTP\Request( + 'POST', + '/calendars/user1', + ['Content-Type' => 'text/xml'] + ); $xml = ' '; $request->setBody($xml); - - $response = $this->request($request); - $this->assertEquals(501, $response->status, $response->body); + $this->request($request, 501); } function testUnpublishWrongUrl() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/calendars/user1/cal2', - 'CONTENT_TYPE' => 'text/xml', - )); - + $request = new HTTP\Request( + 'POST', + '/calendars/user1', + ['Content-Type' => 'text/xml'] + ); $xml = ' '; $request->setBody($xml); - $response = $this->request($request); - $this->assertEquals(501, $response->status, $response->body); + $this->request($request, 501); } function testUnknownXmlDoc() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/calendars/user1/cal2', - 'CONTENT_TYPE' => 'text/xml', - )); + + $request = new HTTP\Request( + 'POST', + '/calendars/user1/cal2', + ['Content-Type' => 'text/xml'] + ); $xml = ' '; diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/TestUtil.php b/vendor/sabre/dav/tests/Sabre/CalDAV/TestUtil.php index 19acea200..673d39c0a 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/TestUtil.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/TestUtil.php @@ -6,48 +6,29 @@ class TestUtil { static function getBackend() { - $backend = new Backend\PDO(self::getSQLiteDB()); - return $backend; - - } - - static function getSQLiteDB() { - - if (file_exists(SABRE_TEMPDIR . '/testdb.sqlite')) - unlink(SABRE_TEMPDIR . '/testdb.sqlite'); - - $pdo = new \PDO('sqlite:' . SABRE_TEMPDIR . '/testdb.sqlite'); - $pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); - - // Yup this is definitely not 'fool proof', but good enough for now. - $queries = explode(';', file_get_contents(__DIR__ . '/../../../examples/sql/sqlite.calendars.sql')); - foreach($queries as $query) { - $pdo->exec($query); - } - // Inserting events through a backend class. - $backend = new Backend\PDO($pdo); + $backend = new Backend\Mock(); $calendarId = $backend->createCalendar( 'principals/user1', 'UUID-123467', - array( - '{DAV:}displayname' => 'user1 calendar', + [ + '{DAV:}displayname' => 'user1 calendar', '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar description', - '{http://apple.com/ns/ical/}calendar-order' => '1', - '{http://apple.com/ns/ical/}calendar-color' => '#FF0000', - ) + '{http://apple.com/ns/ical/}calendar-order' => '1', + '{http://apple.com/ns/ical/}calendar-color' => '#FF0000', + ] ); $backend->createCalendar( 'principals/user1', 'UUID-123468', - array( - '{DAV:}displayname' => 'user1 calendar2', + [ + '{DAV:}displayname' => 'user1 calendar2', '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar description', - '{http://apple.com/ns/ical/}calendar-order' => '1', - '{http://apple.com/ns/ical/}calendar-color' => '#FF0000', - ) + '{http://apple.com/ns/ical/}calendar-order' => '1', + '{http://apple.com/ns/ical/}calendar-color' => '#FF0000', + ] ); $backend->createCalendarObject($calendarId, 'UUID-2345', self::getTestCalendarData()); - return $pdo; + return $backend; } @@ -80,37 +61,37 @@ TRANSP:TRANSPARENT SUMMARY:Something here DTSTAMP:20100228T130202Z'; - switch($type) { + switch ($type) { case 1 : - $calendarData.="\nDTSTART;TZID=Asia/Seoul:20100223T060000\nDTEND;TZID=Asia/Seoul:20100223T070000\n"; + $calendarData .= "\nDTSTART;TZID=Asia/Seoul:20100223T060000\nDTEND;TZID=Asia/Seoul:20100223T070000\n"; break; case 2 : - $calendarData.="\nDTSTART:20100223T060000\nDTEND:20100223T070000\n"; + $calendarData .= "\nDTSTART:20100223T060000\nDTEND:20100223T070000\n"; break; case 3 : - $calendarData.="\nDTSTART;VALUE=DATE:20100223\nDTEND;VALUE=DATE:20100223\n"; + $calendarData .= "\nDTSTART;VALUE=DATE:20100223\nDTEND;VALUE=DATE:20100223\n"; break; case 4 : - $calendarData.="\nDTSTART;TZID=Asia/Seoul:20100223T060000\nDURATION:PT1H\n"; + $calendarData .= "\nDTSTART;TZID=Asia/Seoul:20100223T060000\nDURATION:PT1H\n"; break; case 5 : - $calendarData.="\nDTSTART;TZID=Asia/Seoul:20100223T060000\nDURATION:-P5D\n"; + $calendarData .= "\nDTSTART;TZID=Asia/Seoul:20100223T060000\nDURATION:-P5D\n"; break; case 6 : - $calendarData.="\nDTSTART;VALUE=DATE:20100223\n"; + $calendarData .= "\nDTSTART;VALUE=DATE:20100223\n"; break; case 7 : - $calendarData.="\nDTSTART;VALUE=DATETIME:20100223T060000\n"; + $calendarData .= "\nDTSTART;VALUE=DATETIME:20100223T060000\n"; break; // No DTSTART, so intentionally broken case 'X' : - $calendarData.="\n"; + $calendarData .= "\n"; break; } - $calendarData.='ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:lisa@example.com + $calendarData .= 'ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:lisa@example.com SEQUENCE:2 END:VEVENT END:VCALENDAR'; @@ -121,7 +102,7 @@ END:VCALENDAR'; static function getTestTODO($type = 'due') { - switch($type) { + switch ($type) { case 'due' : $extra = "DUE:20100104T000000Z"; diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/ValidateICalTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/ValidateICalTest.php index be166d9e6..629df90c1 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/ValidateICalTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/ValidateICalTest.php @@ -21,20 +21,20 @@ class ValidateICalTest extends \PHPUnit_Framework_TestCase { function setUp() { - $calendars = array( - array( - 'id' => 'calendar1', - 'principaluri' => 'principals/admin', - 'uri' => 'calendar1', - '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Xml\Property\SupportedCalendarComponentSet( ['VEVENT','VTODO','VJOURNAL'] ), - ), - array( - 'id' => 'calendar2', - 'principaluri' => 'principals/admin', - 'uri' => 'calendar2', - '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Xml\Property\SupportedCalendarComponentSet( ['VTODO','VJOURNAL'] ), - ) - ); + $calendars = [ + [ + 'id' => 'calendar1', + 'principaluri' => 'principals/admin', + 'uri' => 'calendar1', + '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Xml\Property\SupportedCalendarComponentSet(['VEVENT', 'VTODO', 'VJOURNAL']), + ], + [ + 'id' => 'calendar2', + 'principaluri' => 'principals/admin', + 'uri' => 'calendar2', + '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Xml\Property\SupportedCalendarComponentSet(['VTODO', 'VJOURNAL']), + ] + ]; $this->calBackend = new Backend\Mock($calendars, []); $principalBackend = new DAVACL\PrincipalBackend\Mock(); @@ -66,10 +66,10 @@ class ValidateICalTest extends \PHPUnit_Framework_TestCase { function testCreateFile() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', + ]); $response = $this->request($request); @@ -79,66 +79,168 @@ class ValidateICalTest extends \PHPUnit_Framework_TestCase { function testCreateFileValid() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); - $request->setBody("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nUID:foo\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $request = new HTTP\Request( + 'PUT', + '/calendars/admin/calendar1/blabla.ics', + ['Prefer' => 'handling=strict'] + ); + + $ics = <<setBody($ics); $response = $this->request($request); $this->assertEquals(201, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Length' => ['0'], - 'ETag' => ['"' . md5("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nUID:foo\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n") . '"'], - ), $response->getHeaders()); + 'Content-Length' => ['0'], + 'ETag' => ['"' . md5($ics) . '"'], + ], $response->getHeaders()); - $expected = array( + $expected = [ 'uri' => 'blabla.ics', - 'calendardata' => "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nUID:foo\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", + 'calendardata' => $ics, 'calendarid' => 'calendar1', 'lastmodified' => null, + ]; + + $this->assertEquals($expected, $this->calBackend->getCalendarObject('calendar1', 'blabla.ics')); + + } + + function testCreateFileNoVersion() { + + $request = new HTTP\Request( + 'PUT', + '/calendars/admin/calendar1/blabla.ics', + ['Prefer' => 'handling=strict'] ); - $this->assertEquals($expected, $this->calBackend->getCalendarObject('calendar1','blabla.ics')); + $ics = <<setBody($ics); + + $response = $this->request($request); + + $this->assertEquals(415, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); } - function testCreateFileNoComponents() { + function testCreateFileNoVersionFixed() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); - $request->setBody("BEGIN:VCALENDAR\r\nEND:VCALENDAR\r\n"); + $request = new HTTP\Request( + 'PUT', + '/calendars/admin/calendar1/blabla.ics', + ['Prefer' => 'handling=lenient'] + ); + + $ics = <<setBody($ics); $response = $this->request($request); - $this->assertEquals(400, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); + $this->assertEquals(201, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); + $this->assertEquals([ + 'X-Sabre-Version' => [DAV\Version::VERSION], + 'Content-Length' => ['0'], + 'X-Sabre-Ew-Gross' => ['iCalendar validation warning: VERSION MUST appear exactly once in a VCALENDAR component'], + ], $response->getHeaders()); + + $ics = << 'blabla.ics', + 'calendardata' => $ics, + 'calendarid' => 'calendar1', + 'lastmodified' => null, + ]; + + $this->assertEquals($expected, $this->calBackend->getCalendarObject('calendar1', 'blabla.ics')); + + } + + function testCreateFileNoComponents() { + + $request = new HTTP\Request( + 'PUT', + '/calendars/admin/calendar1/blabla.ics', + ['Prefer' => 'handling=strict'] + ); + $ics = <<setBody($ics); + + $response = $this->request($request); + $this->assertEquals(403, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); } function testCreateFileNoUID() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', + ]); $request->setBody("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $response = $this->request($request); - $this->assertEquals(400, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); + $this->assertEquals(415, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); } function testCreateFileVCard() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', + ]); $request->setBody("BEGIN:VCARD\r\nEND:VCARD\r\n"); $response = $this->request($request); @@ -149,53 +251,53 @@ class ValidateICalTest extends \PHPUnit_Framework_TestCase { function testCreateFile2Components() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', + ]); $request->setBody("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nUID:foo\r\nEND:VEVENT\r\nBEGIN:VJOURNAL\r\nUID:foo\r\nEND:VJOURNAL\r\nEND:VCALENDAR\r\n"); $response = $this->request($request); - $this->assertEquals(400, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); + $this->assertEquals(415, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); } function testCreateFile2UIDS() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', + ]); $request->setBody("BEGIN:VCALENDAR\r\nBEGIN:VTIMEZONE\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nUID:foo\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nUID:bar\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $response = $this->request($request); - $this->assertEquals(400, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); + $this->assertEquals(415, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); } function testCreateFileWrongComponent() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', + ]); $request->setBody("BEGIN:VCALENDAR\r\nBEGIN:VTIMEZONE\r\nEND:VTIMEZONE\r\nBEGIN:VFREEBUSY\r\nUID:foo\r\nEND:VFREEBUSY\r\nEND:VCALENDAR\r\n"); $response = $this->request($request); - $this->assertEquals(400, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); + $this->assertEquals(403, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); } function testUpdateFile() { - $this->calBackend->createCalendarObject('calendar1','blabla.ics','foo'); - $request = HTTP\Sapi::createFromServerArray(array( + $this->calBackend->createCalendarObject('calendar1', 'blabla.ics', 'foo'); + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', + ]); $response = $this->request($request); @@ -205,35 +307,45 @@ class ValidateICalTest extends \PHPUnit_Framework_TestCase { function testUpdateFileParsableBody() { - $this->calBackend->createCalendarObject('calendar1','blabla.ics','foo'); - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); - $body = "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nUID:foo\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"; - $request->setBody($body); - + $this->calBackend->createCalendarObject('calendar1', 'blabla.ics', 'foo'); + $request = new HTTP\Request( + 'PUT', + '/calendars/admin/calendar1/blabla.ics' + ); + $ics = <<setBody($ics); $response = $this->request($request); $this->assertEquals(204, $response->status); - $expected = array( + $expected = [ 'uri' => 'blabla.ics', - 'calendardata' => $body, + 'calendardata' => $ics, 'calendarid' => 'calendar1', 'lastmodified' => null, - ); + ]; - $this->assertEquals($expected, $this->calBackend->getCalendarObject('calendar1','blabla.ics')); + $this->assertEquals($expected, $this->calBackend->getCalendarObject('calendar1', 'blabla.ics')); } function testCreateFileInvalidComponent() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar2/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar2/blabla.ics', + ]); $request->setBody("BEGIN:VCALENDAR\r\nBEGIN:VTIMEZONE\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nUID:foo\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $response = $this->request($request); @@ -244,11 +356,11 @@ class ValidateICalTest extends \PHPUnit_Framework_TestCase { function testUpdateFileInvalidComponent() { - $this->calBackend->createCalendarObject('calendar2','blabla.ics','foo'); - $request = HTTP\Sapi::createFromServerArray(array( + $this->calBackend->createCalendarObject('calendar2', 'blabla.ics', 'foo'); + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar2/blabla.ics', - )); + 'REQUEST_URI' => '/calendars/admin/calendar2/blabla.ics', + ]); $request->setBody("BEGIN:VCALENDAR\r\nBEGIN:VTIMEZONE\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nUID:foo\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); $response = $this->request($request); @@ -266,11 +378,24 @@ class ValidateICalTest extends \PHPUnit_Framework_TestCase { */ function testCreateFileModified() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/calendars/admin/calendar1/blabla.ics', - )); - $request->setBody("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nUID:foo\r\nSUMMARY:Meeting in M\xfcnster\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"); + $request = new HTTP\Request( + 'PUT', + '/calendars/admin/calendar1/blabla.ics' + ); + $ics = <<setBody($ics); $response = $this->request($request); diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/AbstractPluginTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/AbstractPluginTest.php index a123099a0..552e2ba77 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/AbstractPluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/AbstractPluginTest.php @@ -26,13 +26,13 @@ abstract class AbstractPluginTest extends \PHPUnit_Framework_TestCase { $this->backend = new Backend\Mock(); $principalBackend = new DAVACL\PrincipalBackend\Mock(); - $tree = array( + $tree = [ new AddressBookRoot($principalBackend, $this->backend), new DAVACL\PrincipalCollection($principalBackend) - ); + ]; $this->plugin = new Plugin(); - $this->plugin->directories = array('directory'); + $this->plugin->directories = ['directory']; $this->server = new DAV\Server($tree); $this->server->sapi = new HTTP\SapiMock(); $this->server->addPlugin($this->plugin); diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/AddressBookQueryTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/AddressBookQueryTest.php index 478f6beb5..2c3171bf3 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/AddressBookQueryTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/AddressBookQueryTest.php @@ -12,11 +12,11 @@ class AddressBookQueryTest extends AbstractPluginTest { function testQuery() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'REPORT', - 'REQUEST_URI' => '/addressbooks/user1/book1', - 'HTTP_DEPTH' => '1', - )); + $request = new HTTP\Request( + 'REPORT', + '/addressbooks/user1/book1', + ['Depth' => '1'] + ); $request->setBody( ' @@ -40,33 +40,33 @@ class AddressBookQueryTest extends AbstractPluginTest { $this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body); // using the client for parsing - $client = new DAV\Client(array('baseUri'=>'/')); + $client = new DAV\Client(['baseUri' => '/']); $result = $client->parseMultiStatus($response->body); - $this->assertEquals(array( - '/addressbooks/user1/book1/card1' => array( - 200 => array( + $this->assertEquals([ + '/addressbooks/user1/book1/card1' => [ + 200 => [ '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', - ), - ), - '/addressbooks/user1/book1/card2' => array( - 404 => array( + ], + ], + '/addressbooks/user1/book1/card2' => [ + 404 => [ '{DAV:}getetag' => null, - ), - ) - ), $result); + ], + ] + ], $result); } function testQueryDepth0() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'REPORT', - 'REQUEST_URI' => '/addressbooks/user1/book1/card1', - 'HTTP_DEPTH' => '0', - )); + $request = new HTTP\Request( + 'REPORT', + '/addressbooks/user1/book1/card1', + ['Depth' => '0'] + ); $request->setBody( ' @@ -90,28 +90,28 @@ class AddressBookQueryTest extends AbstractPluginTest { $this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body); // using the client for parsing - $client = new DAV\Client(array('baseUri'=>'/')); + $client = new DAV\Client(['baseUri' => '/']); $result = $client->parseMultiStatus($response->body); - $this->assertEquals(array( - '/addressbooks/user1/book1/card1' => array( - 200 => array( + $this->assertEquals([ + '/addressbooks/user1/book1/card1' => [ + 200 => [ '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', - ), - ), - ), $result); + ], + ], + ], $result); } function testQueryNoMatch() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'REPORT', - 'REQUEST_URI' => '/addressbooks/user1/book1', - 'HTTP_DEPTH' => '1', - )); + $request = new HTTP\Request( + 'REPORT', + '/addressbooks/user1/book1', + ['Depth' => '1'] + ); $request->setBody( ' @@ -135,21 +135,21 @@ class AddressBookQueryTest extends AbstractPluginTest { $this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body); // using the client for parsing - $client = new DAV\Client(array('baseUri'=>'/')); + $client = new DAV\Client(['baseUri' => '/']); $result = $client->parseMultiStatus($response->body); - $this->assertEquals(array(), $result); + $this->assertEquals([], $result); } function testQueryLimit() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'REPORT', - 'REQUEST_URI' => '/addressbooks/user1/book1', - 'HTTP_DEPTH' => '1', - )); + 'REQUEST_URI' => '/addressbooks/user1/book1', + 'HTTP_DEPTH' => '1', + ]); $request->setBody( ' @@ -174,17 +174,17 @@ class AddressBookQueryTest extends AbstractPluginTest { $this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body); // using the client for parsing - $client = new DAV\Client(array('baseUri'=>'/')); + $client = new DAV\Client(['baseUri' => '/']); $result = $client->parseMultiStatus($response->body); - $this->assertEquals(array( - '/addressbooks/user1/book1/card1' => array( - 200 => array( - '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD"). '"', - ), - ), - ), $result); + $this->assertEquals([ + '/addressbooks/user1/book1/card1' => [ + 200 => [ + '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', + ], + ], + ], $result); } @@ -217,20 +217,20 @@ class AddressBookQueryTest extends AbstractPluginTest { $this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body); // using the client for parsing - $client = new DAV\Client(array('baseUri'=>'/')); + $client = new DAV\Client(['baseUri' => '/']); $result = $client->parseMultiStatus($response->body); $vobjVersion = \Sabre\VObject\Version::VERSION; - $this->assertEquals(array( - '/addressbooks/user1/book1/card1' => array( - 200 => array( - '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD"). '"', + $this->assertEquals([ + '/addressbooks/user1/book1/card1' => [ + 200 => [ + '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', '{urn:ietf:params:xml:ns:carddav}address-data' => '["vcard",[["version",{},"text","4.0"],["prodid",{},"text","-\/\/Sabre\/\/Sabre VObject ' . $vobjVersion . '\/\/EN"],["uid",{},"text","12345"]]]', - ), - ), - ), $result); + ], + ], + ], $result); } @@ -262,20 +262,20 @@ class AddressBookQueryTest extends AbstractPluginTest { $this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body); // using the client for parsing - $client = new DAV\Client(array('baseUri'=>'/')); + $client = new DAV\Client(['baseUri' => '/']); $result = $client->parseMultiStatus($response->body); $vobjVersion = \Sabre\VObject\Version::VERSION; - $this->assertEquals(array( - '/addressbooks/user1/book1/card1' => array( - 200 => array( - '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD"). '"', + $this->assertEquals([ + '/addressbooks/user1/book1/card1' => [ + 200 => [ + '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', '{urn:ietf:params:xml:ns:carddav}address-data' => "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:-//Sabre//Sabre VObject $vobjVersion//EN\r\nUID:12345\r\nEND:VCARD\r\n", - ), - ), - ), $result); + ], + ], + ], $result); } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/AddressBookTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/AddressBookTest.php index fe8ba9025..1a36fd10c 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/AddressBookTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/AddressBookTest.php @@ -4,10 +4,10 @@ namespace Sabre\CardDAV; use Sabre\DAV\PropPatch; -require_once 'Sabre/CardDAV/Backend/Mock.php'; - class AddressBookTest extends \PHPUnit_Framework_TestCase { + use \Sabre\DAV\DbTestHelperTrait; + /** * @var Sabre\CardDAV\AddressBook */ @@ -19,12 +19,12 @@ class AddressBookTest extends \PHPUnit_Framework_TestCase { $this->backend = new Backend\Mock(); $this->ab = new AddressBook( $this->backend, - array( - 'uri' => 'book1', - 'id' => 'foo', + [ + 'uri' => 'book1', + 'id' => 'foo', '{DAV:}displayname' => 'd-name', - 'principaluri' => 'principals/user1', - ) + 'principaluri' => 'principals/user1', + ] ); } @@ -73,10 +73,10 @@ class AddressBookTest extends \PHPUnit_Framework_TestCase { function testCreateFile() { - $file = fopen('php://memory','r+'); - fwrite($file,'foo'); + $file = fopen('php://memory', 'r+'); + fwrite($file, 'foo'); rewind($file); - $this->ab->createFile('card2',$file); + $this->ab->createFile('card2', $file); $this->assertEquals('foo', $this->backend->cards['foo']['card2']); @@ -85,7 +85,7 @@ class AddressBookTest extends \PHPUnit_Framework_TestCase { function testDelete() { $this->ab->delete(); - $this->assertEquals(array(), $this->backend->addressBooks); + $this->assertEquals([], $this->backend->addressBooks); } @@ -118,10 +118,10 @@ class AddressBookTest extends \PHPUnit_Framework_TestCase { function testGetProperties() { - $props = $this->ab->getProperties(array('{DAV:}displayname')); - $this->assertEquals(array( + $props = $this->ab->getProperties(['{DAV:}displayname']); + $this->assertEquals([ '{DAV:}displayname' => 'd-name', - ), $props); + ], $props); } @@ -129,27 +129,22 @@ class AddressBookTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('principals/user1', $this->ab->getOwner()); $this->assertNull($this->ab->getGroup()); - $this->assertEquals(array( - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/user1', - 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', - 'principal' => 'principals/user1', + $this->assertEquals([ + [ + 'privilege' => '{DAV:}all', + 'principal' => '{DAV:}owner', 'protected' => true, - ), - ), $this->ab->getACL()); + ], + ], $this->ab->getACL()); } /** - * @expectedException Sabre\DAV\Exception\MethodNotAllowed + * @expectedException Sabre\DAV\Exception\Forbidden */ function testSetACL() { - $this->ab->setACL(array()); + $this->ab->setACL([]); } @@ -168,45 +163,32 @@ class AddressBookTest extends \PHPUnit_Framework_TestCase { } function testGetChangesNoSyncSupport() { - $this->assertNull($this->ab->getChanges(1,null)); + $this->assertNull($this->ab->getChanges(1, null)); } function testGetSyncToken() { - if (!SABRE_HASSQLITE) { - $this->markTestSkipped('Sqlite is required for this test to run'); - } - $ab = new AddressBook(TestUtil::getBackend(), [ 'id' => 1, '{DAV:}sync-token' => 2]); + $this->driver = 'sqlite'; + $this->dropTables(['addressbooks', 'cards', 'addressbookchanges']); + $this->createSchema('addressbooks'); + $backend = new Backend\PDO( + $this->getPDO() + ); + $ab = new AddressBook($backend, [ 'id' => 1, '{DAV:}sync-token' => 2]); $this->assertEquals(2, $ab->getSyncToken()); - TestUtil::deleteSQLiteDB(); } function testGetSyncToken2() { - if (!SABRE_HASSQLITE) { - $this->markTestSkipped('Sqlite is required for this test to run'); - } - $ab = new AddressBook(TestUtil::getBackend(), [ 'id' => 1, '{http://sabredav.org/ns}sync-token' => 2]); + $this->driver = 'sqlite'; + $this->dropTables(['addressbooks', 'cards', 'addressbookchanges']); + $this->createSchema('addressbooks'); + $backend = new Backend\PDO( + $this->getPDO() + ); + $ab = new AddressBook($backend, [ 'id' => 1, '{http://sabredav.org/ns}sync-token' => 2]); $this->assertEquals(2, $ab->getSyncToken()); - TestUtil::deleteSQLiteDB(); } - function testGetChanges() { - - if (!SABRE_HASSQLITE) { - $this->markTestSkipped('Sqlite is required for this test to run'); - } - $ab = new AddressBook(TestUtil::getBackend(), [ 'id' => 1, '{DAV:}sync-token' => 2]); - $this->assertEquals([ - 'syncToken' => 2, - 'modified' => [], - 'deleted' => [], - 'added' => ['UUID-2345'], - ], $ab->getChanges(1, 1)); - TestUtil::deleteSQLiteDB(); - - } - - } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/AbstractPDOTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/AbstractPDOTest.php index d2ec278be..f62bfb1ae 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/AbstractPDOTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/AbstractPDOTest.php @@ -7,52 +7,55 @@ use Sabre\DAV\PropPatch; abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { + use \Sabre\DAV\DbTestHelperTrait; + /** * @var CardDAV\Backend\PDO */ protected $backend; - /** - * @abstract - * @return PDO - */ - abstract function getPDO(); - - public function setUp() { + function setUp() { + $this->dropTables([ + 'addressbooks', + 'cards', + 'addressbookchanges', + ]); + $this->createSchema('addressbooks'); $pdo = $this->getPDO(); + $this->backend = new PDO($pdo); - $pdo->exec('INSERT INTO addressbooks (principaluri, displayname, uri, description, synctoken) VALUES ("principals/user1", "book1", "book1", "addressbook 1", 1)'); - $pdo->exec('INSERT INTO cards (addressbookid, carddata, uri, lastmodified, etag, size) VALUES (1, "card1", "card1", 0, "' . md5('card1') . '", 5)'); + $pdo->exec("INSERT INTO addressbooks (principaluri, displayname, uri, description, synctoken) VALUES ('principals/user1', 'book1', 'book1', 'addressbook 1', 1)"); + $pdo->exec("INSERT INTO cards (addressbookid, carddata, uri, lastmodified, etag, size) VALUES (1, 'card1', 'card1', 0, '" . md5('card1') . "', 5)"); } - public function testGetAddressBooksForUser() { + function testGetAddressBooksForUser() { $result = $this->backend->getAddressBooksForUser('principals/user1'); - $expected = array( - array( - 'id' => 1, - 'uri' => 'book1', - 'principaluri' => 'principals/user1', - '{DAV:}displayname' => 'book1', + $expected = [ + [ + 'id' => 1, + 'uri' => 'book1', + 'principaluri' => 'principals/user1', + '{DAV:}displayname' => 'book1', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'addressbook 1', - '{http://calendarserver.org/ns/}getctag' => 1, - '{http://sabredav.org/ns}sync-token' => 1 - ) - ); + '{http://calendarserver.org/ns/}getctag' => 1, + '{http://sabredav.org/ns}sync-token' => 1 + ] + ]; $this->assertEquals($expected, $result); } - public function testUpdateAddressBookInvalidProp() { + function testUpdateAddressBookInvalidProp() { $propPatch = new PropPatch([ - '{DAV:}displayname' => 'updated', + '{DAV:}displayname' => 'updated', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'updated', - '{DAV:}foo' => 'bar', + '{DAV:}foo' => 'bar', ]); $this->backend->updateAddressBook(1, $propPatch); @@ -62,23 +65,23 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $result = $this->backend->getAddressBooksForUser('principals/user1'); - $expected = array( - array( - 'id' => 1, - 'uri' => 'book1', - 'principaluri' => 'principals/user1', - '{DAV:}displayname' => 'book1', + $expected = [ + [ + 'id' => 1, + 'uri' => 'book1', + 'principaluri' => 'principals/user1', + '{DAV:}displayname' => 'book1', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'addressbook 1', - '{http://calendarserver.org/ns/}getctag' => 1, - '{http://sabredav.org/ns}sync-token' => 1 - ) - ); + '{http://calendarserver.org/ns/}getctag' => 1, + '{http://sabredav.org/ns}sync-token' => 1 + ] + ]; $this->assertEquals($expected, $result); } - public function testUpdateAddressBookNoProps() { + function testUpdateAddressBookNoProps() { $propPatch = new PropPatch([ ]); @@ -89,27 +92,27 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $result = $this->backend->getAddressBooksForUser('principals/user1'); - $expected = array( - array( - 'id' => 1, - 'uri' => 'book1', - 'principaluri' => 'principals/user1', - '{DAV:}displayname' => 'book1', + $expected = [ + [ + 'id' => 1, + 'uri' => 'book1', + 'principaluri' => 'principals/user1', + '{DAV:}displayname' => 'book1', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'addressbook 1', - '{http://calendarserver.org/ns/}getctag' => 1, - '{http://sabredav.org/ns}sync-token' => 1 - ) - ); + '{http://calendarserver.org/ns/}getctag' => 1, + '{http://sabredav.org/ns}sync-token' => 1 + ] + ]; $this->assertEquals($expected, $result); } - public function testUpdateAddressBookSuccess() { + function testUpdateAddressBookSuccess() { $propPatch = new PropPatch([ - '{DAV:}displayname' => 'updated', + '{DAV:}displayname' => 'updated', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'updated', ]); @@ -120,104 +123,108 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $result = $this->backend->getAddressBooksForUser('principals/user1'); - $expected = array( - array( - 'id' => 1, - 'uri' => 'book1', - 'principaluri' => 'principals/user1', - '{DAV:}displayname' => 'updated', + $expected = [ + [ + 'id' => 1, + 'uri' => 'book1', + 'principaluri' => 'principals/user1', + '{DAV:}displayname' => 'updated', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'updated', - '{http://calendarserver.org/ns/}getctag' => 2, - '{http://sabredav.org/ns}sync-token' => 2 - ) - ); + '{http://calendarserver.org/ns/}getctag' => 2, + '{http://sabredav.org/ns}sync-token' => 2 + ] + ]; $this->assertEquals($expected, $result); } - public function testDeleteAddressBook() { + function testDeleteAddressBook() { $this->backend->deleteAddressBook(1); - $this->assertEquals(array(), $this->backend->getAddressBooksForUser('principals/user1')); + $this->assertEquals([], $this->backend->getAddressBooksForUser('principals/user1')); } /** * @expectedException Sabre\DAV\Exception\BadRequest */ - public function testCreateAddressBookUnsupportedProp() { + function testCreateAddressBookUnsupportedProp() { - $this->backend->createAddressBook('principals/user1','book2', array( + $this->backend->createAddressBook('principals/user1', 'book2', [ '{DAV:}foo' => 'bar', - )); + ]); } - public function testCreateAddressBookSuccess() { + function testCreateAddressBookSuccess() { - $this->backend->createAddressBook('principals/user1','book2', array( - '{DAV:}displayname' => 'book2', + $this->backend->createAddressBook('principals/user1', 'book2', [ + '{DAV:}displayname' => 'book2', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'addressbook 2', - )); - - $expected = array( - array( - 'id' => 1, - 'uri' => 'book1', - 'principaluri' => 'principals/user1', - '{DAV:}displayname' => 'book1', + ]); + + $expected = [ + [ + 'id' => 1, + 'uri' => 'book1', + 'principaluri' => 'principals/user1', + '{DAV:}displayname' => 'book1', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'addressbook 1', - '{http://calendarserver.org/ns/}getctag' => 1, - '{http://sabredav.org/ns}sync-token' => 1, - ), - array( - 'id' => 2, - 'uri' => 'book2', - 'principaluri' => 'principals/user1', - '{DAV:}displayname' => 'book2', + '{http://calendarserver.org/ns/}getctag' => 1, + '{http://sabredav.org/ns}sync-token' => 1, + ], + [ + 'id' => 2, + 'uri' => 'book2', + 'principaluri' => 'principals/user1', + '{DAV:}displayname' => 'book2', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => 'addressbook 2', - '{http://calendarserver.org/ns/}getctag' => 1, - '{http://sabredav.org/ns}sync-token' => 1, - ) - ); + '{http://calendarserver.org/ns/}getctag' => 1, + '{http://sabredav.org/ns}sync-token' => 1, + ] + ]; $result = $this->backend->getAddressBooksForUser('principals/user1'); $this->assertEquals($expected, $result); } - public function testGetCards() { + function testGetCards() { $result = $this->backend->getCards(1); - $expected = array( - array( - 'id' => 1, - 'uri' => 'card1', + $expected = [ + [ + 'id' => 1, + 'uri' => 'card1', 'lastmodified' => 0, - 'etag' => '"' . md5('card1') . '"', - 'size' => 5 - ) - ); + 'etag' => '"' . md5('card1') . '"', + 'size' => 5 + ] + ]; $this->assertEquals($expected, $result); } - public function testGetCard() { + function testGetCard() { - $result = $this->backend->getCard(1,'card1'); + $result = $this->backend->getCard(1, 'card1'); - $expected = array( - 'id' => 1, - 'uri' => 'card1', - 'carddata' => 'card1', + $expected = [ + 'id' => 1, + 'uri' => 'card1', + 'carddata' => 'card1', 'lastmodified' => 0, - 'etag' => '"' . md5('card1') . '"', - 'size' => 5 - ); + 'etag' => '"' . md5('card1') . '"', + 'size' => 5 + ]; + + if (is_resource($result['carddata'])) { + $result['carddata'] = stream_get_contents($result['carddata']); + } $this->assertEquals($expected, $result); @@ -226,13 +233,16 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { /** * @depends testGetCard */ - public function testCreateCard() { + function testCreateCard() { $result = $this->backend->createCard(1, 'card2', 'data2'); $this->assertEquals('"' . md5('data2') . '"', $result); - $result = $this->backend->getCard(1,'card2'); + $result = $this->backend->getCard(1, 'card2'); $this->assertEquals(2, $result['id']); $this->assertEquals('card2', $result['uri']); + if (is_resource($result['carddata'])) { + $result['carddata'] = stream_get_contents($result['carddata']); + } $this->assertEquals('data2', $result['carddata']); } @@ -240,41 +250,52 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { /** * @depends testCreateCard */ - public function testGetMultiple() { + function testGetMultiple() { $result = $this->backend->createCard(1, 'card2', 'data2'); $result = $this->backend->createCard(1, 'card3', 'data3'); $check = [ [ - 'id' => 1, - 'uri' => 'card1', - 'carddata' => 'card1', + 'id' => 1, + 'uri' => 'card1', + 'carddata' => 'card1', 'lastmodified' => 0, ], [ - 'id' => 2, - 'uri' => 'card2', - 'carddata' => 'data2', + 'id' => 2, + 'uri' => 'card2', + 'carddata' => 'data2', 'lastmodified' => time(), ], [ - 'id' => 3, - 'uri' => 'card3', - 'carddata' => 'data3', + 'id' => 3, + 'uri' => 'card3', + 'carddata' => 'data3', 'lastmodified' => time(), ], ]; - $result = $this->backend->getMultipleCards(1, ['card1','card2','card3']); + $result = $this->backend->getMultipleCards(1, ['card1', 'card2', 'card3']); + + foreach ($check as $index => $node) { - foreach($check as $index=>$node) { + foreach ($node as $k => $v) { - foreach($node as $k=>$v) { + $expected = $v; + $actual = $result[$index][$k]; - if ($k!=='lastmodified') { - $this->assertEquals($v, $result[$index][$k]); - } else { - $this->assertTrue(isset($result[$index][$k])); + switch ($k) { + case 'lastmodified' : + $this->assertInternalType('int', $actual); + break; + case 'carddata' : + if (is_resource($actual)) { + $actual = stream_get_contents($actual); + } + // No break intended. + default : + $this->assertEquals($expected, $actual); + break; } } @@ -287,13 +308,16 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { /** * @depends testGetCard */ - public function testUpdateCard() { + function testUpdateCard() { $result = $this->backend->updateCard(1, 'card1', 'newdata'); $this->assertEquals('"' . md5('newdata') . '"', $result); - $result = $this->backend->getCard(1,'card1'); + $result = $this->backend->getCard(1, 'card1'); $this->assertEquals(1, $result['id']); + if (is_resource($result['carddata'])) { + $result['carddata'] = stream_get_contents($result['carddata']); + } $this->assertEquals('newdata', $result['carddata']); } @@ -301,10 +325,10 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { /** * @depends testGetCard */ - public function testDeleteCard() { + function testDeleteCard() { $this->backend->deleteCard(1, 'card1'); - $result = $this->backend->getCard(1,'card1'); + $result = $this->backend->getCard(1, 'card1'); $this->assertFalse($result); } @@ -347,4 +371,3 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { } } - diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/Mock.php b/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/Mock.php index 3f96d3c5d..840b898e8 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/Mock.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/Mock.php @@ -13,24 +13,24 @@ class Mock extends AbstractBackend { $this->cards = $cards; if (is_null($this->addressBooks)) { - $this->addressBooks = array( - array( - 'id' => 'foo', - 'uri' => 'book1', - 'principaluri' => 'principals/user1', + $this->addressBooks = [ + [ + 'id' => 'foo', + 'uri' => 'book1', + 'principaluri' => 'principals/user1', '{DAV:}displayname' => 'd-name', - ), - ); + ], + ]; - $card2 = fopen('php://memory','r+'); - fwrite($card2,"BEGIN:VCARD\nVERSION:3.0\nUID:45678\nEND:VCARD"); + $card2 = fopen('php://memory', 'r+'); + fwrite($card2, "BEGIN:VCARD\nVERSION:3.0\nUID:45678\nEND:VCARD"); rewind($card2); - $this->cards = array( - 'foo' => array( + $this->cards = [ + 'foo' => [ 'card1' => "BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD", 'card2' => $card2, - ), - ); + ], + ]; } } @@ -38,8 +38,8 @@ class Mock extends AbstractBackend { function getAddressBooksForUser($principalUri) { - $books = array(); - foreach($this->addressBooks as $book) { + $books = []; + foreach ($this->addressBooks as $book) { if ($book['principaluri'] === $principalUri) { $books[] = $book; } @@ -64,14 +64,14 @@ class Mock extends AbstractBackend { * @param \Sabre\DAV\PropPatch $propPatch * @return void */ - public function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) { + function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) { - foreach($this->addressBooks as &$book) { + foreach ($this->addressBooks as &$book) { if ($book['id'] !== $addressBookId) continue; $propPatch->handleRemaining(function($mutations) use (&$book) { - foreach($mutations as $key=>$value) { + foreach ($mutations as $key => $value) { $book[$key] = $value; } return true; @@ -83,17 +83,17 @@ class Mock extends AbstractBackend { function createAddressBook($principalUri, $url, array $properties) { - $this->addressBooks[] = array_merge($properties, array( - 'id' => $url, - 'uri' => $url, + $this->addressBooks[] = array_merge($properties, [ + 'id' => $url, + 'uri' => $url, 'principaluri' => $principalUri, - )); + ]); } function deleteAddressBook($addressBookId) { - foreach($this->addressBooks as $key=>$value) { + foreach ($this->addressBooks as $key => $value) { if ($value['id'] === $addressBookId) unset($this->addressBooks[$key]); } @@ -101,41 +101,142 @@ class Mock extends AbstractBackend { } + /** + * Returns all cards for a specific addressbook id. + * + * This method should return the following properties for each card: + * * carddata - raw vcard data + * * uri - Some unique url + * * lastmodified - A unix timestamp + * + * It's recommended to also return the following properties: + * * etag - A unique etag. This must change every time the card changes. + * * size - The size of the card in bytes. + * + * If these last two properties are provided, less time will be spent + * calculating them. If they are specified, you can also ommit carddata. + * This may speed up certain requests, especially with large cards. + * + * @param mixed $addressbookId + * @return array + */ function getCards($addressBookId) { - $cards = array(); - foreach($this->cards[$addressBookId] as $uri=>$data) { - $cards[] = array( - 'uri' => $uri, - 'carddata' => $data, - ); + $cards = []; + foreach ($this->cards[$addressBookId] as $uri => $data) { + if (is_resource($data)) { + $cards[] = [ + 'uri' => $uri, + 'carddata' => $data, + ]; + } else { + $cards[] = [ + 'uri' => $uri, + 'carddata' => $data, + 'etag' => '"' . md5($data) . '"', + 'size' => strlen($data) + ]; + } } return $cards; } + /** + * Returns a specfic card. + * + * The same set of properties must be returned as with getCards. The only + * exception is that 'carddata' is absolutely required. + * + * If the card does not exist, you must return false. + * + * @param mixed $addressBookId + * @param string $cardUri + * @return array + */ function getCard($addressBookId, $cardUri) { if (!isset($this->cards[$addressBookId][$cardUri])) { return false; } - return array( - 'uri' => $cardUri, - 'carddata' => $this->cards[$addressBookId][$cardUri], - ); + $data = $this->cards[$addressBookId][$cardUri]; + return [ + 'uri' => $cardUri, + 'carddata' => $data, + 'etag' => '"' . md5($data) . '"', + 'size' => strlen($data) + ]; } + /** + * Creates a new card. + * + * The addressbook id will be passed as the first argument. This is the + * same id as it is returned from the getAddressBooksForUser method. + * + * The cardUri is a base uri, and doesn't include the full path. The + * cardData argument is the vcard body, and is passed as a string. + * + * It is possible to return an ETag from this method. This ETag is for the + * newly created resource, and must be enclosed with double quotes (that + * is, the string itself must contain the double quotes). + * + * You should only return the ETag if you store the carddata as-is. If a + * subsequent GET request on the same card does not have the same body, + * byte-by-byte and you did return an ETag here, clients tend to get + * confused. + * + * If you don't return an ETag, you can just return null. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null + */ function createCard($addressBookId, $cardUri, $cardData) { + if (is_resource($cardData)) { + $cardData = stream_get_contents($cardData); + } $this->cards[$addressBookId][$cardUri] = $cardData; + return '"' . md5($cardData) . '"'; } + /** + * Updates a card. + * + * The addressbook id will be passed as the first argument. This is the + * same id as it is returned from the getAddressBooksForUser method. + * + * The cardUri is a base uri, and doesn't include the full path. The + * cardData argument is the vcard body, and is passed as a string. + * + * It is possible to return an ETag from this method. This ETag should + * match that of the updated resource, and must be enclosed with double + * quotes (that is: the string itself must contain the actual quotes). + * + * You should only return the ETag if you store the carddata as-is. If a + * subsequent GET request on the same card does not have the same body, + * byte-by-byte and you did return an ETag here, clients tend to get + * confused. + * + * If you don't return an ETag, you can just return null. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null + */ function updateCard($addressBookId, $cardUri, $cardData) { + if (is_resource($cardData)) { + $cardData = stream_get_contents($cardData); + } $this->cards[$addressBookId][$cardUri] = $cardData; + return '"' . md5($cardData) . '"'; } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/PDOMySQLTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/PDOMySQLTest.php index 38cb655d0..c1b0e274e 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/PDOMySQLTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/PDOMySQLTest.php @@ -2,35 +2,8 @@ namespace Sabre\CardDAV\Backend; -require_once 'Sabre/TestUtil.php'; - class PDOMySQLTest extends AbstractPDOTest { - /** - * @return PDO - */ - public function getPDO() { - - if (!SABRE_HASMYSQL) $this->markTestSkipped('MySQL driver is not available, or not properly configured'); - - $pdo = \Sabre\TestUtil::getMySQLDB(); - if (!$pdo) $this->markTestSkipped('Could not connect to MySQL database'); - - $pdo->query("DROP TABLE IF EXISTS addressbooks, cards, addressbookchanges"); - - $queries = explode( - ';', - file_get_contents(__DIR__ . '/../../../../examples/sql/mysql.addressbook.sql') - ); - - foreach($queries as $query) { - $query = trim($query," \r\n\t"); - if ($query) - $pdo->exec($query); - } - return $pdo; - - } + public $driver = 'mysql'; } - diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/PDOSqliteTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/PDOSqliteTest.php index 5a4a7a327..b187c4d78 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/PDOSqliteTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/Backend/PDOSqliteTest.php @@ -2,53 +2,8 @@ namespace Sabre\CardDAV\Backend; -require_once 'Sabre/TestUtil.php'; - class PDOSqliteTest extends AbstractPDOTest { - function tearDown() { - - if (file_exists(SABRE_TEMPDIR . '/pdobackend')) unlink(SABRE_TEMPDIR . '/pdobackend'); - if (file_exists(SABRE_TEMPDIR . '/pdobackend2')) unlink(SABRE_TEMPDIR . '/pdobackend2'); - - } - - /** - * @return PDO - */ - function getPDO() { - - return self::getSQLite(); - - } - - /** - * @return PDO - */ - static function getSQLite() { - - if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available'); - $pdo = new \PDO('sqlite:'.SABRE_TEMPDIR.'/pdobackend'); - $pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); - - $pdo->query("DROP TABLE IF EXISTS addressbooks"); - $pdo->query("DROP TABLE IF EXISTS addressbookchanges"); - $pdo->query("DROP TABLE IF EXISTS cards"); - - $queries = explode( - ';', - file_get_contents(__DIR__ . '/../../../../examples/sql/sqlite.addressbooks.sql') - ); - - foreach($queries as $query) { - $query = trim($query," \r\n\t"); - if ($query) - $pdo->exec($query); - } - - return $pdo; - - } + public $driver = 'sqlite'; } - diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/CardTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/CardTest.php index cf8dbab0c..cb7d152c3 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/CardTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/CardTest.php @@ -18,16 +18,16 @@ class CardTest extends \PHPUnit_Framework_TestCase { $this->backend = new Backend\Mock(); $this->card = new Card( $this->backend, - array( - 'uri' => 'book1', - 'id' => 'foo', + [ + 'uri' => 'book1', + 'id' => 'foo', 'principaluri' => 'principals/user1', - ), - array( - 'uri' => 'card1', + ], + [ + 'uri' => 'card1', 'addressbookid' => 'foo', - 'carddata' => 'card', - ) + 'carddata' => 'card', + ] ); } @@ -42,15 +42,15 @@ class CardTest extends \PHPUnit_Framework_TestCase { $this->card = new Card( $this->backend, - array( - 'uri' => 'book1', - 'id' => 'foo', + [ + 'uri' => 'book1', + 'id' => 'foo', 'principaluri' => 'principals/user1', - ), - array( - 'uri' => 'card1', + ], + [ + 'uri' => 'card1', 'addressbookid' => 'foo', - ) + ] ); $result = $this->card->get(); $this->assertEquals("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD", $result); @@ -63,7 +63,7 @@ class CardTest extends \PHPUnit_Framework_TestCase { */ function testPut() { - $file = fopen('php://memory','r+'); + $file = fopen('php://memory', 'r+'); fwrite($file, 'newdata'); rewind($file); $this->card->put($file); @@ -88,7 +88,7 @@ class CardTest extends \PHPUnit_Framework_TestCase { function testGetETag() { - $this->assertEquals('"' . md5('card') . '"' , $this->card->getETag()); + $this->assertEquals('"' . md5('card') . '"', $this->card->getETag()); } @@ -96,19 +96,19 @@ class CardTest extends \PHPUnit_Framework_TestCase { $card = new Card( $this->backend, - array( - 'uri' => 'book1', - 'id' => 'foo', + [ + 'uri' => 'book1', + 'id' => 'foo', 'principaluri' => 'principals/user1', - ), - array( - 'uri' => 'card1', + ], + [ + 'uri' => 'card1', 'addressbookid' => 'foo', - 'carddata' => 'card', - 'etag' => '"blabla"', - ) + 'carddata' => 'card', + 'etag' => '"blabla"', + ] ); - $this->assertEquals('"blabla"' , $card->getETag()); + $this->assertEquals('"blabla"', $card->getETag()); } @@ -129,17 +129,17 @@ class CardTest extends \PHPUnit_Framework_TestCase { $card = new Card( $this->backend, - array( - 'uri' => 'book1', - 'id' => 'foo', + [ + 'uri' => 'book1', + 'id' => 'foo', 'principaluri' => 'principals/user1', - ), - array( - 'uri' => 'card1', + ], + [ + 'uri' => 'card1', 'addressbookid' => 'foo', - 'etag' => '"blabla"', - 'size' => 4, - ) + 'etag' => '"blabla"', + 'size' => 4, + ] ); $this->assertEquals(4, $card->getSize()); @@ -149,58 +149,53 @@ class CardTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('principals/user1', $this->card->getOwner()); $this->assertNull($this->card->getGroup()); - $this->assertEquals(array( - array( - 'privilege' => '{DAV:}read', - 'principal' => 'principals/user1', - 'protected' => true, - ), - array( - 'privilege' => '{DAV:}write', + $this->assertEquals([ + [ + 'privilege' => '{DAV:}all', 'principal' => 'principals/user1', 'protected' => true, - ), - ), $this->card->getACL()); + ], + ], $this->card->getACL()); } function testOverrideACL() { $card = new Card( $this->backend, - array( - 'uri' => 'book1', - 'id' => 'foo', + [ + 'uri' => 'book1', + 'id' => 'foo', 'principaluri' => 'principals/user1', - ), - array( - 'uri' => 'card1', + ], + [ + 'uri' => 'card1', 'addressbookid' => 'foo', - 'carddata' => 'card', - 'acl' => array( - array( + 'carddata' => 'card', + 'acl' => [ + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1', 'protected' => true, - ), - ), - ) + ], + ], + ] ); - $this->assertEquals(array( - array( + $this->assertEquals([ + [ 'privilege' => '{DAV:}read', 'principal' => 'principals/user1', 'protected' => true, - ), - ), $card->getACL()); + ], + ], $card->getACL()); } /** - * @expectedException Sabre\DAV\Exception\MethodNotAllowed + * @expectedException Sabre\DAV\Exception\Forbidden */ function testSetACL() { - $this->card->setACL(array()); + $this->card->setACL([]); } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/IDirectoryTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/IDirectoryTest.php index 431cd2524..4796a131f 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/IDirectoryTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/IDirectoryTest.php @@ -8,15 +8,15 @@ class IDirectoryTest extends \PHPUnit_Framework_TestCase { function testResourceType() { - $tree = array( + $tree = [ new DirectoryMock('directory') - ); + ]; $server = new DAV\Server($tree); $plugin = new Plugin(); $server->addPlugin($plugin); - $props = $server->getProperties('directory', array('{DAV:}resourcetype')); + $props = $server->getProperties('directory', ['{DAV:}resourcetype']); $this->assertTrue($props['{DAV:}resourcetype']->is('{' . Plugin::NS_CARDDAV . '}directory')); } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/MultiGetTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/MultiGetTest.php index b0ee45880..d79239d0f 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/MultiGetTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/MultiGetTest.php @@ -11,10 +11,10 @@ class MultiGetTest extends AbstractPluginTest { function testMultiGet() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'REPORT', - 'REQUEST_URI' => '/addressbooks/user1/book1', - )); + 'REQUEST_URI' => '/addressbooks/user1/book1', + ]); $request->setBody( ' @@ -37,27 +37,27 @@ class MultiGetTest extends AbstractPluginTest { $this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body); // using the client for parsing - $client = new DAV\Client(array('baseUri'=>'/')); + $client = new DAV\Client(['baseUri' => '/']); $result = $client->parseMultiStatus($response->body); - $this->assertEquals(array( - '/addressbooks/user1/book1/card1' => array( - 200 => array( - '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', - '{urn:ietf:params:xml:ns:carddav}address-data' => "BEGIN:VCARD\r\nVERSION:3.0\r\nUID:12345\r\nEND:VCARD\r\n", - ) - ) - ), $result); + $this->assertEquals([ + '/addressbooks/user1/book1/card1' => [ + 200 => [ + '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', + '{urn:ietf:params:xml:ns:carddav}address-data' => "BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD", + ] + ] + ], $result); } function testMultiGetVCard4() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'REPORT', - 'REQUEST_URI' => '/addressbooks/user1/book1', - )); + 'REQUEST_URI' => '/addressbooks/user1/book1', + ]); $request->setBody( ' @@ -80,20 +80,20 @@ class MultiGetTest extends AbstractPluginTest { $this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body); // using the client for parsing - $client = new DAV\Client(array('baseUri'=>'/')); + $client = new DAV\Client(['baseUri' => '/']); $result = $client->parseMultiStatus($response->body); $prodId = "PRODID:-//Sabre//Sabre VObject " . \Sabre\VObject\Version::VERSION . "//EN"; - $this->assertEquals(array( - '/addressbooks/user1/book1/card1' => array( - 200 => array( - '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', + $this->assertEquals([ + '/addressbooks/user1/book1/card1' => [ + 200 => [ + '{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD") . '"', '{urn:ietf:params:xml:ns:carddav}address-data' => "BEGIN:VCARD\r\nVERSION:4.0\r\n$prodId\r\nUID:12345\r\nEND:VCARD\r\n", - ) - ) - ), $result); + ] + ] + ], $result); } } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/PluginTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/PluginTest.php index 9c916350e..6962e7830 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/PluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/PluginTest.php @@ -3,7 +3,6 @@ namespace Sabre\CardDAV; use Sabre\DAV; -use Sabre\DAV\Xml\Property\Href; class PluginTest extends AbstractPluginTest { @@ -18,23 +17,23 @@ class PluginTest extends AbstractPluginTest { function testSupportedReportSet() { - $this->assertEquals(array( + $this->assertEquals([ '{' . Plugin::NS_CARDDAV . '}addressbook-multiget', '{' . Plugin::NS_CARDDAV . '}addressbook-query', - ), $this->plugin->getSupportedReportSet('addressbooks/user1/book1')); + ], $this->plugin->getSupportedReportSet('addressbooks/user1/book1')); } function testSupportedReportSetEmpty() { - $this->assertEquals(array( - ), $this->plugin->getSupportedReportSet('')); + $this->assertEquals([ + ], $this->plugin->getSupportedReportSet('')); } function testAddressBookHomeSet() { - $result = $this->server->getProperties('principals/user1', array('{' . Plugin::NS_CARDDAV . '}addressbook-home-set')); + $result = $this->server->getProperties('principals/user1', ['{' . Plugin::NS_CARDDAV . '}addressbook-home-set']); $this->assertEquals(1, count($result)); $this->assertTrue(isset($result['{' . Plugin::NS_CARDDAV . '}addressbook-home-set'])); @@ -44,11 +43,11 @@ class PluginTest extends AbstractPluginTest { function testDirectoryGateway() { - $result = $this->server->getProperties('principals/user1', array('{' . Plugin::NS_CARDDAV . '}directory-gateway')); + $result = $this->server->getProperties('principals/user1', ['{' . Plugin::NS_CARDDAV . '}directory-gateway']); $this->assertEquals(1, count($result)); $this->assertTrue(isset($result['{' . Plugin::NS_CARDDAV . '}directory-gateway'])); - $this->assertEquals(array('directory'), $result['{' . Plugin::NS_CARDDAV . '}directory-gateway']->getHrefs()); + $this->assertEquals(['directory'], $result['{' . Plugin::NS_CARDDAV . '}directory-gateway']->getHrefs()); } @@ -64,7 +63,7 @@ class PluginTest extends AbstractPluginTest { $r = $this->server->emit('onHTMLActionsPanel', [$this->server->tree->getNodeForPath('addressbooks/user1'), &$output]); $this->assertFalse($r); - $this->assertTrue(!!strpos($output,'Display name')); + $this->assertTrue(!!strpos($output, 'Display name')); } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/SogoStripContentTypeTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/SogoStripContentTypeTest.php index f828cc25b..0ba4fd669 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/SogoStripContentTypeTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/SogoStripContentTypeTest.php @@ -5,44 +5,44 @@ namespace Sabre\CardDAV; use Sabre\HTTP; use Sabre\DAV\PropFind; -class SogoStripContentType extends \Sabre\DAVServerTest { +class SogoStripContentTypeTest extends \Sabre\DAVServerTest { protected $setupCardDAV = true; - protected $carddavAddressBooks = array( - array( - 'id' => 1, - 'uri' => 'book1', + protected $carddavAddressBooks = [ + [ + 'id' => 1, + 'uri' => 'book1', 'principaluri' => 'principals/user1', - ), - ); - protected $carddavCards = array( - 1 => array( + ], + ]; + protected $carddavCards = [ + 1 => [ 'card1.vcf' => "BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD", - ), - ); + ], + ]; function testDontStrip() { - $result = $this->server->getProperties('addressbooks/user1/book1/card1.vcf',array('{DAV:}getcontenttype')); - $this->assertEquals(array( + $result = $this->server->getProperties('addressbooks/user1/book1/card1.vcf', ['{DAV:}getcontenttype']); + $this->assertEquals([ '{DAV:}getcontenttype' => 'text/vcard; charset=utf-8' - ), $result); + ], $result); } function testStrip() { - $this->server->httpRequest = HTTP\Sapi::createFromServerArray(array( + $this->server->httpRequest = HTTP\Sapi::createFromServerArray([ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0.2) Gecko/20120216 Thunderbird/10.0.2 Lightning/1.2.1', - )); - $result = $this->server->getProperties('addressbooks/user1/book1/card1.vcf',array('{DAV:}getcontenttype')); - $this->assertEquals(array( + ]); + $result = $this->server->getProperties('addressbooks/user1/book1/card1.vcf', ['{DAV:}getcontenttype']); + $this->assertEquals([ '{DAV:}getcontenttype' => 'text/x-vcard' - ), $result); + ], $result); } function testDontTouchOtherMimeTypes() { - $this->server->httpRequest = new HTTP\Request('GET','/addressbooks/user1/book1/card1.vcf', [ + $this->server->httpRequest = new HTTP\Request('GET', '/addressbooks/user1/book1/card1.vcf', [ 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0.2) Gecko/20120216 Thunderbird/10.0.2 Lightning/1.2.1', ]); diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/TestUtil.php b/vendor/sabre/dav/tests/Sabre/CardDAV/TestUtil.php index c9cc10d35..ec8a3501e 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/TestUtil.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/TestUtil.php @@ -2,8 +2,6 @@ namespace Sabre\CardDAV; -use PDO; - class TestUtil { static function getBackend() { @@ -22,18 +20,18 @@ class TestUtil { $addressbookId = $backend->createAddressBook( 'principals/user1', 'UUID-123467', - array( - '{DAV:}displayname' => 'user1 addressbook', + [ + '{DAV:}displayname' => 'user1 addressbook', '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'AddressBook description', - ) + ] ); $backend->createAddressBook( 'principals/user1', 'UUID-123468', - array( - '{DAV:}displayname' => 'user1 addressbook2', + [ + '{DAV:}displayname' => 'user1 addressbook2', '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'AddressBook description', - ) + ] ); $backend->createCard($addressbookId, 'UUID-2345', self::getTestCardData()); return $pdo; diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/VCFExportTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/VCFExportTest.php index 71fde719d..82d82fadd 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/VCFExportTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/VCFExportTest.php @@ -10,21 +10,21 @@ class VCFExportTest extends \Sabre\DAVServerTest { protected $autoLogin = 'user1'; protected $setupACL = true; - protected $carddavAddressBooks = array( - array( - 'id' => 'book1', - 'uri' => 'book1', + protected $carddavAddressBooks = [ + [ + 'id' => 'book1', + 'uri' => 'book1', 'principaluri' => 'principals/user1', - ) - ); - protected $carddavCards = array( - 'book1' => array( + ] + ]; + protected $carddavCards = [ + 'book1' => [ "card1" => "BEGIN:VCARD\r\nFN:Person1\r\nEND:VCARD\r\n", "card2" => "BEGIN:VCARD\r\nFN:Person2\r\nEND:VCARD", "card3" => "BEGIN:VCARD\r\nFN:Person3\r\nEND:VCARD\r\n", "card4" => "BEGIN:VCARD\nFN:Person4\nEND:VCARD\n", - ) - ); + ] + ]; function setUp() { @@ -50,11 +50,11 @@ class VCFExportTest extends \Sabre\DAVServerTest { function testExport() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_URI' => '/addressbooks/user1/book1?export', - 'QUERY_STRING' => 'export', + $request = HTTP\Sapi::createFromServerArray([ + 'REQUEST_URI' => '/addressbooks/user1/book1?export', + 'QUERY_STRING' => 'export', 'REQUEST_METHOD' => 'GET', - )); + ]); $response = $this->request($request); $this->assertEquals(200, $response->status, $response->body); @@ -73,7 +73,7 @@ FN:Person4 END:VCARD "; // We actually expected windows line endings - $expected = str_replace("\n","\r\n", $expected); + $expected = str_replace("\n", "\r\n", $expected); $this->assertEquals($expected, $response->body); @@ -89,4 +89,47 @@ END:VCARD } + function testContentDisposition() { + + $request = new HTTP\Request( + 'GET', + '/addressbooks/user1/book1?export' + ); + + $response = $this->request($request, 200); + $this->assertEquals('text/directory', $response->getHeader('Content-Type')); + $this->assertEquals( + 'attachment; filename="book1-' . date('Y-m-d') . '.vcf"', + $response->getHeader('Content-Disposition') + ); + + } + + function testContentDispositionBadChars() { + + $this->carddavBackend->createAddressBook( + 'principals/user1', + 'book-b_ad"(ch)ars', + [] + ); + $this->carddavBackend->createCard( + 'book-b_ad"(ch)ars', + 'card1', + "BEGIN:VCARD\r\nFN:Person1\r\nEND:VCARD\r\n" + ); + + $request = new HTTP\Request( + 'GET', + '/addressbooks/user1/book-b_ad"(ch)ars?export' + ); + + $response = $this->request($request, 200); + $this->assertEquals('text/directory', $response->getHeader('Content-Type')); + $this->assertEquals( + 'attachment; filename="book-b_adchars-' . date('Y-m-d') . '.vcf"', + $response->getHeader('Content-Disposition') + ); + + } + } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/ValidateFilterTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/ValidateFilterTest.php index c87716c10..57ac21b4a 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/ValidateFilterTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/ValidateFilterTest.php @@ -48,35 +48,35 @@ HELLO; // Check if TITLE is defined $filter1 = - array('name' => 'title', 'is-not-defined' => false, 'param-filters' => array(), 'text-matches' => array()); + ['name' => 'title', 'is-not-defined' => false, 'param-filters' => [], 'text-matches' => []]; // Check if FOO is defined $filter2 = - array('name' => 'foo', 'is-not-defined' => false, 'param-filters' => array(), 'text-matches' => array()); + ['name' => 'foo', 'is-not-defined' => false, 'param-filters' => [], 'text-matches' => []]; // Check if TITLE is not defined $filter3 = - array('name' => 'title', 'is-not-defined' => true, 'param-filters' => array(), 'text-matches' => array()); + ['name' => 'title', 'is-not-defined' => true, 'param-filters' => [], 'text-matches' => []]; // Check if FOO is not defined $filter4 = - array('name' => 'foo', 'is-not-defined' => true, 'param-filters' => array(), 'text-matches' => array()); + ['name' => 'foo', 'is-not-defined' => true, 'param-filters' => [], 'text-matches' => []]; // Check if TEL[TYPE] is defined $filter5 = - array( - 'name' => 'tel', + [ + 'name' => 'tel', 'is-not-defined' => false, - 'test' => 'anyof', - 'param-filters' => array( - array( - 'name' => 'type', + 'test' => 'anyof', + 'param-filters' => [ + [ + 'name' => 'type', 'is-not-defined' => false, - 'text-match' => null - ), - ), - 'text-matches' => array(), - ); + 'text-match' => null + ], + ], + 'text-matches' => [], + ]; // Check if TEL[FOO] is defined $filter6 = $filter5; @@ -101,20 +101,20 @@ HELLO; // Check if URL contains 'google' $filter11 = - array( - 'name' => 'url', + [ + 'name' => 'url', 'is-not-defined' => false, - 'test' => 'anyof', - 'param-filters' => array(), - 'text-matches' => array( - array( - 'match-type' => 'contains', - 'value' => 'google', + 'test' => 'anyof', + 'param-filters' => [], + 'text-matches' => [ + [ + 'match-type' => 'contains', + 'value' => 'google', 'negate-condition' => false, - 'collation' => 'i;octet', - ), - ), - ); + 'collation' => 'i;octet', + ], + ], + ]; // Check if URL contains 'bing' $filter12 = $filter11; @@ -131,12 +131,12 @@ HELLO; // Param filter with text $filter15 = $filter5; - $filter15['param-filters'][0]['text-match'] = array( - 'match-type' => 'contains', - 'value' => 'WORK', - 'collation' => 'i;octet', + $filter15['param-filters'][0]['text-match'] = [ + 'match-type' => 'contains', + 'value' => 'WORK', + 'collation' => 'i;octet', 'negate-condition' => false, - ); + ]; $filter16 = $filter15; $filter16['param-filters'][0]['text-match']['negate-condition'] = true; @@ -144,60 +144,60 @@ HELLO; // Param filter + text filter $filter17 = $filter5; $filter17['test'] = 'anyof'; - $filter17['text-matches'][] = array( - 'match-type' => 'contains', - 'value' => '444', - 'collation' => 'i;octet', + $filter17['text-matches'][] = [ + 'match-type' => 'contains', + 'value' => '444', + 'collation' => 'i;octet', 'negate-condition' => false, - ); + ]; $filter18 = $filter17; $filter18['text-matches'][0]['negate-condition'] = true; $filter18['test'] = 'allof'; - return array( + return [ // Basic filters - array($body1, array($filter1), 'anyof',true), - array($body1, array($filter2), 'anyof',false), - array($body1, array($filter3), 'anyof',false), - array($body1, array($filter4), 'anyof',true), + [$body1, [$filter1], 'anyof',true], + [$body1, [$filter2], 'anyof',false], + [$body1, [$filter3], 'anyof',false], + [$body1, [$filter4], 'anyof',true], // Combinations - array($body1, array($filter1, $filter2), 'anyof',true), - array($body1, array($filter1, $filter2), 'allof',false), - array($body1, array($filter1, $filter4), 'anyof',true), - array($body1, array($filter1, $filter4), 'allof',true), - array($body1, array($filter2, $filter3), 'anyof',false), - array($body1, array($filter2, $filter3), 'allof',false), + [$body1, [$filter1, $filter2], 'anyof',true], + [$body1, [$filter1, $filter2], 'allof',false], + [$body1, [$filter1, $filter4], 'anyof',true], + [$body1, [$filter1, $filter4], 'allof',true], + [$body1, [$filter2, $filter3], 'anyof',false], + [$body1, [$filter2, $filter3], 'allof',false], // Basic parameters - array($body1, array($filter5), 'anyof', true, 'TEL;TYPE is defined, so this should return true'), - array($body1, array($filter6), 'anyof', false, 'TEL;FOO is not defined, so this should return false'), + [$body1, [$filter5], 'anyof', true, 'TEL;TYPE is defined, so this should return true'], + [$body1, [$filter6], 'anyof', false, 'TEL;FOO is not defined, so this should return false'], - array($body1, array($filter7), 'anyof', false, 'TEL;TYPE is defined, so this should return false'), - array($body1, array($filter8), 'anyof', true, 'TEL;TYPE is not defined, so this should return true'), + [$body1, [$filter7], 'anyof', false, 'TEL;TYPE is defined, so this should return false'], + [$body1, [$filter8], 'anyof', true, 'TEL;TYPE is not defined, so this should return true'], // Combined parameters - array($body1, array($filter9), 'anyof', true), - array($body1, array($filter10), 'anyof', false), + [$body1, [$filter9], 'anyof', true], + [$body1, [$filter10], 'anyof', false], // Text-filters - array($body1, array($filter11), 'anyof', true), - array($body1, array($filter12), 'anyof', false), - array($body1, array($filter13), 'anyof', false), - array($body1, array($filter14), 'anyof', true), + [$body1, [$filter11], 'anyof', true], + [$body1, [$filter12], 'anyof', false], + [$body1, [$filter13], 'anyof', false], + [$body1, [$filter14], 'anyof', true], // Param filter with text-match - array($body1, array($filter15), 'anyof', true), - array($body1, array($filter16), 'anyof', false), + [$body1, [$filter15], 'anyof', true], + [$body1, [$filter16], 'anyof', false], // Param filter + text filter - array($body1, array($filter17), 'anyof', true), - array($body1, array($filter18), 'anyof', false), - array($body1, array($filter18), 'anyof', false), - ); + [$body1, [$filter17], 'anyof', true], + [$body1, [$filter18], 'anyof', false], + [$body1, [$filter18], 'anyof', false], + ]; } diff --git a/vendor/sabre/dav/tests/Sabre/CardDAV/ValidateVCardTest.php b/vendor/sabre/dav/tests/Sabre/CardDAV/ValidateVCardTest.php index ad8495c13..dda8a0c37 100644 --- a/vendor/sabre/dav/tests/Sabre/CardDAV/ValidateVCardTest.php +++ b/vendor/sabre/dav/tests/Sabre/CardDAV/ValidateVCardTest.php @@ -15,20 +15,20 @@ class ValidateVCardTest extends \PHPUnit_Framework_TestCase { function setUp() { - $addressbooks = array( - array( - 'id' => 'addressbook1', + $addressbooks = [ + [ + 'id' => 'addressbook1', 'principaluri' => 'principals/admin', - 'uri' => 'addressbook1', - ) - ); + 'uri' => 'addressbook1', + ] + ]; - $this->cardBackend = new Backend\Mock($addressbooks,array()); + $this->cardBackend = new Backend\Mock($addressbooks, []); $principalBackend = new DAVACL\PrincipalBackend\Mock(); - $tree = array( + $tree = [ new AddressBookRoot($principalBackend, $this->cardBackend), - ); + ]; $this->server = new DAV\Server($tree); $this->server->sapi = new HTTP\SapiMock(); @@ -42,21 +42,36 @@ class ValidateVCardTest extends \PHPUnit_Framework_TestCase { } - function request(HTTP\Request $request) { + function request(HTTP\Request $request, $expectedStatus = null) { $this->server->httpRequest = $request; $this->server->exec(); + if ($expectedStatus) { + + $realStatus = $this->server->httpResponse->getStatus(); + + $msg = ''; + if ($realStatus !== $expectedStatus) { + $msg = 'Response body: ' . $this->server->httpResponse->getBodyAsString(); + } + $this->assertEquals( + $expectedStatus, + $realStatus, + $msg + ); + } + return $this->server->httpResponse; } function testCreateFile() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/addressbooks/admin/addressbook1/blabla.vcf', - )); + 'REQUEST_URI' => '/addressbooks/admin/addressbook1/blabla.vcf', + ]); $response = $this->request($request); @@ -66,38 +81,159 @@ class ValidateVCardTest extends \PHPUnit_Framework_TestCase { function testCreateFileValid() { - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/addressbooks/admin/addressbook1/blabla.vcf', - )); - $request->setBody("BEGIN:VCARD\r\nUID:foo\r\nEND:VCARD\r\n"); - - $response = $this->request($request); + $request = new HTTP\Request( + 'PUT', + '/addressbooks/admin/addressbook1/blabla.vcf' + ); - $this->assertEquals(201, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); - $expected = array( - 'uri' => 'blabla.vcf', - 'carddata' => "BEGIN:VCARD\r\nUID:foo\r\nEND:VCARD\r\n", + $vcard = <<setBody($vcard); + + $response = $this->request($request, 201); + + // The custom Ew header should not be set + $this->assertNull( + $response->getHeader('X-Sabre-Ew-Gross') + ); + // Valid, non-auto-fixed responses should contain an ETag. + $this->assertTrue( + $response->getHeader('ETag') !== null, + 'We did not receive an etag' ); - $this->assertEquals($expected, $this->cardBackend->getCard('addressbook1','blabla.vcf')); + + $expected = [ + 'uri' => 'blabla.vcf', + 'carddata' => $vcard, + 'size' => strlen($vcard), + 'etag' => '"' . md5($vcard) . '"', + ]; + + $this->assertEquals($expected, $this->cardBackend->getCard('addressbook1', 'blabla.vcf')); } - function testCreateFileNoUID() { + /** + * This test creates an intentionally broken vCard that vobject is able + * to automatically repair. + * + * @depends testCreateFileValid + */ + function testCreateVCardAutoFix() { $request = new HTTP\Request( 'PUT', '/addressbooks/admin/addressbook1/blabla.vcf' ); - $request->setBody("BEGIN:VCARD\r\nEND:VCARD\r\n"); - $response = $this->request($request); + // The error in this vcard is that there's not enough semi-colons in N + $vcard = <<assertEquals(201, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); + $request->setBody($vcard); + + $response = $this->request($request, 201); + + // Auto-fixed vcards should NOT return an etag + $this->assertNull( + $response->getHeader('ETag') + ); + + // We should have gotten an Ew header + $this->assertNotNull( + $response->getHeader('X-Sabre-Ew-Gross') + ); + + $expectedVCard = << 'blabla.vcf', + 'carddata' => $expectedVCard, + 'size' => strlen($expectedVCard), + 'etag' => '"' . md5($expectedVCard) . '"', + ]; + + $this->assertEquals($expected, $this->cardBackend->getCard('addressbook1', 'blabla.vcf')); - $foo = $this->cardBackend->getCard('addressbook1','blabla.vcf'); - $this->assertTrue(strpos($foo['carddata'],'UID')!==false); + } + + /** + * This test creates an intentionally broken vCard that vobject is able + * to automatically repair. + * + * However, we're supplying a heading asking the server to treat the + * request as strict, so the server should still let the request fail. + * + * @depends testCreateFileValid + */ + function testCreateVCardStrictFail() { + + $request = new HTTP\Request( + 'PUT', + '/addressbooks/admin/addressbook1/blabla.vcf', + [ + 'Prefer' => 'handling=strict', + ] + ); + + // The error in this vcard is that there's not enough semi-colons in N + $vcard = <<setBody($vcard); + $this->request($request, 415); + + } + + function testCreateFileNoUID() { + + $request = new HTTP\Request( + 'PUT', + '/addressbooks/admin/addressbook1/blabla.vcf' + ); + $vcard = <<setBody($vcard); + + $response = $this->request($request, 201); + + $foo = $this->cardBackend->getCard('addressbook1', 'blabla.vcf'); + $this->assertTrue( + strpos($foo['carddata'], 'UID') !== false, + print_r($foo, true) + ); } function testCreateFileJson() { @@ -106,23 +242,23 @@ class ValidateVCardTest extends \PHPUnit_Framework_TestCase { 'PUT', '/addressbooks/admin/addressbook1/blabla.vcf' ); - $request->setBody('[ "vcard" , [ [ "UID" , {}, "text", "foo" ] ] ]'); + $request->setBody('[ "vcard" , [ [ "VERSION", {}, "text", "4.0"], [ "UID" , {}, "text", "foo" ], [ "FN", {}, "text", "FirstName LastName"] ] ]'); $response = $this->request($request); $this->assertEquals(201, $response->status, 'Incorrect status returned! Full response body: ' . $response->body); - $foo = $this->cardBackend->getCard('addressbook1','blabla.vcf'); - $this->assertEquals("BEGIN:VCARD\r\nUID:foo\r\nEND:VCARD\r\n", $foo['carddata']); + $foo = $this->cardBackend->getCard('addressbook1', 'blabla.vcf'); + $this->assertEquals("BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nFN:FirstName LastName\r\nEND:VCARD\r\n", $foo['carddata']); } function testCreateFileVCalendar() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/addressbooks/admin/addressbook1/blabla.vcf', - )); + 'REQUEST_URI' => '/addressbooks/admin/addressbook1/blabla.vcf', + ]); $request->setBody("BEGIN:VCALENDAR\r\nEND:VCALENDAR\r\n"); $response = $this->request($request); @@ -133,40 +269,37 @@ class ValidateVCardTest extends \PHPUnit_Framework_TestCase { function testUpdateFile() { - $this->cardBackend->createCard('addressbook1','blabla.vcf','foo'); - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/addressbooks/admin/addressbook1/blabla.vcf', - )); - - $response = $this->request($request); + $this->cardBackend->createCard('addressbook1', 'blabla.vcf', 'foo'); + $request = new HTTP\Request( + 'PUT', + '/addressbooks/admin/addressbook1/blabla.vcf' + ); - $this->assertEquals(415, $response->status); + $response = $this->request($request, 415); } function testUpdateFileParsableBody() { - $this->cardBackend->createCard('addressbook1','blabla.vcf','foo'); - $request = HTTP\Sapi::createFromServerArray(array( - 'REQUEST_METHOD' => 'PUT', - 'REQUEST_URI' => '/addressbooks/admin/addressbook1/blabla.vcf', - )); - $body = "BEGIN:VCARD\r\nUID:foo\r\nEND:VCARD\r\n"; - $request->setBody($body); + $this->cardBackend->createCard('addressbook1', 'blabla.vcf', 'foo'); + $request = new HTTP\Request( + 'PUT', + '/addressbooks/admin/addressbook1/blabla.vcf' + ); - $response = $this->request($request); + $body = "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nFN:FirstName LastName\r\nEND:VCARD\r\n"; + $request->setBody($body); - $this->assertEquals(204, $response->status); + $response = $this->request($request, 204); - $expected = array( + $expected = [ 'uri' => 'blabla.vcf', - 'carddata' => $body, - ); + 'carddata' => $body, + 'size' => strlen($body), + 'etag' => '"' . md5($body) . '"', + ]; - $this->assertEquals($expected, $this->cardBackend->getCard('addressbook1','blabla.vcf')); + $this->assertEquals($expected, $this->cardBackend->getCard('addressbook1', 'blabla.vcf')); } } - -?> diff --git a/vendor/sabre/dav/tests/Sabre/DAV/AbstractServer.php b/vendor/sabre/dav/tests/Sabre/DAV/AbstractServer.php index b5b8d64ee..6a8d389a0 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/AbstractServer.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/AbstractServer.php @@ -24,7 +24,7 @@ abstract class AbstractServer extends \PHPUnit_Framework_TestCase { $this->server->sapi = new HTTP\SapiMock(); $this->server->httpResponse = $this->response; $this->server->debugExceptions = true; - $this->deleteTree(SABRE_TEMPDIR,false); + $this->deleteTree(SABRE_TEMPDIR, false); file_put_contents(SABRE_TEMPDIR . '/test.txt', 'Test contents'); mkdir(SABRE_TEMPDIR . '/dir'); file_put_contents(SABRE_TEMPDIR . '/dir/child.txt', 'Child contents'); @@ -34,7 +34,7 @@ abstract class AbstractServer extends \PHPUnit_Framework_TestCase { function tearDown() { - $this->deleteTree(SABRE_TEMPDIR,false); + $this->deleteTree(SABRE_TEMPDIR, false); } @@ -44,12 +44,12 @@ abstract class AbstractServer extends \PHPUnit_Framework_TestCase { } - private function deleteTree($path,$deleteRoot = true) { + private function deleteTree($path, $deleteRoot = true) { - foreach(scandir($path) as $node) { + foreach (scandir($path) as $node) { - if ($node=='.' || $node=='.svn' || $node=='..') continue; - $myPath = $path.'/'. $node; + if ($node == '.' || $node == '.svn' || $node == '..') continue; + $myPath = $path . '/' . $node; if (is_file($myPath)) { unlink($myPath); } else { diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php index 7d7a59898..455403aff 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php @@ -2,7 +2,6 @@ namespace Sabre\DAV\Auth\Backend; -use Sabre\DAV; use Sabre\HTTP; class AbstractBasicTest extends \PHPUnit_Framework_TestCase { @@ -22,10 +21,10 @@ class AbstractBasicTest extends \PHPUnit_Framework_TestCase { function testCheckUnknownUser() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'PHP_AUTH_USER' => 'username', - 'PHP_AUTH_PW' => 'wrongpassword', - )); + 'PHP_AUTH_PW' => 'wrongpassword', + ]); $response = new HTTP\Response(); $backend = new AbstractBasicMock(); @@ -38,10 +37,10 @@ class AbstractBasicTest extends \PHPUnit_Framework_TestCase { function testCheckSuccess() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'PHP_AUTH_USER' => 'username', - 'PHP_AUTH_PW' => 'password', - )); + 'PHP_AUTH_PW' => 'password', + ]); $response = new HTTP\Response(); $backend = new AbstractBasicMock(); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractDigestTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractDigestTest.php index 8ef416c37..14c72aaa0 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractDigestTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractDigestTest.php @@ -2,7 +2,6 @@ namespace Sabre\DAV\Auth\Backend; -use Sabre\DAV; use Sabre\HTTP; class AbstractDigestTest extends \PHPUnit_Framework_TestCase { @@ -87,12 +86,12 @@ class AbstractDigestTest extends \PHPUnit_Framework_TestCase { function testCheck() { $digestHash = md5('HELLO:12345:1:1:auth:' . md5('GET:/')); - $header = 'username=user, realm=myRealm, nonce=12345, uri=/, response='.$digestHash.', opaque=1, qop=auth, nc=1, cnonce=1'; - $request = HTTP\Sapi::createFromServerArray(array( + $header = 'username=user, realm=myRealm, nonce=12345, uri=/, response=' . $digestHash . ', opaque=1, qop=auth, nc=1, cnonce=1'; + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'GET', 'PHP_AUTH_DIGEST' => $header, 'REQUEST_URI' => '/', - )); + ]); $response = new HTTP\Response(); @@ -127,10 +126,10 @@ class AbstractDigestMock extends AbstractDigest { function getDigestHash($realm, $userName) { - switch($userName) { + switch ($userName) { case 'null' : return null; case 'false' : return false; - case 'array' : return array(); + case 'array' : return []; case 'user' : return 'HELLO'; } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractPDOTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractPDOTest.php index d22923d51..b14e9fa2e 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractPDOTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractPDOTest.php @@ -2,11 +2,21 @@ namespace Sabre\DAV\Auth\Backend; -use Sabre\DAV; - abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { - abstract function getPDO(); + use \Sabre\DAV\DbTestHelperTrait; + + function setUp() { + + $this->dropTables('users'); + $this->createSchema('users'); + + $this->getPDO()->query( + "INSERT INTO users (username,digesta1) VALUES ('user','hash')" + + ); + + } function testConstruct() { @@ -24,11 +34,11 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $pdo = $this->getPDO(); $backend = new PDO($pdo); - $this->assertNull($backend->getDigestHash('realm','blabla')); + $this->assertNull($backend->getDigestHash('realm', 'blabla')); $expected = 'hash'; - $this->assertEquals($expected, $backend->getDigestHash('realm','user')); + $this->assertEquals($expected, $backend->getDigestHash('realm', 'user')); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/ApacheTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/ApacheTest.php index 697b593db..29cbc2162 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/ApacheTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/ApacheTest.php @@ -2,7 +2,6 @@ namespace Sabre\DAV\Auth\Backend; -use Sabre\DAV; use Sabre\HTTP; class ApacheTest extends \PHPUnit_Framework_TestCase { diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/FileTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/FileTest.php index d2e5fe49b..9b66d642f 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/FileTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/FileTest.php @@ -6,7 +6,7 @@ class FileTest extends \PHPUnit_Framework_TestCase { function tearDown() { - if (file_exists(SABRE_TEMPDIR . '/filebackend')) unlink(SABRE_TEMPDIR .'/filebackend'); + if (file_exists(SABRE_TEMPDIR . '/filebackend')) unlink(SABRE_TEMPDIR . '/filebackend'); } @@ -22,20 +22,20 @@ class FileTest extends \PHPUnit_Framework_TestCase { */ function testLoadFileBroken() { - file_put_contents(SABRE_TEMPDIR . '/backend','user:realm:hash'); + file_put_contents(SABRE_TEMPDIR . '/backend', 'user:realm:hash'); $file = new File(); - $file->loadFile(SABRE_TEMPDIR .'/backend'); + $file->loadFile(SABRE_TEMPDIR . '/backend'); } function testLoadFile() { - file_put_contents(SABRE_TEMPDIR . '/backend','user:realm:' . md5('user:realm:password')); + file_put_contents(SABRE_TEMPDIR . '/backend', 'user:realm:' . md5('user:realm:password')); $file = new File(); $file->loadFile(SABRE_TEMPDIR . '/backend'); - $this->assertFalse($file->getDigestHash('realm','blabla')); - $this->assertEquals(md5('user:realm:password'), $file->getDigestHash('realm','user')); + $this->assertFalse($file->getDigestHash('realm', 'blabla')); + $this->assertEquals(md5('user:realm:password'), $file->getDigestHash('realm', 'user')); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/Mock.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/Mock.php index a782cb74d..b30b3f143 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/Mock.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/Mock.php @@ -2,10 +2,8 @@ namespace Sabre\DAV\Auth\Backend; -use - Sabre\DAV, - Sabre\HTTP\RequestInterface, - Sabre\HTTP\ResponseInterface; +use Sabre\HTTP\RequestInterface; +use Sabre\HTTP\ResponseInterface; class Mock implements BackendInterface { diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/PDOMySQLTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/PDOMySQLTest.php index 8de2be667..18f59793a 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/PDOMySQLTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/PDOMySQLTest.php @@ -2,32 +2,8 @@ namespace Sabre\DAV\Auth\Backend; -require_once 'Sabre/TestUtil.php'; - class PDOMySQLTest extends AbstractPDOTest { - function getPDO() { - - if (!SABRE_HASMYSQL) $this->markTestSkipped('MySQL driver is not available, or not properly configured'); - $pdo = \Sabre\TestUtil::getMySQLDB(); - if (!$pdo) $this->markTestSkipped('Could not connect to MySQL database'); - $pdo->query("DROP TABLE IF EXISTS users"); - $pdo->query(<<query("INSERT INTO users (username,digesta1,email,displayname) VALUES ('user','hash','user@example.org','User')"); - - return $pdo; - - } + public $driver = 'mysql'; } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/PDOSqliteTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/PDOSqliteTest.php index abfb031bb..b1f382237 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/PDOSqliteTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/PDOSqliteTest.php @@ -2,27 +2,8 @@ namespace Sabre\DAV\Auth\Backend; -require_once 'Sabre/DAV/Auth/Backend/AbstractPDOTest.php'; +class PDOSqliteTest extends AbstractPDOTest { -class PDOSQLiteTest extends AbstractPDOTest { - - function tearDown() { - - if (file_exists(SABRE_TEMPDIR . '/pdobackend')) unlink(SABRE_TEMPDIR . '/pdobackend'); - if (file_exists(SABRE_TEMPDIR . '/pdobackend2')) unlink(SABRE_TEMPDIR . '/pdobackend2'); - - } - - function getPDO() { - - if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available'); - $pdo = new \PDO('sqlite:'.SABRE_TEMPDIR.'/pdobackend'); - $pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); - $pdo->query('CREATE TABLE users (username TEXT, digesta1 TEXT, email VARCHAR(80), displayname VARCHAR(80))'); - $pdo->query('INSERT INTO users VALUES ("user","hash","user@example.org","User")'); - - return $pdo; - - } + public $driver = 'sqlite'; } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php index 0ac9e0613..3ed79a7da 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php @@ -5,13 +5,11 @@ namespace Sabre\DAV\Auth; use Sabre\HTTP; use Sabre\DAV; -require_once 'Sabre/HTTP/ResponseMock.php'; - class PluginTest extends \PHPUnit_Framework_TestCase { function testInit() { - $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla')); + $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla')); $plugin = new Plugin(new Backend\Mock()); $this->assertTrue($plugin instanceof Plugin); $fakeServer->addPlugin($plugin); @@ -25,7 +23,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase { */ function testAuthenticate() { - $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla')); + $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla')); $plugin = new Plugin(new Backend\Mock()); $fakeServer->addPlugin($plugin); $this->assertTrue( @@ -40,7 +38,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase { */ function testAuthenticateFail() { - $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla')); + $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla')); $backend = new Backend\Mock(); $backend->fail = true; @@ -55,7 +53,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase { */ function testMultipleBackend() { - $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla')); + $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla')); $backend1 = new Backend\Mock(); $backend2 = new Backend\Mock(); $backend2->fail = true; @@ -77,7 +75,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase { */ function testNoAuthBackend() { - $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla')); + $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla')); $plugin = new Plugin(); $fakeServer->addPlugin($plugin); @@ -90,7 +88,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase { */ function testInvalidCheckResponse() { - $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla')); + $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla')); $backend = new Backend\Mock(); $backend->invalidCheckResponse = true; @@ -105,7 +103,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase { */ function testGetCurrentPrincipal() { - $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla')); + $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla')); $plugin = new Plugin(new Backend\Mock()); $fakeServer->addPlugin($plugin); $fakeServer->emit('beforeMethod', [new HTTP\Request(), new HTTP\Response()]); @@ -113,18 +111,4 @@ class PluginTest extends \PHPUnit_Framework_TestCase { } - /** - * @depends testAuthenticate - */ - function testGetCurrentUser() { - - $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla')); - $plugin = new Plugin(new Backend\Mock()); - $fakeServer->addPlugin($plugin); - $fakeServer->emit('beforeMethod', [new HTTP\Request(), new HTTP\Response()]); - $this->assertEquals('admin', $plugin->getCurrentUser()); - - } - } - diff --git a/vendor/sabre/dav/tests/Sabre/DAV/BasicNodeTest.php b/vendor/sabre/dav/tests/Sabre/DAV/BasicNodeTest.php index 155c785f8..ec104ec80 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/BasicNodeTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/BasicNodeTest.php @@ -7,7 +7,7 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\Forbidden */ - public function testPut() { + function testPut() { $file = new FileMock(); $file->put('hi'); @@ -17,29 +17,29 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\Forbidden */ - public function testGet() { + function testGet() { $file = new FileMock(); $file->get(); } - public function testGetSize() { + function testGetSize() { $file = new FileMock(); - $this->assertEquals(0,$file->getSize()); + $this->assertEquals(0, $file->getSize()); } - public function testGetETag() { + function testGetETag() { $file = new FileMock(); $this->assertNull($file->getETag()); } - public function testGetContentType() { + function testGetContentType() { $file = new FileMock(); $this->assertNull($file->getContentType()); @@ -49,7 +49,7 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\Forbidden */ - public function testDelete() { + function testDelete() { $file = new FileMock(); $file->delete(); @@ -59,24 +59,24 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\Forbidden */ - public function testSetName() { + function testSetName() { $file = new FileMock(); $file->setName('hi'); } - public function testGetLastModified() { + function testGetLastModified() { $file = new FileMock(); // checking if lastmod is within the range of a few seconds $lastMod = $file->getLastModified(); - $compareTime = ($lastMod + 1)-time(); + $compareTime = ($lastMod + 1) - time(); $this->assertTrue($compareTime < 3); } - public function testGetChild() { + function testGetChild() { $dir = new DirectoryMock(); $file = $dir->getChild('mockfile'); @@ -84,14 +84,14 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { } - public function testChildExists() { + function testChildExists() { $dir = new DirectoryMock(); $this->assertTrue($dir->childExists('mockfile')); } - public function testChildExistsFalse() { + function testChildExistsFalse() { $dir = new DirectoryMock(); $this->assertFalse($dir->childExists('mockfile2')); @@ -101,7 +101,7 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\NotFound */ - public function testGetChild404() { + function testGetChild404() { $dir = new DirectoryMock(); $file = $dir->getChild('blabla'); @@ -111,26 +111,26 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\Forbidden */ - public function testCreateFile() { + function testCreateFile() { $dir = new DirectoryMock(); - $dir->createFile('hello','data'); + $dir->createFile('hello', 'data'); } /** * @expectedException Sabre\DAV\Exception\Forbidden */ - public function testCreateDirectory() { + function testCreateDirectory() { $dir = new DirectoryMock(); $dir->createDirectory('hello'); } - public function testSimpleDirectoryConstruct() { + function testSimpleDirectoryConstruct() { - $dir = new SimpleCollection('simpledir',array()); + $dir = new SimpleCollection('simpledir', []); $this->assertInstanceOf('Sabre\DAV\SimpleCollection', $dir); } @@ -138,13 +138,13 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { /** * @depends testSimpleDirectoryConstruct */ - public function testSimpleDirectoryConstructChild() { + function testSimpleDirectoryConstructChild() { $file = new FileMock(); - $dir = new SimpleCollection('simpledir',array($file)); + $dir = new SimpleCollection('simpledir', [$file]); $file2 = $dir->getChild('mockfile'); - $this->assertEquals($file,$file2); + $this->assertEquals($file, $file2); } @@ -152,23 +152,23 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { * @expectedException Sabre\DAV\Exception * @depends testSimpleDirectoryConstruct */ - public function testSimpleDirectoryBadParam() { + function testSimpleDirectoryBadParam() { - $dir = new SimpleCollection('simpledir',array('string shouldn\'t be here')); + $dir = new SimpleCollection('simpledir', ['string shouldn\'t be here']); } /** * @depends testSimpleDirectoryConstruct */ - public function testSimpleDirectoryAddChild() { + function testSimpleDirectoryAddChild() { $file = new FileMock(); $dir = new SimpleCollection('simpledir'); $dir->addChild($file); $file2 = $dir->getChild('mockfile'); - $this->assertEquals($file,$file2); + $this->assertEquals($file, $file2); } @@ -176,23 +176,23 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { * @depends testSimpleDirectoryConstruct * @depends testSimpleDirectoryAddChild */ - public function testSimpleDirectoryGetChildren() { + function testSimpleDirectoryGetChildren() { $file = new FileMock(); $dir = new SimpleCollection('simpledir'); $dir->addChild($file); - $this->assertEquals(array($file),$dir->getChildren()); + $this->assertEquals([$file], $dir->getChildren()); } /* * @depends testSimpleDirectoryConstruct */ - public function testSimpleDirectoryGetName() { + function testSimpleDirectoryGetName() { $dir = new SimpleCollection('simpledir'); - $this->assertEquals('simpledir',$dir->getName()); + $this->assertEquals('simpledir', $dir->getName()); } @@ -200,7 +200,7 @@ class BasicNodeTest extends \PHPUnit_Framework_TestCase { * @depends testSimpleDirectoryConstruct * @expectedException Sabre\DAV\Exception\NotFound */ - public function testSimpleDirectoryGetChild404() { + function testSimpleDirectoryGetChild404() { $dir = new SimpleCollection('simpledir'); $dir->getChild('blabla'); @@ -218,7 +218,7 @@ class DirectoryMock extends Collection { function getChildren() { - return array(new FileMock()); + return [new FileMock()]; } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Browser/GuessContentTypeTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Browser/GuessContentTypeTest.php index 157c2170a..54a3053ec 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Browser/GuessContentTypeTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Browser/GuessContentTypeTest.php @@ -11,8 +11,8 @@ class GuessContentTypeTest extends DAV\AbstractServer { parent::setUp(); \Sabre\TestUtil::clearTempDir(); - file_put_contents(SABRE_TEMPDIR . '/somefile.jpg','blabla'); - file_put_contents(SABRE_TEMPDIR . '/somefile.hoi','blabla'); + file_put_contents(SABRE_TEMPDIR . '/somefile.jpg', 'blabla'); + file_put_contents(SABRE_TEMPDIR . '/somefile.hoi', 'blabla'); } @@ -24,13 +24,13 @@ class GuessContentTypeTest extends DAV\AbstractServer { function testGetProperties() { - $properties = array( + $properties = [ '{DAV:}getcontenttype', - ); - $result = $this->server->getPropertiesForPath('/somefile.jpg',$properties); - $this->assertArrayHasKey(0,$result); - $this->assertArrayHasKey(404,$result[0]); - $this->assertArrayHasKey('{DAV:}getcontenttype',$result[0][404]); + ]; + $result = $this->server->getPropertiesForPath('/somefile.jpg', $properties); + $this->assertArrayHasKey(0, $result); + $this->assertArrayHasKey(404, $result[0]); + $this->assertArrayHasKey('{DAV:}getcontenttype', $result[0][404]); } @@ -40,14 +40,14 @@ class GuessContentTypeTest extends DAV\AbstractServer { function testGetPropertiesPluginEnabled() { $this->server->addPlugin(new GuessContentType()); - $properties = array( + $properties = [ '{DAV:}getcontenttype', - ); - $result = $this->server->getPropertiesForPath('/somefile.jpg',$properties); - $this->assertArrayHasKey(0,$result); - $this->assertArrayHasKey(200,$result[0], 'We received: ' . print_r($result,true)); - $this->assertArrayHasKey('{DAV:}getcontenttype',$result[0][200]); - $this->assertEquals('image/jpeg',$result[0][200]['{DAV:}getcontenttype']); + ]; + $result = $this->server->getPropertiesForPath('/somefile.jpg', $properties); + $this->assertArrayHasKey(0, $result); + $this->assertArrayHasKey(200, $result[0], 'We received: ' . print_r($result, true)); + $this->assertArrayHasKey('{DAV:}getcontenttype', $result[0][200]); + $this->assertEquals('image/jpeg', $result[0][200]['{DAV:}getcontenttype']); } @@ -57,14 +57,14 @@ class GuessContentTypeTest extends DAV\AbstractServer { function testGetPropertiesUnknown() { $this->server->addPlugin(new GuessContentType()); - $properties = array( + $properties = [ '{DAV:}getcontenttype', - ); - $result = $this->server->getPropertiesForPath('/somefile.hoi',$properties); - $this->assertArrayHasKey(0,$result); - $this->assertArrayHasKey(200,$result[0]); - $this->assertArrayHasKey('{DAV:}getcontenttype',$result[0][200]); - $this->assertEquals('application/octet-stream',$result[0][200]['{DAV:}getcontenttype']); + ]; + $result = $this->server->getPropertiesForPath('/somefile.hoi', $properties); + $this->assertArrayHasKey(0, $result); + $this->assertArrayHasKey(200, $result[0]); + $this->assertArrayHasKey('{DAV:}getcontenttype', $result[0][200]); + $this->assertEquals('application/octet-stream', $result[0][200]['{DAV:}getcontenttype']); } } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Browser/MapGetToPropFindTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Browser/MapGetToPropFindTest.php index 9d9fbb319..33c4ede96 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Browser/MapGetToPropFindTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Browser/MapGetToPropFindTest.php @@ -18,23 +18,23 @@ class MapGetToPropFindTest extends DAV\AbstractServer { function testCollectionGet() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/', 'REQUEST_METHOD' => 'GET', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody(''); $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(207, $this->response->status,'Incorrect status response received. Full response body: ' . $this->response->body); - $this->assertEquals(array( + $this->assertEquals(207, $this->response->status, 'Incorrect status response received. Full response body: ' . $this->response->body); + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - 'DAV' => ['1, 3, extended-mkcol'], - 'Vary' => ['Brief,Prefer'], - ), + 'Content-Type' => ['application/xml; charset=utf-8'], + 'DAV' => ['1, 3, extended-mkcol'], + 'Vary' => ['Brief,Prefer'], + ], $this->response->getHeaders() ); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Browser/PluginTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Browser/PluginTest.php index 00beea9f2..f20c50f86 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Browser/PluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Browser/PluginTest.php @@ -28,16 +28,16 @@ class PluginTest extends DAV\AbstractServer{ $this->assertEquals(200, $this->response->getStatus(), "Incorrect status received. Full response body: " . $this->response->getBodyAsString()); $this->assertEquals( [ - 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['text/html; charset=utf-8'], - 'Content-Security-Policy' => ["img-src 'self'; style-src 'self';"] + 'X-Sabre-Version' => [DAV\Version::VERSION], + 'Content-Type' => ['text/html; charset=utf-8'], + 'Content-Security-Policy' => ["default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self';"] ], $this->response->getHeaders() ); $body = $this->response->getBodyAsString(); $this->assertTrue(strpos($body, 'dir') !== false, $body); - $this->assertTrue(strpos($body, '<a href="/dir/child.txt">')!==false); + $this->assertTrue(strpos($body, '<a href="/dir/child.txt">') !== false); } @@ -54,16 +54,16 @@ class PluginTest extends DAV\AbstractServer{ $this->assertEquals(200, $this->response->getStatus(), "Incorrect status received. Full response body: " . $this->response->getBodyAsString()); $this->assertEquals( [ - 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['text/html; charset=utf-8'], - 'Content-Security-Policy' => ["img-src 'self'; style-src 'self';"] + 'X-Sabre-Version' => [DAV\Version::VERSION], + 'Content-Type' => ['text/html; charset=utf-8'], + 'Content-Security-Policy' => ["default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self';"] ], $this->response->getHeaders() ); $body = $this->response->getBodyAsString(); $this->assertTrue(strpos($body, '<title>dir') !== false, $body); - $this->assertTrue(strpos($body, '<a href="/dir/child.txt">')!==false); + $this->assertTrue(strpos($body, '<a href="/dir/child.txt">') !== false); } function testCollectionGetRoot() { @@ -75,17 +75,17 @@ class PluginTest extends DAV\AbstractServer{ $this->assertEquals(200, $this->response->status, "Incorrect status received. Full response body: " . $this->response->getBodyAsString()); $this->assertEquals( [ - 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['text/html; charset=utf-8'], - 'Content-Security-Policy' => ["img-src 'self'; style-src 'self';"] + 'X-Sabre-Version' => [DAV\Version::VERSION], + 'Content-Type' => ['text/html; charset=utf-8'], + 'Content-Security-Policy' => ["default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self';"] ], $this->response->getHeaders() ); $body = $this->response->getBodyAsString(); $this->assertTrue(strpos($body, '<title>/') !== false, $body); - $this->assertTrue(strpos($body, '<a href="/dir/">')!==false); - $this->assertTrue(strpos($body, '<span class="btn disabled">')!==false); + $this->assertTrue(strpos($body, '<a href="/dir/">') !== false); + $this->assertTrue(strpos($body, '<span class="btn disabled">') !== false); } @@ -122,15 +122,15 @@ class PluginTest extends DAV\AbstractServer{ function testPostMkCol() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/', 'REQUEST_METHOD' => 'POST', - 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', - ); - $postVars = array( + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', + ]; + $postVars = [ 'sabreAction' => 'mkcol', - 'name' => 'new_collection', - ); + 'name' => 'new_collection', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setPostData($postVars); @@ -138,10 +138,10 @@ class PluginTest extends DAV\AbstractServer{ $this->server->exec(); $this->assertEquals(302, $this->response->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Location' => ['/'], - ), $this->response->getHeaders()); + 'Location' => ['/'], + ], $this->response->getHeaders()); $this->assertTrue(is_dir(SABRE_TEMPDIR . '/new_collection')); @@ -155,11 +155,11 @@ class PluginTest extends DAV\AbstractServer{ $this->assertEquals(200, $this->response->getStatus(), 'Error: ' . $this->response->body); $this->assertEquals([ - 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['image/vnd.microsoft.icon'], - 'Content-Length' => ['4286'], - 'Cache-Control' => ['public, max-age=1209600'], - 'Content-Security-Policy' => ["img-src 'self'; style-src 'self';"] + 'X-Sabre-Version' => [DAV\Version::VERSION], + 'Content-Type' => ['image/vnd.microsoft.icon'], + 'Content-Length' => ['4286'], + 'Cache-Control' => ['public, max-age=1209600'], + 'Content-Security-Policy' => ["default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self';"] ], $this->response->getHeaders()); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ClientMock.php b/vendor/sabre/dav/tests/Sabre/DAV/ClientMock.php index d8b53a5a1..5a48b063c 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ClientMock.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ClientMock.php @@ -18,13 +18,13 @@ class ClientMock extends Client { * @param string $url * @return string */ - public function getAbsoluteUrl($url) { + function getAbsoluteUrl($url) { return parent::getAbsoluteUrl($url); } - public function doRequest(RequestInterface $request) { + function doRequest(RequestInterface $request) { $this->request = $request; return $this->response; diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Exception/LockedTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Exception/LockedTest.php index c06d6aa1f..8788475cb 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Exception/LockedTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Exception/LockedTest.php @@ -2,9 +2,8 @@ namespace Sabre\DAV\Exception; -use - Sabre\DAV, - DOMDocument; +use Sabre\DAV; +use DOMDocument; class LockedTest extends \PHPUnit_Framework_TestCase { @@ -15,7 +14,7 @@ class LockedTest extends \PHPUnit_Framework_TestCase { $root = $dom->createElement('d:root'); $dom->appendChild($root); - $root->setAttribute('xmlns:d','DAV:'); + $root->setAttribute('xmlns:d', 'DAV:'); $lockInfo = new DAV\Locks\LockInfo(); $lockInfo->uri = '/foo'; @@ -44,7 +43,7 @@ class LockedTest extends \PHPUnit_Framework_TestCase { $root = $dom->createElement('d:root'); $dom->appendChild($root); - $root->setAttribute('xmlns:d','DAV:'); + $root->setAttribute('xmlns:d', 'DAV:'); $lockInfo = new DAV\Locks\LockInfo(); $lockInfo->uri = '/foo&bar'; diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ExceptionTest.php b/vendor/sabre/dav/tests/Sabre/DAV/ExceptionTest.php index 6d6bf5668..0eb4f3dd8 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ExceptionTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ExceptionTest.php @@ -7,18 +7,18 @@ class ExceptionTest extends \PHPUnit_Framework_TestCase { function testStatus() { $e = new Exception(); - $this->assertEquals(500,$e->getHTTPCode()); + $this->assertEquals(500, $e->getHTTPCode()); } function testExceptionStatuses() { - $c = array( + $c = [ 'Sabre\\DAV\\Exception\\NotAuthenticated' => 401, 'Sabre\\DAV\\Exception\\InsufficientStorage' => 507, - ); + ]; - foreach($c as $class=>$status) { + foreach ($c as $class => $status) { $obj = new $class(); $this->assertEquals($status, $obj->getHTTPCode()); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/FSExt/FileTest.php b/vendor/sabre/dav/tests/Sabre/DAV/FSExt/FileTest.php index 3708594e0..f5d65a44f 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/FSExt/FileTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/FSExt/FileTest.php @@ -2,8 +2,6 @@ namespace Sabre\DAV\FSExt; -use Sabre\DAV; - require_once 'Sabre/TestUtil.php'; class FileTest extends \PHPUnit_Framework_TestCase { @@ -26,12 +24,12 @@ class FileTest extends \PHPUnit_Framework_TestCase { $file = new File($filename); $result = $file->put('New contents'); - $this->assertEquals('New contents',file_get_contents(SABRE_TEMPDIR . '/file.txt')); + $this->assertEquals('New contents', file_get_contents(SABRE_TEMPDIR . '/file.txt')); $this->assertEquals( '"' . sha1( fileinode($filename) . - filesize($filename ) . + filesize($filename) . filemtime($filename) ) . '"', $result @@ -45,13 +43,13 @@ class FileTest extends \PHPUnit_Framework_TestCase { $file->put('0000000'); $file->patch('111', 2, 3); - $this->assertEquals('0001110',file_get_contents(SABRE_TEMPDIR . '/file.txt')); + $this->assertEquals('0001110', file_get_contents(SABRE_TEMPDIR . '/file.txt')); } function testRangeStream() { - $stream = fopen('php://memory','r+'); + $stream = fopen('php://memory', 'r+'); fwrite($stream, "222"); rewind($stream); @@ -59,7 +57,7 @@ class FileTest extends \PHPUnit_Framework_TestCase { $file->put('0000000'); $file->patch($stream, 2, 3); - $this->assertEquals('0002220',file_get_contents(SABRE_TEMPDIR . '/file.txt')); + $this->assertEquals('0002220', file_get_contents(SABRE_TEMPDIR . '/file.txt')); } @@ -67,7 +65,7 @@ class FileTest extends \PHPUnit_Framework_TestCase { function testGet() { $file = new File(SABRE_TEMPDIR . '/file.txt'); - $this->assertEquals('Contents',stream_get_contents($file->get())); + $this->assertEquals('Contents', stream_get_contents($file->get())); } @@ -88,7 +86,7 @@ class FileTest extends \PHPUnit_Framework_TestCase { '"' . sha1( fileinode($filename) . - filesize($filename ) . + filesize($filename) . filemtime($filename) ) . '"', $file->getETag() @@ -105,7 +103,7 @@ class FileTest extends \PHPUnit_Framework_TestCase { function testGetSize() { $file = new File(SABRE_TEMPDIR . '/file.txt'); - $this->assertEquals(8,$file->getSize()); + $this->assertEquals(8, $file->getSize()); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/FSExt/ServerTest.php b/vendor/sabre/dav/tests/Sabre/DAV/FSExt/ServerTest.php index 63d858de1..20fca490a 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/FSExt/ServerTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/FSExt/ServerTest.php @@ -28,7 +28,7 @@ class ServerTest extends DAV\AbstractServer{ 'Content-Type' => ['application/octet-stream'], 'Content-Length' => [13], 'Last-Modified' => [HTTP\Util::toHTTPDate(new \DateTime('@' . filemtime($filename)))], - 'ETag' => ['"' . sha1(fileinode($filename ) . filesize($filename) . filemtime($filename)) . '"'], + 'ETag' => ['"' . sha1(fileinode($filename) . filesize($filename) . filemtime($filename)) . '"'], ], $this->response->getHeaders() ); @@ -50,12 +50,12 @@ class ServerTest extends DAV\AbstractServer{ 'Content-Type' => ['application/octet-stream'], 'Content-Length' => [13], 'Last-Modified' => [HTTP\Util::toHTTPDate(new \DateTime('@' . filemtime($this->tempDir . '/test.txt')))], - 'ETag' => ['"' . sha1(fileinode($filename ) . filesize($filename) . filemtime($filename)) . '"'], + 'ETag' => ['"' . sha1(fileinode($filename) . filesize($filename) . filemtime($filename)) . '"'], ], $this->response->getHeaders() ); - $this->assertEquals(200,$this->response->status); + $this->assertEquals(200, $this->response->status); $this->assertEquals('', $this->response->body); } @@ -71,12 +71,12 @@ class ServerTest extends DAV\AbstractServer{ $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], 'Content-Length' => ['0'], - 'ETag' => ['"' . sha1(fileinode($filename ) . filesize($filename) . filemtime($filename)) . '"'], + 'ETag' => ['"' . sha1(fileinode($filename) . filesize($filename) . filemtime($filename)) . '"'], ], $this->response->getHeaders()); $this->assertEquals(201, $this->response->status); $this->assertEquals('', $this->response->body); - $this->assertEquals('Testing new file',file_get_contents($filename)); + $this->assertEquals('Testing new file', file_get_contents($filename)); } @@ -89,11 +89,11 @@ class ServerTest extends DAV\AbstractServer{ $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ],$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); $this->assertEquals(412, $this->response->status); - $this->assertNotEquals('Testing new file',file_get_contents($this->tempDir . '/test.txt')); + $this->assertNotEquals('Testing new file', file_get_contents($this->tempDir . '/test.txt')); } @@ -105,8 +105,8 @@ class ServerTest extends DAV\AbstractServer{ $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Length' => ['0'], - ],$this->response->getHeaders()); + 'Content-Length' => ['0'], + ], $this->response->getHeaders()); $this->assertEquals(201, $this->response->status); $this->assertEquals('', $this->response->body); @@ -125,7 +125,7 @@ class ServerTest extends DAV\AbstractServer{ $this->assertEquals(204, $this->response->status); $this->assertEquals('', $this->response->body); - $this->assertEquals('Testing updated file',file_get_contents($this->tempDir . '/test.txt')); + $this->assertEquals('Testing updated file', file_get_contents($this->tempDir . '/test.txt')); } @@ -137,8 +137,8 @@ class ServerTest extends DAV\AbstractServer{ $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Length' => ['0'], - ],$this->response->getHeaders()); + 'Content-Length' => ['0'], + ], $this->response->getHeaders()); $this->assertEquals(204, $this->response->status); $this->assertEquals('', $this->response->body); @@ -148,8 +148,8 @@ class ServerTest extends DAV\AbstractServer{ function testDeleteDirectory() { - mkdir($this->tempDir.'/testcol'); - file_put_contents($this->tempDir.'/testcol/test.txt','Hi! I\'m a file with a short lifespan'); + mkdir($this->tempDir . '/testcol'); + file_put_contents($this->tempDir . '/testcol/test.txt', 'Hi! I\'m a file with a short lifespan'); $request = new HTTP\Request('DELETE', '/testcol'); $this->server->httpRequest = ($request); @@ -157,8 +157,8 @@ class ServerTest extends DAV\AbstractServer{ $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Length' => ['0'], - ],$this->response->getHeaders()); + 'Content-Length' => ['0'], + ], $this->response->getHeaders()); $this->assertEquals(204, $this->response->status); $this->assertEquals('', $this->response->body); $this->assertFalse(file_exists($this->tempDir . '/testcol')); @@ -172,12 +172,12 @@ class ServerTest extends DAV\AbstractServer{ $this->server->exec(); $this->assertEquals([ - 'DAV' => ['1, 3, extended-mkcol'], - 'MS-Author-Via' => ['DAV'], - 'Allow' => ['OPTIONS, GET, HEAD, DELETE, PROPFIND, PUT, PROPPATCH, COPY, MOVE, REPORT'], - 'Accept-Ranges' => ['bytes'], - 'Content-Length' => ['0'], - 'X-Sabre-Version'=> [DAV\Version::VERSION], + 'DAV' => ['1, 3, extended-mkcol'], + 'MS-Author-Via' => ['DAV'], + 'Allow' => ['OPTIONS, GET, HEAD, DELETE, PROPFIND, PUT, PROPPATCH, COPY, MOVE, REPORT'], + 'Accept-Ranges' => ['bytes'], + 'Content-Length' => ['0'], + 'X-Sabre-Version' => [DAV\Version::VERSION], ], $this->response->getHeaders()); $this->assertEquals(200, $this->response->status); @@ -187,7 +187,7 @@ class ServerTest extends DAV\AbstractServer{ function testMove() { - mkdir($this->tempDir.'/testcol'); + mkdir($this->tempDir . '/testcol'); $request = new HTTP\Request('MOVE', '/test.txt', ['Destination' => '/testcol/test2.txt']); $this->server->httpRequest = ($request); @@ -197,9 +197,9 @@ class ServerTest extends DAV\AbstractServer{ $this->assertEquals('', $this->response->body); $this->assertEquals([ - 'Content-Length' => ['0'], - 'X-Sabre-Version'=> [DAV\Version::VERSION], - ],$this->response->getHeaders()); + 'Content-Length' => ['0'], + 'X-Sabre-Version' => [DAV\Version::VERSION], + ], $this->response->getHeaders()); $this->assertTrue( is_file($this->tempDir . '/testcol/test2.txt') @@ -217,8 +217,8 @@ class ServerTest extends DAV\AbstractServer{ */ function testMoveOtherObject() { - mkdir($this->tempDir.'/tree1'); - mkdir($this->tempDir.'/tree2'); + mkdir($this->tempDir . '/tree1'); + mkdir($this->tempDir . '/tree2'); $tree = new DAV\Tree(new DAV\SimpleCollection('root', [ new DAV\FS\Directory($this->tempDir . '/tree1'), @@ -234,9 +234,9 @@ class ServerTest extends DAV\AbstractServer{ $this->assertEquals('', $this->response->body); $this->assertEquals([ - 'Content-Length' => ['0'], - 'X-Sabre-Version'=> [DAV\Version::VERSION], - ],$this->response->getHeaders()); + 'Content-Length' => ['0'], + 'X-Sabre-Version' => [DAV\Version::VERSION], + ], $this->response->getHeaders()); $this->assertTrue( is_dir($this->tempDir . '/tree2/tree1') diff --git a/vendor/sabre/dav/tests/Sabre/DAV/HttpDeleteTest.php b/vendor/sabre/dav/tests/Sabre/DAV/HttpDeleteTest.php index 6c10afa9f..bd1b33150 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/HttpDeleteTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/HttpDeleteTest.php @@ -19,12 +19,12 @@ class HttpDeleteTest extends DAVServerTest { * * @return void */ - public function setUpTree() { + function setUpTree() { $this->tree = new Mock\Collection('root', [ 'file1' => 'foo', - 'dir' => [ - 'subfile' => 'bar', + 'dir' => [ + 'subfile' => 'bar', 'subfile2' => 'baz', ], ]); @@ -34,7 +34,7 @@ class HttpDeleteTest extends DAVServerTest { /** * A successful DELETE */ - public function testDelete() { + function testDelete() { $request = new HTTP\Request('DELETE', '/file1'); @@ -49,7 +49,7 @@ class HttpDeleteTest extends DAVServerTest { $this->assertEquals( [ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], + 'Content-Length' => ['0'], ], $response->getHeaders() ); @@ -59,7 +59,7 @@ class HttpDeleteTest extends DAVServerTest { /** * Deleting a Directory */ - public function testDeleteDirectory() { + function testDeleteDirectory() { $request = new HTTP\Request('DELETE', '/dir'); @@ -74,7 +74,7 @@ class HttpDeleteTest extends DAVServerTest { $this->assertEquals( [ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], + 'Content-Length' => ['0'], ], $response->getHeaders() ); @@ -84,7 +84,7 @@ class HttpDeleteTest extends DAVServerTest { /** * DELETE on a node that does not exist */ - public function testDeleteNotFound() { + function testDeleteNotFound() { $request = new HTTP\Request('DELETE', '/file2'); $response = $this->request($request); @@ -100,7 +100,7 @@ class HttpDeleteTest extends DAVServerTest { /** * DELETE with preconditions */ - public function testDeletePreconditions() { + function testDeletePreconditions() { $request = new HTTP\Request('DELETE', '/file1', [ 'If-Match' => '"' . md5('foo') . '"', @@ -119,7 +119,7 @@ class HttpDeleteTest extends DAVServerTest { /** * DELETE with incorrect preconditions */ - public function testDeletePreconditionsFailed() { + function testDeletePreconditionsFailed() { $request = new HTTP\Request('DELETE', '/file1', [ 'If-Match' => '"' . md5('bar') . '"', diff --git a/vendor/sabre/dav/tests/Sabre/DAV/HttpPutTest.php b/vendor/sabre/dav/tests/Sabre/DAV/HttpPutTest.php index eddaf3f22..86480b1c2 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/HttpPutTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/HttpPutTest.php @@ -46,8 +46,8 @@ class HttpPutTest extends DAVServerTest { $this->assertEquals( [ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - 'ETag' => ['"' . md5('hello') . '"'] + 'Content-Length' => ['0'], + 'ETag' => ['"' . md5('hello') . '"'] ], $response->getHeaders() ); @@ -75,8 +75,8 @@ class HttpPutTest extends DAVServerTest { $this->assertEquals( [ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - 'ETag' => ['"' . md5('bar') . '"'] + 'Content-Length' => ['0'], + 'ETag' => ['"' . md5('bar') . '"'] ], $response->getHeaders() ); @@ -109,8 +109,8 @@ class HttpPutTest extends DAVServerTest { $this->assertEquals( [ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - 'ETag' => ['"' . md5('hello') . '"'] + 'Content-Length' => ['0'], + 'ETag' => ['"' . md5('hello') . '"'] ], $response->getHeaders() ); @@ -143,8 +143,8 @@ class HttpPutTest extends DAVServerTest { $this->assertEquals( [ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - 'ETag' => ['"' . md5('hello') . '"'], + 'Content-Length' => ['0'], + 'ETag' => ['"' . md5('hello') . '"'], ], $response->getHeaders() ); @@ -196,8 +196,8 @@ class HttpPutTest extends DAVServerTest { $this->assertEquals( [ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - 'ETag' => ['"' . md5('hello') . '"'] + 'Content-Length' => ['0'], + 'ETag' => ['"' . md5('hello') . '"'] ], $response->getHeaders() ); @@ -291,8 +291,8 @@ class HttpPutTest extends DAVServerTest { $this->assertEquals( [ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - 'ETag' => ['"' . md5('hello') . '"'], + 'Content-Length' => ['0'], + 'ETag' => ['"' . md5('hello') . '"'], ], $response->getHeaders() ); @@ -334,7 +334,7 @@ class HttpPutTest extends DAVServerTest { $request = new HTTP\Request('PUT', '/file2', [], 'hello'); $response = $this->request($request); - $this->assertEquals(418, $response->getStatus(), 'Incorrect status code received. Full response body: ' .$response->getBodyAsString()); + $this->assertEquals(418, $response->getStatus(), 'Incorrect status code received. Full response body: ' . $response->getBodyAsString()); $this->assertFalse( $this->server->tree->nodeExists('file2') diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Issue33Test.php b/vendor/sabre/dav/tests/Sabre/DAV/Issue33Test.php index 4ccb42fbb..edd09e634 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Issue33Test.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Issue33Test.php @@ -17,16 +17,16 @@ class Issue33Test extends \PHPUnit_Framework_TestCase { function testCopyMoveInfo() { $bar = new SimpleCollection('bar'); - $root = new SimpleCollection('webdav',array($bar)); + $root = new SimpleCollection('webdav', [$bar]); $server = new Server($root); $server->setBaseUri('/webdav/'); - $serverVars = array( - 'REQUEST_URI' => '/webdav/bar', + $serverVars = [ + 'REQUEST_URI' => '/webdav/bar', 'HTTP_DESTINATION' => 'http://dev2.tribalos.com/webdav/%C3%A0fo%C3%B3', - 'HTTP_OVERWRITE' => 'F', - ); + 'HTTP_OVERWRITE' => 'F', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); @@ -48,19 +48,19 @@ class Issue33Test extends \PHPUnit_Framework_TestCase { $dir->createDirectory('bar'); $tree = new Tree($dir); - $tree->move('bar',urldecode('%C3%A0fo%C3%B3')); + $tree->move('bar', urldecode('%C3%A0fo%C3%B3')); $node = $tree->getNodeForPath(urldecode('%C3%A0fo%C3%B3')); - $this->assertEquals(urldecode('%C3%A0fo%C3%B3'),$node->getName()); + $this->assertEquals(urldecode('%C3%A0fo%C3%B3'), $node->getName()); } function testDirName() { $dirname1 = 'bar'; - $dirname2 = urlencode('%C3%A0fo%C3%B3');; + $dirname2 = urlencode('%C3%A0fo%C3%B3'); - $this->assertTrue(dirname($dirname1)==dirname($dirname2)); + $this->assertTrue(dirname($dirname1) == dirname($dirname2)); } @@ -71,12 +71,12 @@ class Issue33Test extends \PHPUnit_Framework_TestCase { function testEverything() { // Request object - $serverVars = array( - 'REQUEST_METHOD' => 'MOVE', - 'REQUEST_URI' => '/webdav/bar', + $serverVars = [ + 'REQUEST_METHOD' => 'MOVE', + 'REQUEST_URI' => '/webdav/bar', 'HTTP_DESTINATION' => 'http://dev2.tribalos.com/webdav/%C3%A0fo%C3%B3', - 'HTTP_OVERWRITE' => 'F', - ); + 'HTTP_OVERWRITE' => 'F', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody(''); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/AbstractTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/AbstractTest.php index f39e9a036..bbde69097 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/AbstractTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/AbstractTest.php @@ -31,15 +31,15 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase { $lock->timeout = 60; $lock->created = time(); $lock->token = 'MY-UNIQUE-TOKEN'; - $lock->uri ='someuri'; + $lock->uri = 'someuri'; $this->assertTrue($backend->lock('someuri', $lock)); $locks = $backend->getLocks('someuri', false); - $this->assertEquals(1,count($locks)); - $this->assertEquals('Sinterklaas',$locks[0]->owner); - $this->assertEquals('someuri',$locks[0]->uri); + $this->assertEquals(1, count($locks)); + $this->assertEquals('Sinterklaas', $locks[0]->owner); + $this->assertEquals('someuri', $locks[0]->uri); } @@ -61,9 +61,9 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase { $locks = $backend->getLocks('someuri/child', false); - $this->assertEquals(1,count($locks)); - $this->assertEquals('Sinterklaas',$locks[0]->owner); - $this->assertEquals('someuri',$locks[0]->uri); + $this->assertEquals(1, count($locks)); + $this->assertEquals('Sinterklaas', $locks[0]->owner); + $this->assertEquals('someuri', $locks[0]->uri); } @@ -86,7 +86,7 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase { $locks = $backend->getLocks('someuri/child', false); - $this->assertEquals(0,count($locks)); + $this->assertEquals(0, count($locks)); } @@ -104,13 +104,13 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase { $this->assertTrue($backend->lock('someuri/child', $lock)); $locks = $backend->getLocks('someuri/child', false); - $this->assertEquals(1,count($locks)); + $this->assertEquals(1, count($locks)); $locks = $backend->getLocks('someuri', false); - $this->assertEquals(0,count($locks)); + $this->assertEquals(0, count($locks)); $locks = $backend->getLocks('someuri', true); - $this->assertEquals(1,count($locks)); + $this->assertEquals(1, count($locks)); } @@ -135,10 +135,10 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase { $locks = $backend->getLocks('someuri', false); - $this->assertEquals(1,count($locks)); + $this->assertEquals(1, count($locks)); - $this->assertEquals('Santa Clause',$locks[0]->owner); - $this->assertEquals('someuri',$locks[0]->uri); + $this->assertEquals('Santa Clause', $locks[0]->owner); + $this->assertEquals('someuri', $locks[0]->uri); } @@ -158,12 +158,12 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase { $this->assertTrue($backend->lock('someuri', $lock)); $locks = $backend->getLocks('someuri', false); - $this->assertEquals(1,count($locks)); + $this->assertEquals(1, count($locks)); - $this->assertTrue($backend->unlock('someuri',$lock)); + $this->assertTrue($backend->unlock('someuri', $lock)); $locks = $backend->getLocks('someuri', false); - $this->assertEquals(0,count($locks)); + $this->assertEquals(0, count($locks)); } @@ -183,13 +183,13 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase { $this->assertTrue($backend->lock('someuri', $lock)); $locks = $backend->getLocks('someuri', false); - $this->assertEquals(1,count($locks)); + $this->assertEquals(1, count($locks)); $lock->token = 'SOME-OTHER-TOKEN'; - $this->assertFalse($backend->unlock('someuri',$lock)); + $this->assertFalse($backend->unlock('someuri', $lock)); $locks = $backend->getLocks('someuri', false); - $this->assertEquals(1,count($locks)); + $this->assertEquals(1, count($locks)); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/PDOMySQLTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/PDOMySQLTest.php index b6f06224c..0ba02fc8b 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/PDOMySQLTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/PDOMySQLTest.php @@ -2,31 +2,8 @@ namespace Sabre\DAV\Locks\Backend; -require_once 'Sabre/TestUtil.php'; +class PDOMySQLTest extends PDOTest { -class PDOMySQLTest extends AbstractTest { - - function getBackend() { - - if (!SABRE_HASMYSQL) $this->markTestSkipped('MySQL driver is not available, or it was not properly configured'); - $pdo = \Sabre\TestUtil::getMySQLDB(); - if (!$pdo) $this->markTestSkipped('Could not connect to MySQL database'); - $pdo->query('DROP TABLE IF EXISTS locks;'); - $pdo->query(" -CREATE TABLE locks ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - owner VARCHAR(100), - timeout INTEGER UNSIGNED, - created INTEGER, - token VARCHAR(100), - scope TINYINT, - depth TINYINT, - uri text -);"); - - $backend = new PDO($pdo); - return $backend; - - } + public $driver = 'mysql'; } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/PDOTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/PDOTest.php index d6336c7b2..a27eae93c 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/PDOTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Locks/Backend/PDOTest.php @@ -2,27 +2,18 @@ namespace Sabre\DAV\Locks\Backend; -require_once 'Sabre/TestUtil.php'; -require_once 'Sabre/DAV/Locks/Backend/AbstractTest.php'; +abstract class PDOTest extends AbstractTest { -class PDOTest extends AbstractTest { + use \Sabre\DAV\DbTestHelperTrait; function getBackend() { - if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available'); - \Sabre\TestUtil::clearTempDir(); - mkdir(SABRE_TEMPDIR . '/pdolocks'); - $pdo = new \PDO('sqlite:' . SABRE_TEMPDIR . '/pdolocks/db.sqlite'); - $pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); - $pdo->query('CREATE TABLE locks ( id integer primary key asc, owner text, timeout text, created integer, token text, scope integer, depth integer, uri text)'); - $backend = new PDO($pdo); - return $backend; + $this->dropTables('locks'); + $this->createSchema('locks'); - } - - function tearDown() { + $pdo = $this->getPDO(); - \Sabre\TestUtil::clearTempDir(); + return new PDO($pdo); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Locks/MSWordTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Locks/MSWordTest.php index 23f283796..f08f19da5 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Locks/MSWordTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Locks/MSWordTest.php @@ -62,12 +62,12 @@ class MSWordTest extends \PHPUnit_Framework_TestCase { function getLockRequest() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'LOCK', 'HTTP_CONTENT_TYPE' => 'application/xml', 'HTTP_TIMEOUT' => 'Second-3600', 'REQUEST_URI' => '/Nouveau%20Microsoft%20Office%20Excel%20Worksheet.xlsx', - )); + ]); $request->setBody('<D:lockinfo xmlns:D="DAV:"> <D:lockscope> @@ -86,12 +86,12 @@ class MSWordTest extends \PHPUnit_Framework_TestCase { } function getLockRequest2() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'LOCK', 'HTTP_CONTENT_TYPE' => 'application/xml', 'HTTP_TIMEOUT' => 'Second-3600', 'REQUEST_URI' => '/~$Nouveau%20Microsoft%20Office%20Excel%20Worksheet.xlsx', - )); + ]); $request->setBody('<D:lockinfo xmlns:D="DAV:"> <D:lockscope> @@ -111,11 +111,11 @@ class MSWordTest extends \PHPUnit_Framework_TestCase { function getPutRequest($lockToken) { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'PUT', 'REQUEST_URI' => '/Nouveau%20Microsoft%20Office%20Excel%20Worksheet.xlsx', - 'HTTP_IF' => 'If: ('.$lockToken.')', - )); + 'HTTP_IF' => 'If: (' . $lockToken . ')', + ]); $request->setBody('FAKE BODY'); return $request; diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Locks/PluginTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Locks/PluginTest.php index ef0e473ae..6511d4e7d 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Locks/PluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Locks/PluginTest.php @@ -35,13 +35,13 @@ class PluginTest extends DAV\AbstractServer { function testGetFeatures() { - $this->assertEquals(array(2),$this->locksPlugin->getFeatures()); + $this->assertEquals([2], $this->locksPlugin->getFeatures()); } function testGetHTTPMethods() { - $this->assertEquals(array('LOCK','UNLOCK'),$this->locksPlugin->getHTTPMethods('')); + $this->assertEquals(['LOCK', 'UNLOCK'], $this->locksPlugin->getHTTPMethods('')); } @@ -51,10 +51,10 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders() ); @@ -77,16 +77,16 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); - $this->assertEquals(200, $this->response->status,'Got an incorrect status back. Response body: ' . $this->response->body); + $this->assertEquals(200, $this->response->status, 'Got an incorrect status back. Response body: ' . $this->response->body); - $body = preg_replace("/xmlns(:[A-Za-z0-9_])?=(\"|\')DAV:(\"|\')/","xmlns\\1=\"urn:DAV\"",$this->response->body); + $body = preg_replace("/xmlns(:[A-Za-z0-9_])?=(\"|\')DAV:(\"|\')/", "xmlns\\1=\"urn:DAV\"", $this->response->body); $xml = simplexml_load_string($body); - $xml->registerXPathNamespace('d','urn:DAV'); + $xml->registerXPathNamespace('d', 'urn:DAV'); - $elements = array( + $elements = [ '/d:prop', '/d:prop/d:lockdiscovery', '/d:prop/d:lockdiscovery/d:activelock', @@ -101,18 +101,18 @@ class PluginTest extends DAV\AbstractServer { '/d:prop/d:lockdiscovery/d:activelock/d:timeout', '/d:prop/d:lockdiscovery/d:activelock/d:locktoken', '/d:prop/d:lockdiscovery/d:activelock/d:locktoken/d:href', - ); + ]; - foreach($elements as $elem) { + foreach ($elements as $elem) { $data = $xml->xpath($elem); - $this->assertEquals(1,count($data),'We expected 1 match for the xpath expression "' . $elem . '". ' . count($data) . ' were found. Full response body: ' . $this->response->body); + $this->assertEquals(1, count($data), 'We expected 1 match for the xpath expression "' . $elem . '". ' . count($data) . ' were found. Full response body: ' . $this->response->body); } $depth = $xml->xpath('/d:prop/d:lockdiscovery/d:activelock/d:depth'); - $this->assertEquals('infinity',(string)$depth[0]); + $this->assertEquals('infinity', (string)$depth[0]); $token = $xml->xpath('/d:prop/d:lockdiscovery/d:activelock/d:locktoken/d:href'); - $this->assertEquals($this->response->getHeader('Lock-Token'),'<' . (string)$token[0] . '>','Token in response body didn\'t match token in response header.'); + $this->assertEquals($this->response->getHeader('Lock-Token'), '<' . (string)$token[0] . '>', 'Token in response body didn\'t match token in response header.'); } @@ -139,7 +139,7 @@ class PluginTest extends DAV\AbstractServer { $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); $this->assertEquals(423, $this->response->status, 'Full response: ' . $this->response->body); @@ -174,9 +174,9 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); - $this->assertEquals(200, $this->response->status,'We received an incorrect status code. Full response body: ' . $this->response->getBody()); + $this->assertEquals(200, $this->response->status, 'We received an incorrect status code. Full response body: ' . $this->response->getBody()); } @@ -209,9 +209,9 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); - $this->assertEquals(423, $this->response->getStatus(),'We received an incorrect status code. Full response body: ' . $this->response->getBody()); + $this->assertEquals(423, $this->response->getStatus(), 'We received an incorrect status code. Full response body: ' . $this->response->getBody()); } @@ -233,8 +233,8 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(201, $this->response->status); @@ -251,7 +251,7 @@ class PluginTest extends DAV\AbstractServer { $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], + 'Content-Type' => ['application/xml; charset=utf-8'], ], $this->response->getHeaders() ); @@ -271,7 +271,7 @@ class PluginTest extends DAV\AbstractServer { $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], + 'Content-Type' => ['application/xml; charset=utf-8'], ], $this->response->getHeaders() ); @@ -298,8 +298,8 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(200, $this->response->status); @@ -308,8 +308,8 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(423, $this->response->status); @@ -340,10 +340,10 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpResponse = new HTTP\ResponseMock(); $this->server->invokeMethod($request, $this->server->httpResponse); - $this->assertEquals(204,$this->server->httpResponse->status,'Got an incorrect status code. Full response body: ' . $this->response->body); + $this->assertEquals(204, $this->server->httpResponse->status, 'Got an incorrect status code. Full response body: ' . $this->response->body); $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Length' => ['0'], + 'Content-Length' => ['0'], ], $this->server->httpResponse->getHeaders() ); @@ -372,17 +372,17 @@ class PluginTest extends DAV\AbstractServer { $lockToken = $this->server->httpResponse->getHeader('Lock-Token'); // See Issue 123 - $lockToken = trim($lockToken,'<>'); + $lockToken = trim($lockToken, '<>'); $request = new HTTP\Request('UNLOCK', '/test.txt', ['Lock-Token' => $lockToken]); $this->server->httpRequest = $request; $this->server->httpResponse = new HTTP\ResponseMock(); $this->server->invokeMethod($request, $this->server->httpResponse); - $this->assertEquals(204, $this->server->httpResponse->status,'Got an incorrect status code. Full response body: ' . $this->response->body); + $this->assertEquals(204, $this->server->httpResponse->status, 'Got an incorrect status code. Full response body: ' . $this->response->body); $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Length' => ['0'], + 'Content-Length' => ['0'], ], $this->server->httpResponse->getHeaders() ); @@ -396,7 +396,7 @@ class PluginTest extends DAV\AbstractServer { function testLockRetainOwner() { $request = HTTP\Sapi::createFromServerArray([ - 'REQUEST_URI' => '/test.txt', + 'REQUEST_URI' => '/test.txt', 'REQUEST_METHOD' => 'LOCK', ]); $this->server->httpRequest = $request; @@ -412,8 +412,8 @@ class PluginTest extends DAV\AbstractServer { $lockToken = $this->server->httpResponse->getHeader('Lock-Token'); $locks = $this->locksPlugin->getLocks('test.txt'); - $this->assertEquals(1,count($locks)); - $this->assertEquals('Evert',$locks[0]->owner); + $this->assertEquals(1, count($locks)); + $this->assertEquals('Evert', $locks[0]->owner); } @@ -423,10 +423,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockPutBadToken() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/test.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -441,24 +441,24 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(200, $this->response->status); - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/test.txt', 'REQUEST_METHOD' => 'PUT', - 'HTTP_IF' => '(<opaquelocktoken:token1>)', - ); + 'HTTP_IF' => '(<opaquelocktoken:token1>)', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('newbody'); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); // $this->assertEquals('412 Precondition failed',$this->response->status); $this->assertEquals(423, $this->response->status); @@ -470,10 +470,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockDeleteParent() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir/child.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -488,22 +488,22 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(200, $this->response->status); - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir', 'REQUEST_METHOD' => 'DELETE', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; $this->server->exec(); $this->assertEquals(423, $this->response->status); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); } /** @@ -511,10 +511,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockDeleteSucceed() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir/child.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -529,23 +529,23 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(200, $this->response->status); - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir/child.txt', 'REQUEST_METHOD' => 'DELETE', - 'HTTP_IF' => '(' . $this->response->getHeader('Lock-Token') . ')', - ); + 'HTTP_IF' => '(' . $this->response->getHeader('Lock-Token') . ')', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; $this->server->exec(); $this->assertEquals(204, $this->response->status); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); } @@ -554,10 +554,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockCopyLockSource() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir/child.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -572,23 +572,23 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(200, $this->response->status); - $serverVars = array( - 'REQUEST_URI' => '/dir/child.txt', - 'REQUEST_METHOD' => 'COPY', + $serverVars = [ + 'REQUEST_URI' => '/dir/child.txt', + 'REQUEST_METHOD' => 'COPY', 'HTTP_DESTINATION' => '/dir/child2.txt', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals(201, $this->response->status,'Copy must succeed if only the source is locked, but not the destination'); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals(201, $this->response->status, 'Copy must succeed if only the source is locked, but not the destination'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); } /** @@ -596,10 +596,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockCopyLockDestination() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir/child2.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -614,23 +614,23 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(201, $this->response->status); - $serverVars = array( - 'REQUEST_URI' => '/dir/child.txt', - 'REQUEST_METHOD' => 'COPY', + $serverVars = [ + 'REQUEST_URI' => '/dir/child.txt', + 'REQUEST_METHOD' => 'COPY', 'HTTP_DESTINATION' => '/dir/child2.txt', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals(423, $this->response->status,'Copy must succeed if only the source is locked, but not the destination'); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals(423, $this->response->status, 'Copy must succeed if only the source is locked, but not the destination'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); } @@ -639,10 +639,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockMoveLockSourceLocked() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir/child.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -657,23 +657,23 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(200, $this->response->status); - $serverVars = array( - 'REQUEST_URI' => '/dir/child.txt', - 'REQUEST_METHOD' => 'MOVE', + $serverVars = [ + 'REQUEST_URI' => '/dir/child.txt', + 'REQUEST_METHOD' => 'MOVE', 'HTTP_DESTINATION' => '/dir/child2.txt', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals(423, $this->response->status,'Copy must succeed if only the source is locked, but not the destination'); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals(423, $this->response->status, 'Copy must succeed if only the source is locked, but not the destination'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); } @@ -682,10 +682,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockMoveLockSourceSucceed() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir/child.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -700,23 +700,23 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(200, $this->response->status); - $serverVars = array( - 'REQUEST_URI' => '/dir/child.txt', - 'REQUEST_METHOD' => 'MOVE', + $serverVars = [ + 'REQUEST_URI' => '/dir/child.txt', + 'REQUEST_METHOD' => 'MOVE', 'HTTP_DESTINATION' => '/dir/child2.txt', - 'HTTP_IF' => '(' . $this->response->getHeader('Lock-Token') . ')', - ); + 'HTTP_IF' => '(' . $this->response->getHeader('Lock-Token') . ')', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals(201, $this->response->status,'A valid lock-token was provided for the source, so this MOVE operation must succeed. Full response body: ' . $this->response->body); + $this->assertEquals(201, $this->response->status, 'A valid lock-token was provided for the source, so this MOVE operation must succeed. Full response body: ' . $this->response->body); } @@ -725,10 +725,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockMoveLockDestination() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir/child2.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -743,23 +743,23 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(201, $this->response->status); - $serverVars = array( - 'REQUEST_URI' => '/dir/child.txt', - 'REQUEST_METHOD' => 'MOVE', + $serverVars = [ + 'REQUEST_URI' => '/dir/child.txt', + 'REQUEST_METHOD' => 'MOVE', 'HTTP_DESTINATION' => '/dir/child2.txt', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals(423, $this->response->status,'Copy must succeed if only the source is locked, but not the destination'); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals(423, $this->response->status, 'Copy must succeed if only the source is locked, but not the destination'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); } /** @@ -767,11 +767,11 @@ class PluginTest extends DAV\AbstractServer { */ function testLockMoveLockParent() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir', 'REQUEST_METHOD' => 'LOCK', - 'HTTP_DEPTH' => 'infinite', - ); + 'HTTP_DEPTH' => 'infinite', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -786,24 +786,24 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); - $this->assertEquals(200,$this->response->status); + $this->assertEquals(200, $this->response->status); - $serverVars = array( - 'REQUEST_URI' => '/dir/child.txt', - 'REQUEST_METHOD' => 'MOVE', + $serverVars = [ + 'REQUEST_URI' => '/dir/child.txt', + 'REQUEST_METHOD' => 'MOVE', 'HTTP_DESTINATION' => '/dir/child2.txt', - 'HTTP_IF' => '</dir> (' . $this->response->getHeader('Lock-Token') . ')', - ); + 'HTTP_IF' => '</dir> (' . $this->response->getHeader('Lock-Token') . ')', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals(201, $this->response->status,'We locked the parent of both the source and destination, but the move didn\'t succeed.'); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); + $this->assertEquals(201, $this->response->status, 'We locked the parent of both the source and destination, but the move didn\'t succeed.'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); } @@ -812,10 +812,10 @@ class PluginTest extends DAV\AbstractServer { */ function testLockPutGoodToken() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/test.txt', 'REQUEST_METHOD' => 'LOCK', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -830,24 +830,24 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(200, $this->response->status); - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/test.txt', 'REQUEST_METHOD' => 'PUT', - 'HTTP_IF' => '('.$this->response->getHeader('Lock-Token').')', - ); + 'HTTP_IF' => '(' . $this->response->getHeader('Lock-Token') . ')', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('newbody'); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(204, $this->response->status); @@ -871,22 +871,22 @@ class PluginTest extends DAV\AbstractServer { $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(201, $this->response->getStatus()); $request = new HTTP\Request( 'PUT', '/test.txt', - ['If' => '</unrelated.txt> ('.$this->response->getHeader('Lock-Token').')'] + ['If' => '</unrelated.txt> (' . $this->response->getHeader('Lock-Token') . ')'] ); $request->setBody('newbody'); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); $this->assertEquals(204, $this->response->status); @@ -894,11 +894,11 @@ class PluginTest extends DAV\AbstractServer { function testPutWithIncorrectETag() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/test.txt', 'REQUEST_METHOD' => 'PUT', - 'HTTP_IF' => '(["etag1"])', - ); + 'HTTP_IF' => '(["etag1"])', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('newbody'); @@ -920,14 +920,14 @@ class PluginTest extends DAV\AbstractServer { $filename = SABRE_TEMPDIR . '/test.txt'; $etag = sha1( fileinode($filename) . - filesize($filename ) . + filesize($filename) . filemtime($filename) ); - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/test.txt', 'REQUEST_METHOD' => 'PUT', - 'HTTP_IF' => '(["'.$etag.'"])', - ); + 'HTTP_IF' => '(["' . $etag . '"])', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('newbody'); @@ -939,11 +939,11 @@ class PluginTest extends DAV\AbstractServer { function testDeleteWithETagOnCollection() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/dir', 'REQUEST_METHOD' => 'DELETE', - 'HTTP_IF' => '(["etag1"])', - ); + 'HTTP_IF' => '(["etag1"])', + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = $request; @@ -954,9 +954,9 @@ class PluginTest extends DAV\AbstractServer { function testGetTimeoutHeader() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'HTTP_TIMEOUT' => 'second-100', - )); + ]); $this->server->httpRequest = $request; $this->assertEquals(100, $this->locksPlugin->getTimeoutHeader()); @@ -965,9 +965,9 @@ class PluginTest extends DAV\AbstractServer { function testGetTimeoutHeaderTwoItems() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'HTTP_TIMEOUT' => 'second-5, infinite', - )); + ]); $this->server->httpRequest = $request; $this->assertEquals(5, $this->locksPlugin->getTimeoutHeader()); @@ -976,9 +976,9 @@ class PluginTest extends DAV\AbstractServer { function testGetTimeoutHeaderInfinite() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'HTTP_TIMEOUT' => 'infinite, second-5', - )); + ]); $this->server->httpRequest = $request; $this->assertEquals(LockInfo::TIMEOUT_INFINITE, $this->locksPlugin->getTimeoutHeader()); @@ -990,9 +990,9 @@ class PluginTest extends DAV\AbstractServer { */ function testGetTimeoutHeaderInvalid() { - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'HTTP_TIMEOUT' => 'yourmom', - )); + ]); $this->server->httpRequest = $request; $this->locksPlugin->getTimeoutHeader(); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Mount/PluginTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Mount/PluginTest.php index e6415792c..3213fcb1b 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Mount/PluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Mount/PluginTest.php @@ -18,27 +18,27 @@ class PluginTest extends DAV\AbstractServer { function testPassThrough() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/', 'REQUEST_METHOD' => 'GET', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(501, $this->response->status,'We expected GET to not be implemented for Directories. Response body: ' . $this->response->body); + $this->assertEquals(501, $this->response->status, 'We expected GET to not be implemented for Directories. Response body: ' . $this->response->body); } function testMountResponse() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/?mount', 'REQUEST_METHOD' => 'GET', 'QUERY_STRING' => 'mount', 'HTTP_HOST' => 'example.org', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = ($request); @@ -47,11 +47,11 @@ class PluginTest extends DAV\AbstractServer { $this->assertEquals(200, $this->response->status); $xml = simplexml_load_string($this->response->body); - $this->assertInstanceOf('SimpleXMLElement',$xml, 'Response was not a valid xml document. The list of errors:' . print_r(libxml_get_errors(),true) . '. xml body: ' . $this->response->body . '. What type we got: ' . gettype($xml) . ' class, if object: ' . get_class($xml)); + $this->assertInstanceOf('SimpleXMLElement', $xml, 'Response was not a valid xml document. The list of errors:' . print_r(libxml_get_errors(), true) . '. xml body: ' . $this->response->body . '. What type we got: ' . gettype($xml) . ' class, if object: ' . get_class($xml)); - $xml->registerXPathNamespace('dm','http://purl.org/NET/webdav/mount'); + $xml->registerXPathNamespace('dm', 'http://purl.org/NET/webdav/mount'); $url = $xml->xpath('//dm:url'); - $this->assertEquals('http://example.org/',(string)$url[0]); + $this->assertEquals('http://example.org/', (string)$url[0]); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ObjectTreeTest.php b/vendor/sabre/dav/tests/Sabre/DAV/ObjectTreeTest.php index 9b7eeb90c..15289ce52 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ObjectTreeTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ObjectTreeTest.php @@ -13,8 +13,8 @@ class ObjectTreeTest extends \PHPUnit_Framework_TestCase { \Sabre\TestUtil::clearTempDir(); mkdir(SABRE_TEMPDIR . '/root'); mkdir(SABRE_TEMPDIR . '/root/subdir'); - file_put_contents(SABRE_TEMPDIR . '/root/file.txt','contents'); - file_put_contents(SABRE_TEMPDIR . '/root/subdir/subfile.txt','subcontents'); + file_put_contents(SABRE_TEMPDIR . '/root/file.txt', 'contents'); + file_put_contents(SABRE_TEMPDIR . '/root/subdir/subfile.txt', 'subcontents'); $rootNode = new FSExt\Directory(SABRE_TEMPDIR . '/root'); $this->tree = new Tree($rootNode); @@ -29,22 +29,22 @@ class ObjectTreeTest extends \PHPUnit_Framework_TestCase { function testGetRootNode() { $root = $this->tree->getNodeForPath(''); - $this->assertInstanceOf('Sabre\\DAV\\FSExt\\Directory',$root); + $this->assertInstanceOf('Sabre\\DAV\\FSExt\\Directory', $root); } function testGetSubDir() { $root = $this->tree->getNodeForPath('subdir'); - $this->assertInstanceOf('Sabre\\DAV\\FSExt\\Directory',$root); + $this->assertInstanceOf('Sabre\\DAV\\FSExt\\Directory', $root); } function testCopyFile() { - $this->tree->copy('file.txt','file2.txt'); - $this->assertTrue(file_exists(SABRE_TEMPDIR.'/root/file2.txt')); - $this->assertEquals('contents',file_get_contents(SABRE_TEMPDIR.'/root/file2.txt')); + $this->tree->copy('file.txt', 'file2.txt'); + $this->assertTrue(file_exists(SABRE_TEMPDIR . '/root/file2.txt')); + $this->assertEquals('contents', file_get_contents(SABRE_TEMPDIR . '/root/file2.txt')); } @@ -53,10 +53,10 @@ class ObjectTreeTest extends \PHPUnit_Framework_TestCase { */ function testCopyDirectory() { - $this->tree->copy('subdir','subdir2'); - $this->assertTrue(file_exists(SABRE_TEMPDIR.'/root/subdir2')); - $this->assertTrue(file_exists(SABRE_TEMPDIR.'/root/subdir2/subfile.txt')); - $this->assertEquals('subcontents',file_get_contents(SABRE_TEMPDIR.'/root/subdir2/subfile.txt')); + $this->tree->copy('subdir', 'subdir2'); + $this->assertTrue(file_exists(SABRE_TEMPDIR . '/root/subdir2')); + $this->assertTrue(file_exists(SABRE_TEMPDIR . '/root/subdir2/subfile.txt')); + $this->assertEquals('subcontents', file_get_contents(SABRE_TEMPDIR . '/root/subdir2/subfile.txt')); } @@ -65,10 +65,10 @@ class ObjectTreeTest extends \PHPUnit_Framework_TestCase { */ function testMoveFile() { - $this->tree->move('file.txt','file2.txt'); - $this->assertTrue(file_exists(SABRE_TEMPDIR.'/root/file2.txt')); - $this->assertFalse(file_exists(SABRE_TEMPDIR.'/root/file.txt')); - $this->assertEquals('contents',file_get_contents(SABRE_TEMPDIR.'/root/file2.txt')); + $this->tree->move('file.txt', 'file2.txt'); + $this->assertTrue(file_exists(SABRE_TEMPDIR . '/root/file2.txt')); + $this->assertFalse(file_exists(SABRE_TEMPDIR . '/root/file.txt')); + $this->assertEquals('contents', file_get_contents(SABRE_TEMPDIR . '/root/file2.txt')); } @@ -77,10 +77,10 @@ class ObjectTreeTest extends \PHPUnit_Framework_TestCase { */ function testMoveFileNewParent() { - $this->tree->move('file.txt','subdir/file2.txt'); - $this->assertTrue(file_exists(SABRE_TEMPDIR.'/root/subdir/file2.txt')); - $this->assertFalse(file_exists(SABRE_TEMPDIR.'/root/file.txt')); - $this->assertEquals('contents',file_get_contents(SABRE_TEMPDIR.'/root/subdir/file2.txt')); + $this->tree->move('file.txt', 'subdir/file2.txt'); + $this->assertTrue(file_exists(SABRE_TEMPDIR . '/root/subdir/file2.txt')); + $this->assertFalse(file_exists(SABRE_TEMPDIR . '/root/file.txt')); + $this->assertEquals('contents', file_get_contents(SABRE_TEMPDIR . '/root/subdir/file2.txt')); } @@ -89,11 +89,11 @@ class ObjectTreeTest extends \PHPUnit_Framework_TestCase { */ function testMoveDirectory() { - $this->tree->move('subdir','subdir2'); - $this->assertTrue(file_exists(SABRE_TEMPDIR.'/root/subdir2')); - $this->assertTrue(file_exists(SABRE_TEMPDIR.'/root/subdir2/subfile.txt')); - $this->assertFalse(file_exists(SABRE_TEMPDIR.'/root/subdir')); - $this->assertEquals('subcontents',file_get_contents(SABRE_TEMPDIR.'/root/subdir2/subfile.txt')); + $this->tree->move('subdir', 'subdir2'); + $this->assertTrue(file_exists(SABRE_TEMPDIR . '/root/subdir2')); + $this->assertTrue(file_exists(SABRE_TEMPDIR . '/root/subdir2/subfile.txt')); + $this->assertFalse(file_exists(SABRE_TEMPDIR . '/root/subdir')); + $this->assertEquals('subcontents', file_get_contents(SABRE_TEMPDIR . '/root/subdir2/subfile.txt')); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/PartialUpdate/FileMock.php b/vendor/sabre/dav/tests/Sabre/DAV/PartialUpdate/FileMock.php index d6cc406be..eff1e7d67 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/PartialUpdate/FileMock.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/PartialUpdate/FileMock.php @@ -1,6 +1,7 @@ <?php namespace Sabre\DAV\PartialUpdate; + use Sabre\DAV; class FileMock implements IPatchSupport { @@ -49,10 +50,10 @@ class FileMock implements IPatchSupport { $data = stream_get_contents($data); } - switch($rangeType) { + switch ($rangeType) { case 1 : - $this->data.=$data; + $this->data .= $data; break; case 3 : // Turn the offset into an offset-offset. diff --git a/vendor/sabre/dav/tests/Sabre/DAV/PartialUpdate/SpecificationTest.php b/vendor/sabre/dav/tests/Sabre/DAV/PartialUpdate/SpecificationTest.php index 31be2a1b1..ca8ca3f6e 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/PartialUpdate/SpecificationTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/PartialUpdate/SpecificationTest.php @@ -16,11 +16,11 @@ class SpecificationTest extends \PHPUnit_Framework_TestCase { protected $server; - public function setUp() { + function setUp() { - $tree = array( + $tree = [ new File(SABRE_TEMPDIR . '/foobar.txt') - ); + ]; $server = new Server($tree); $server->debugExceptions = true; $server->addPlugin(new Plugin()); @@ -31,7 +31,7 @@ class SpecificationTest extends \PHPUnit_Framework_TestCase { } - public function tearDown() { + function tearDown() { \Sabre\TestUtil::clearTempDir(); @@ -40,10 +40,10 @@ class SpecificationTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider data */ - public function testUpdateRange($headerValue, $httpStatus, $endResult, $contentLength = 4) { + function testUpdateRange($headerValue, $httpStatus, $endResult, $contentLength = 4) { $headers = [ - 'Content-Type' => 'application/x-sabredav-partialupdate', + 'Content-Type' => 'application/x-sabredav-partialupdate', 'X-Update-Range' => $headerValue, ]; @@ -64,25 +64,25 @@ class SpecificationTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($endResult, file_get_contents(SABRE_TEMPDIR . '/foobar.txt')); } - } + } - public function data() { + function data() { - return array( + return [ // Problems - array('foo', 400, null), - array('bytes=0-3', 411, null, 0), - array('bytes=4-1', 416, null), - - array('bytes=0-3', 204, '----567890'), - array('bytes=1-4', 204, '1----67890'), - array('bytes=0-', 204, '----567890'), - array('bytes=-4', 204, '123456----'), - array('bytes=-2', 204, '12345678----'), - array('bytes=2-', 204, '12----7890'), - array('append', 204, '1234567890----'), - - ); + ['foo', 400, null], + ['bytes=0-3', 411, null, 0], + ['bytes=4-1', 416, null], + + ['bytes=0-3', 204, '----567890'], + ['bytes=1-4', 204, '1----67890'], + ['bytes=0-', 204, '----567890'], + ['bytes=-4', 204, '123456----'], + ['bytes=-2', 204, '12345678----'], + ['bytes=2-', 204, '12----7890'], + ['append', 204, '1234567890----'], + + ]; } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ServerMKCOLTest.php b/vendor/sabre/dav/tests/Sabre/DAV/ServerMKCOLTest.php index e35189ec3..557eddbbc 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ServerMKCOLTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ServerMKCOLTest.php @@ -8,20 +8,20 @@ class ServerMKCOLTest extends AbstractServer { function testMkcol() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/testcol', 'REQUEST_METHOD' => 'MKCOL', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody(""); $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - ),$this->response->getHeaders()); + 'Content-Length' => ['0'], + ], $this->response->getHeaders()); $this->assertEquals(201, $this->response->status); $this->assertEquals('', $this->response->body); @@ -34,20 +34,20 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLUnknownBody() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/testcol', 'REQUEST_METHOD' => 'MKCOL', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody("Hello"); $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); $this->assertEquals(415, $this->response->status); @@ -58,23 +58,23 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLBrokenXML() { - $serverVars = array( - 'REQUEST_URI' => '/testcol', - 'REQUEST_METHOD' => 'MKCOL', + $serverVars = [ + 'REQUEST_URI' => '/testcol', + 'REQUEST_METHOD' => 'MKCOL', 'HTTP_CONTENT_TYPE' => 'application/xml', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody("Hello"); $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); - $this->assertEquals(400, $this->response->getStatus(), $this->response->getBodyAsString() ); + $this->assertEquals(400, $this->response->getStatus(), $this->response->getBodyAsString()); } @@ -83,21 +83,21 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLUnknownXML() { - $serverVars = array( - 'REQUEST_URI' => '/testcol', - 'REQUEST_METHOD' => 'MKCOL', + $serverVars = [ + 'REQUEST_URI' => '/testcol', + 'REQUEST_METHOD' => 'MKCOL', 'HTTP_CONTENT_TYPE' => 'application/xml', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?><html></html>'); $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); $this->assertEquals(400, $this->response->getStatus()); @@ -108,11 +108,11 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLNoResourceType() { - $serverVars = array( - 'REQUEST_URI' => '/testcol', - 'REQUEST_METHOD' => 'MKCOL', + $serverVars = [ + 'REQUEST_URI' => '/testcol', + 'REQUEST_METHOD' => 'MKCOL', 'HTTP_CONTENT_TYPE' => 'application/xml', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -126,12 +126,12 @@ class ServerMKCOLTest extends AbstractServer { $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); - $this->assertEquals(400, $this->response->status, 'Wrong statuscode received. Full response body: ' .$this->response->body); + $this->assertEquals(400, $this->response->status, 'Wrong statuscode received. Full response body: ' . $this->response->body); } @@ -140,11 +140,11 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLIncorrectResourceType() { - $serverVars = array( - 'REQUEST_URI' => '/testcol', - 'REQUEST_METHOD' => 'MKCOL', + $serverVars = [ + 'REQUEST_URI' => '/testcol', + 'REQUEST_METHOD' => 'MKCOL', 'HTTP_CONTENT_TYPE' => 'application/xml', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -158,12 +158,12 @@ class ServerMKCOLTest extends AbstractServer { $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); - $this->assertEquals(403, $this->response->status, 'Wrong statuscode received. Full response body: ' .$this->response->body); + $this->assertEquals(403, $this->response->status, 'Wrong statuscode received. Full response body: ' . $this->response->body); } @@ -172,11 +172,11 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLSuccess() { - $serverVars = array( - 'REQUEST_URI' => '/testcol', - 'REQUEST_METHOD' => 'MKCOL', + $serverVars = [ + 'REQUEST_URI' => '/testcol', + 'REQUEST_METHOD' => 'MKCOL', 'HTTP_CONTENT_TYPE' => 'application/xml', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -190,12 +190,12 @@ class ServerMKCOLTest extends AbstractServer { $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - ),$this->response->getHeaders()); + 'Content-Length' => ['0'], + ], $this->response->getHeaders()); - $this->assertEquals(201, $this->response->status, 'Wrong statuscode received. Full response body: ' .$this->response->body); + $this->assertEquals(201, $this->response->status, 'Wrong statuscode received. Full response body: ' . $this->response->body); } @@ -204,11 +204,11 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLWhiteSpaceResourceType() { - $serverVars = array( - 'REQUEST_URI' => '/testcol', - 'REQUEST_METHOD' => 'MKCOL', + $serverVars = [ + 'REQUEST_URI' => '/testcol', + 'REQUEST_METHOD' => 'MKCOL', 'HTTP_CONTENT_TYPE' => 'application/xml', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> @@ -224,12 +224,12 @@ class ServerMKCOLTest extends AbstractServer { $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Length' => ['0'], - ),$this->response->getHeaders()); + 'Content-Length' => ['0'], + ], $this->response->getHeaders()); - $this->assertEquals(201, $this->response->status, 'Wrong statuscode received. Full response body: ' .$this->response->body); + $this->assertEquals(201, $this->response->status, 'Wrong statuscode received. Full response body: ' . $this->response->body); } @@ -238,10 +238,10 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLNoParent() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/testnoparent/409me', 'REQUEST_METHOD' => 'MKCOL', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody(''); @@ -249,12 +249,12 @@ class ServerMKCOLTest extends AbstractServer { $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); - $this->assertEquals(409, $this->response->status, 'Wrong statuscode received. Full response body: ' .$this->response->body); + $this->assertEquals(409, $this->response->status, 'Wrong statuscode received. Full response body: ' . $this->response->body); } @@ -263,10 +263,10 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLParentIsNoCollection() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/test.txt/409me', 'REQUEST_METHOD' => 'MKCOL', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody(''); @@ -274,12 +274,12 @@ class ServerMKCOLTest extends AbstractServer { $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); - $this->assertEquals(409, $this->response->status, 'Wrong statuscode received. Full response body: ' .$this->response->body); + $this->assertEquals(409, $this->response->status, 'Wrong statuscode received. Full response body: ' . $this->response->body); } @@ -288,10 +288,10 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLAlreadyExists() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/test.txt', 'REQUEST_METHOD' => 'MKCOL', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody(''); @@ -299,13 +299,13 @@ class ServerMKCOLTest extends AbstractServer { $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - 'Allow' => ['OPTIONS, GET, HEAD, DELETE, PROPFIND, PUT, PROPPATCH, COPY, MOVE, REPORT'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + 'Allow' => ['OPTIONS, GET, HEAD, DELETE, PROPFIND, PUT, PROPPATCH, COPY, MOVE, REPORT'], + ], $this->response->getHeaders()); - $this->assertEquals(405, $this->response->status, 'Wrong statuscode received. Full response body: ' .$this->response->body); + $this->assertEquals(405, $this->response->status, 'Wrong statuscode received. Full response body: ' . $this->response->body); } @@ -315,13 +315,11 @@ class ServerMKCOLTest extends AbstractServer { */ function testMKCOLAndProps() { - $serverVars = array( - 'REQUEST_URI' => '/testcol', - 'REQUEST_METHOD' => 'MKCOL', - 'HTTP_CONTENT_TYPE' => 'application/xml', + $request = new HTTP\Request( + 'MKCOL', + '/testcol', + ['Content-Type' => 'application/xml'] ); - - $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody('<?xml version="1.0"?> <mkcol xmlns="DAV:"> <set> @@ -334,12 +332,34 @@ class ServerMKCOLTest extends AbstractServer { $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(207, $this->response->status, 'Wrong statuscode received. Full response body: ' .$this->response->body); + $this->assertEquals(207, $this->response->status, 'Wrong statuscode received. Full response body: ' . $this->response->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $this->response->getHeaders()); + + $responseBody = $this->response->getBodyAsString(); + + $expected = <<<XML +<?xml version="1.0"?> +<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns"> + <d:response> + <d:href>/testcol</d:href> + <d:propstat> + <d:prop> + <d:displayname /> + </d:prop> + <d:status>HTTP/1.1 403 Forbidden</d:status> + </d:propstat> + </d:response> +</d:multistatus> +XML; + + $this->assertXmlStringEqualsXmlString( + $expected, + $responseBody + ); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ServerPluginTest.php b/vendor/sabre/dav/tests/Sabre/DAV/ServerPluginTest.php index ab0ad295e..fa67102cc 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ServerPluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ServerPluginTest.php @@ -1,6 +1,7 @@ <?php namespace Sabre\DAV; + use Sabre\HTTP; require_once 'Sabre/DAV/AbstractServer.php'; @@ -28,13 +29,13 @@ class ServerPluginTest extends AbstractServer { function testBaseClass() { $p = new ServerPluginMock(); - $this->assertEquals([],$p->getFeatures()); - $this->assertEquals([],$p->getHTTPMethods('')); + $this->assertEquals([], $p->getFeatures()); + $this->assertEquals([], $p->getHTTPMethods('')); $this->assertEquals( [ - 'name' => 'Sabre\DAV\ServerPluginMock', + 'name' => 'Sabre\DAV\ServerPluginMock', 'description' => null, - 'link' => null + 'link' => null ], $p->getPluginInfo() ); @@ -42,34 +43,34 @@ class ServerPluginTest extends AbstractServer { function testOptions() { - $serverVars = array( + $serverVars = [ 'REQUEST_URI' => '/', 'REQUEST_METHOD' => 'OPTIONS', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(array( + $this->assertEquals([ 'DAV' => ['1, 3, extended-mkcol, drinking'], 'MS-Author-Via' => ['DAV'], 'Allow' => ['OPTIONS, GET, HEAD, DELETE, PROPFIND, PUT, PROPPATCH, COPY, MOVE, REPORT, BEER, WINE'], 'Accept-Ranges' => ['bytes'], 'Content-Length' => ['0'], 'X-Sabre-Version' => [Version::VERSION], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); $this->assertEquals(200, $this->response->status); $this->assertEquals('', $this->response->body); - $this->assertEquals('OPTIONS',$this->testPlugin->beforeMethod); + $this->assertEquals('OPTIONS', $this->testPlugin->beforeMethod); } function testGetPlugin() { - $this->assertEquals($this->testPlugin,$this->server->getPlugin(get_class($this->testPlugin))); + $this->assertEquals($this->testPlugin, $this->server->getPlugin(get_class($this->testPlugin))); } @@ -81,17 +82,17 @@ class ServerPluginTest extends AbstractServer { function testGetSupportedReportSet() { - $this->assertEquals(array(), $this->testPlugin->getSupportedReportSet('/')); + $this->assertEquals([], $this->testPlugin->getSupportedReportSet('/')); } function testGetPlugins() { $this->assertEquals( - array( + [ get_class($this->testPlugin) => $this->testPlugin, - 'core' => $this->server->getPlugin('core'), - ), + 'core' => $this->server->getPlugin('core'), + ], $this->server->getPlugins() ); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ServerPreconditionTest.php b/vendor/sabre/dav/tests/Sabre/DAV/ServerPreconditionTest.php index 1dc8d8a37..203cf26d9 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ServerPreconditionTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ServerPreconditionTest.php @@ -13,7 +13,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfMatchNoNode() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('GET', '/bar', ['If-Match' => '*']); $httpResponse = new HTTP\Response(); @@ -25,7 +25,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfMatchHasNode() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('GET', '/foo', ['If-Match' => '*']); $httpResponse = new HTTP\Response(); @@ -38,7 +38,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfMatchWrongEtag() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('GET', '/foo', ['If-Match' => '1234']); $httpResponse = new HTTP\Response(); @@ -50,7 +50,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfMatchCorrectEtag() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('GET', '/foo', ['If-Match' => '"abc123"']); $httpResponse = new HTTP\Response(); @@ -65,7 +65,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfMatchEvolutionEtag() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('GET', '/foo', ['If-Match' => '\\"abc123\\"']); $httpResponse = new HTTP\Response(); @@ -77,7 +77,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfMatchMultiple() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('GET', '/foo', ['If-Match' => '"hellothere", "abc123"']); $httpResponse = new HTTP\Response(); @@ -89,7 +89,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfNoneMatchNoNode() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('GET', '/bar', ['If-None-Match' => '*']); $httpResponse = new HTTP\Response(); @@ -102,7 +102,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfNoneMatchHasNode() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('POST', '/foo', ['If-None-Match' => '*']); $httpResponse = new HTTP\Response(); @@ -114,7 +114,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfNoneMatchWrongEtag() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('POST', '/foo', ['If-None-Match' => '"1234"']); $httpResponse = new HTTP\Response(); @@ -126,7 +126,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { */ function testIfNoneMatchWrongEtagMultiple() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('POST', '/foo', ['If-None-Match' => '"1234", "5678"']); $httpResponse = new HTTP\Response(); @@ -137,9 +137,9 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\PreconditionFailed */ - public function testIfNoneMatchCorrectEtag() { + function testIfNoneMatchCorrectEtag() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('POST', '/foo', ['If-None-Match' => '"abc123"']); $httpResponse = new HTTP\Response(); @@ -150,9 +150,9 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\PreconditionFailed */ - public function testIfNoneMatchCorrectEtagMultiple() { + function testIfNoneMatchCorrectEtagMultiple() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('POST', '/foo', ['If-None-Match' => '"1234, "abc123"']); $httpResponse = new HTTP\Response(); @@ -162,9 +162,9 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** */ - public function testIfNoneMatchCorrectEtagAsGet() { + function testIfNoneMatchCorrectEtagAsGet() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $httpRequest = new HTTP\Request('GET', '/foo', ['If-None-Match' => '"abc123"']); $server->httpResponse = new HTTP\ResponseMock(); @@ -178,9 +178,9 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** * This was a test written for issue #515. */ - public function testNoneMatchCorrectEtagEnsureSapiSent() { + function testNoneMatchCorrectEtagEnsureSapiSent() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); $server->sapi = new HTTP\SapiMock(); HTTP\SapiMock::$sent = 0; @@ -193,7 +193,7 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { $this->assertFalse($server->checkPreconditions($httpRequest, $server->httpResponse)); $this->assertEquals(304, $server->httpResponse->getStatus()); $this->assertEquals([ - 'ETag' => ['"abc123"'], + 'ETag' => ['"abc123"'], 'X-Sabre-Version' => [Version::VERSION], ], $server->httpResponse->getHeaders()); $this->assertEquals(1, HTTP\SapiMock::$sent); @@ -202,35 +202,35 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** */ - public function testIfModifiedSinceUnModified() { + function testIfModifiedSinceUnModified() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); - $httpRequest = HTTP\Sapi::createFromServerArray(array( + $httpRequest = HTTP\Sapi::createFromServerArray([ 'HTTP_IF_MODIFIED_SINCE' => 'Sun, 06 Nov 1994 08:49:37 GMT', - 'REQUEST_URI' => '/foo' - )); + 'REQUEST_URI' => '/foo' + ]); $server->httpResponse = new HTTP\ResponseMock(); $this->assertFalse($server->checkPreconditions($httpRequest, $server->httpResponse)); $this->assertEquals(304, $server->httpResponse->status); - $this->assertEquals(array( + $this->assertEquals([ 'Last-Modified' => ['Sat, 06 Apr 1985 23:30:00 GMT'], - ), $server->httpResponse->getHeaders()); + ], $server->httpResponse->getHeaders()); } /** */ - public function testIfModifiedSinceModified() { + function testIfModifiedSinceModified() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); - $httpRequest = HTTP\Sapi::createFromServerArray(array( + $httpRequest = HTTP\Sapi::createFromServerArray([ 'HTTP_IF_MODIFIED_SINCE' => 'Tue, 06 Nov 1984 08:49:37 GMT', - 'REQUEST_URI' => '/foo' - )); + 'REQUEST_URI' => '/foo' + ]); $httpResponse = new HTTP\ResponseMock(); $this->assertTrue($server->checkPreconditions($httpRequest, $httpResponse)); @@ -239,14 +239,14 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** */ - public function testIfModifiedSinceInvalidDate() { + function testIfModifiedSinceInvalidDate() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); - $httpRequest = HTTP\Sapi::createFromServerArray(array( + $httpRequest = HTTP\Sapi::createFromServerArray([ 'HTTP_IF_MODIFIED_SINCE' => 'Your mother', - 'REQUEST_URI' => '/foo' - )); + 'REQUEST_URI' => '/foo' + ]); $httpResponse = new HTTP\ResponseMock(); // Invalid dates must be ignored, so this should return true @@ -256,14 +256,14 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** */ - public function testIfModifiedSinceInvalidDate2() { + function testIfModifiedSinceInvalidDate2() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); - $httpRequest = HTTP\Sapi::createFromServerArray(array( + $httpRequest = HTTP\Sapi::createFromServerArray([ 'HTTP_IF_MODIFIED_SINCE' => 'Sun, 06 Nov 1994 08:49:37 EST', - 'REQUEST_URI' => '/foo' - )); + 'REQUEST_URI' => '/foo' + ]); $httpResponse = new HTTP\ResponseMock(); $this->assertTrue($server->checkPreconditions($httpRequest, $httpResponse)); @@ -272,14 +272,14 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** */ - public function testIfUnmodifiedSinceUnModified() { + function testIfUnmodifiedSinceUnModified() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); - $httpRequest = HTTP\Sapi::createFromServerArray(array( + $httpRequest = HTTP\Sapi::createFromServerArray([ 'HTTP_IF_UNMODIFIED_SINCE' => 'Sun, 06 Nov 1994 08:49:37 GMT', - 'REQUEST_URI' => '/foo' - )); + 'REQUEST_URI' => '/foo' + ]); $httpResponse = new HTTP\Response(); $this->assertTrue($server->checkPreconditions($httpRequest, $httpResponse)); @@ -289,14 +289,14 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\PreconditionFailed */ - public function testIfUnmodifiedSinceModified() { + function testIfUnmodifiedSinceModified() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); - $httpRequest = HTTP\Sapi::createFromServerArray(array( + $httpRequest = HTTP\Sapi::createFromServerArray([ 'HTTP_IF_UNMODIFIED_SINCE' => 'Tue, 06 Nov 1984 08:49:37 GMT', - 'REQUEST_URI' => '/foo' - )); + 'REQUEST_URI' => '/foo' + ]); $httpResponse = new HTTP\ResponseMock(); $server->checkPreconditions($httpRequest, $httpResponse); @@ -304,14 +304,14 @@ class ServerPreconditionsTest extends \PHPUnit_Framework_TestCase { /** */ - public function testIfUnmodifiedSinceInvalidDate() { + function testIfUnmodifiedSinceInvalidDate() { - $root = new SimpleCollection('root',array(new ServerPreconditionsNode())); + $root = new SimpleCollection('root', [new ServerPreconditionsNode()]); $server = new Server($root); - $httpRequest = HTTP\Sapi::createFromServerArray(array( + $httpRequest = HTTP\Sapi::createFromServerArray([ 'HTTP_IF_UNMODIFIED_SINCE' => 'Sun, 06 Nov 1984 08:49:37 CET', - 'REQUEST_URI' => '/foo' - )); + 'REQUEST_URI' => '/foo' + ]); $httpResponse = new HTTP\ResponseMock(); $this->assertTrue($server->checkPreconditions($httpRequest, $httpResponse)); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ServerSimpleTest.php b/vendor/sabre/dav/tests/Sabre/DAV/ServerSimpleTest.php index 66dde9db8..043179a00 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ServerSimpleTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ServerSimpleTest.php @@ -463,7 +463,7 @@ class ServerSimpleTest extends AbstractServer{ * There are certain cases where no HTTP status may be set. We need to * intercept these and set it to a default error message. */ - function testNoHTTPSTatusSet() { + function testNoHTTPStatusSet() { $this->server->on('method:GET', function() { return false; }, 1); $this->server->httpRequest = new HTTP\Request('GET', '/'); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ServerUpdatePropertiesTest.php b/vendor/sabre/dav/tests/Sabre/DAV/ServerUpdatePropertiesTest.php index 7fde11b22..383f8e657 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ServerUpdatePropertiesTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ServerUpdatePropertiesTest.php @@ -1,101 +1,100 @@ <?php namespace Sabre\DAV; -use Sabre\HTTP; class ServerUpdatePropertiesTest extends \PHPUnit_Framework_TestCase { function testUpdatePropertiesFail() { - $tree = array( + $tree = [ new SimpleCollection('foo'), - ); + ]; $server = new Server($tree); - $result = $server->updateProperties('foo', array( + $result = $server->updateProperties('foo', [ '{DAV:}foo' => 'bar' - )); + ]); - $expected = array( + $expected = [ '{DAV:}foo' => 403, - ); + ]; $this->assertEquals($expected, $result); } function testUpdatePropertiesProtected() { - $tree = array( + $tree = [ new SimpleCollection('foo'), - ); + ]; $server = new Server($tree); $server->on('propPatch', function($path, PropPatch $propPatch) { $propPatch->handleRemaining(function() { return true; }); }); - $result = $server->updateProperties('foo', array( + $result = $server->updateProperties('foo', [ '{DAV:}getetag' => 'bla', - '{DAV:}foo' => 'bar' - )); + '{DAV:}foo' => 'bar' + ]); - $expected = array( + $expected = [ '{DAV:}getetag' => 403, - '{DAV:}foo' => 424, - ); + '{DAV:}foo' => 424, + ]; $this->assertEquals($expected, $result); } function testUpdatePropertiesEventFail() { - $tree = array( + $tree = [ new SimpleCollection('foo'), - ); + ]; $server = new Server($tree); $server->on('propPatch', function($path, PropPatch $propPatch) { $propPatch->setResultCode('{DAV:}foo', 404); $propPatch->handleRemaining(function() { return true; }); }); - $result = $server->updateProperties('foo', array( - '{DAV:}foo' => 'bar', + $result = $server->updateProperties('foo', [ + '{DAV:}foo' => 'bar', '{DAV:}foo2' => 'bla', - )); + ]); - $expected = array( - '{DAV:}foo' => 404, + $expected = [ + '{DAV:}foo' => 404, '{DAV:}foo2' => 424, - ); + ]; $this->assertEquals($expected, $result); } function testUpdatePropertiesEventSuccess() { - $tree = array( + $tree = [ new SimpleCollection('foo'), - ); + ]; $server = new Server($tree); $server->on('propPatch', function($path, PropPatch $propPatch) { $propPatch->handle(['{DAV:}foo', '{DAV:}foo2'], function() { return [ - '{DAV:}foo' => 200, + '{DAV:}foo' => 200, '{DAV:}foo2' => 201, ]; }); }); - $result = $server->updateProperties('foo', array( - '{DAV:}foo' => 'bar', + $result = $server->updateProperties('foo', [ + '{DAV:}foo' => 'bar', '{DAV:}foo2' => 'bla', - )); + ]); - $expected = array( - '{DAV:}foo' => 200, + $expected = [ + '{DAV:}foo' => 200, '{DAV:}foo2' => 201, - ); + ]; $this->assertEquals($expected, $result); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/SimpleFileTest.php b/vendor/sabre/dav/tests/Sabre/DAV/SimpleFileTest.php index 9b083b998..15ccfaf9e 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/SimpleFileTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/SimpleFileTest.php @@ -6,7 +6,7 @@ class SimpleFileTest extends \PHPUnit_Framework_TestCase { function testAll() { - $file = new SimpleFile('filename.txt','contents','text/plain'); + $file = new SimpleFile('filename.txt', 'contents', 'text/plain'); $this->assertEquals('filename.txt', $file->getName()); $this->assertEquals('contents', $file->get()); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/StringUtilTest.php b/vendor/sabre/dav/tests/Sabre/DAV/StringUtilTest.php index 941d1f913..8888f0276 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/StringUtilTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/StringUtilTest.php @@ -15,61 +15,61 @@ class StringUtilTest extends \PHPUnit_Framework_TestCase { function dataset() { - return array( - array('FOOBAR', 'FOO', 'i;octet', 'contains', true), - array('FOOBAR', 'foo', 'i;octet', 'contains', false), - array('FÖÖBAR', 'FÖÖ', 'i;octet', 'contains', true), - array('FÖÖBAR', 'föö', 'i;octet', 'contains', false), - array('FOOBAR', 'FOOBAR', 'i;octet', 'equals', true), - array('FOOBAR', 'fooBAR', 'i;octet', 'equals', false), - array('FOOBAR', 'FOO', 'i;octet', 'starts-with', true), - array('FOOBAR', 'foo', 'i;octet', 'starts-with', false), - array('FOOBAR', 'BAR', 'i;octet', 'starts-with', false), - array('FOOBAR', 'bar', 'i;octet', 'starts-with', false), - array('FOOBAR', 'FOO', 'i;octet', 'ends-with', false), - array('FOOBAR', 'foo', 'i;octet', 'ends-with', false), - array('FOOBAR', 'BAR', 'i;octet', 'ends-with', true), - array('FOOBAR', 'bar', 'i;octet', 'ends-with', false), - - array('FOOBAR', 'FOO', 'i;ascii-casemap', 'contains', true), - array('FOOBAR', 'foo', 'i;ascii-casemap', 'contains', true), - array('FÖÖBAR', 'FÖÖ', 'i;ascii-casemap', 'contains', true), - array('FÖÖBAR', 'föö', 'i;ascii-casemap', 'contains', false), - array('FOOBAR', 'FOOBAR', 'i;ascii-casemap', 'equals', true), - array('FOOBAR', 'fooBAR', 'i;ascii-casemap', 'equals', true), - array('FOOBAR', 'FOO', 'i;ascii-casemap', 'starts-with', true), - array('FOOBAR', 'foo', 'i;ascii-casemap', 'starts-with', true), - array('FOOBAR', 'BAR', 'i;ascii-casemap', 'starts-with', false), - array('FOOBAR', 'bar', 'i;ascii-casemap', 'starts-with', false), - array('FOOBAR', 'FOO', 'i;ascii-casemap', 'ends-with', false), - array('FOOBAR', 'foo', 'i;ascii-casemap', 'ends-with', false), - array('FOOBAR', 'BAR', 'i;ascii-casemap', 'ends-with', true), - array('FOOBAR', 'bar', 'i;ascii-casemap', 'ends-with', true), - - array('FOOBAR', 'FOO', 'i;unicode-casemap', 'contains', true), - array('FOOBAR', 'foo', 'i;unicode-casemap', 'contains', true), - array('FÖÖBAR', 'FÖÖ', 'i;unicode-casemap', 'contains', true), - array('FÖÖBAR', 'föö', 'i;unicode-casemap', 'contains', true), - array('FOOBAR', 'FOOBAR', 'i;unicode-casemap', 'equals', true), - array('FOOBAR', 'fooBAR', 'i;unicode-casemap', 'equals', true), - array('FOOBAR', 'FOO', 'i;unicode-casemap', 'starts-with', true), - array('FOOBAR', 'foo', 'i;unicode-casemap', 'starts-with', true), - array('FOOBAR', 'BAR', 'i;unicode-casemap', 'starts-with', false), - array('FOOBAR', 'bar', 'i;unicode-casemap', 'starts-with', false), - array('FOOBAR', 'FOO', 'i;unicode-casemap', 'ends-with', false), - array('FOOBAR', 'foo', 'i;unicode-casemap', 'ends-with', false), - array('FOOBAR', 'BAR', 'i;unicode-casemap', 'ends-with', true), - array('FOOBAR', 'bar', 'i;unicode-casemap', 'ends-with', true), - ); + return [ + ['FOOBAR', 'FOO', 'i;octet', 'contains', true], + ['FOOBAR', 'foo', 'i;octet', 'contains', false], + ['FÖÖBAR', 'FÖÖ', 'i;octet', 'contains', true], + ['FÖÖBAR', 'föö', 'i;octet', 'contains', false], + ['FOOBAR', 'FOOBAR', 'i;octet', 'equals', true], + ['FOOBAR', 'fooBAR', 'i;octet', 'equals', false], + ['FOOBAR', 'FOO', 'i;octet', 'starts-with', true], + ['FOOBAR', 'foo', 'i;octet', 'starts-with', false], + ['FOOBAR', 'BAR', 'i;octet', 'starts-with', false], + ['FOOBAR', 'bar', 'i;octet', 'starts-with', false], + ['FOOBAR', 'FOO', 'i;octet', 'ends-with', false], + ['FOOBAR', 'foo', 'i;octet', 'ends-with', false], + ['FOOBAR', 'BAR', 'i;octet', 'ends-with', true], + ['FOOBAR', 'bar', 'i;octet', 'ends-with', false], + + ['FOOBAR', 'FOO', 'i;ascii-casemap', 'contains', true], + ['FOOBAR', 'foo', 'i;ascii-casemap', 'contains', true], + ['FÖÖBAR', 'FÖÖ', 'i;ascii-casemap', 'contains', true], + ['FÖÖBAR', 'föö', 'i;ascii-casemap', 'contains', false], + ['FOOBAR', 'FOOBAR', 'i;ascii-casemap', 'equals', true], + ['FOOBAR', 'fooBAR', 'i;ascii-casemap', 'equals', true], + ['FOOBAR', 'FOO', 'i;ascii-casemap', 'starts-with', true], + ['FOOBAR', 'foo', 'i;ascii-casemap', 'starts-with', true], + ['FOOBAR', 'BAR', 'i;ascii-casemap', 'starts-with', false], + ['FOOBAR', 'bar', 'i;ascii-casemap', 'starts-with', false], + ['FOOBAR', 'FOO', 'i;ascii-casemap', 'ends-with', false], + ['FOOBAR', 'foo', 'i;ascii-casemap', 'ends-with', false], + ['FOOBAR', 'BAR', 'i;ascii-casemap', 'ends-with', true], + ['FOOBAR', 'bar', 'i;ascii-casemap', 'ends-with', true], + + ['FOOBAR', 'FOO', 'i;unicode-casemap', 'contains', true], + ['FOOBAR', 'foo', 'i;unicode-casemap', 'contains', true], + ['FÖÖBAR', 'FÖÖ', 'i;unicode-casemap', 'contains', true], + ['FÖÖBAR', 'föö', 'i;unicode-casemap', 'contains', true], + ['FOOBAR', 'FOOBAR', 'i;unicode-casemap', 'equals', true], + ['FOOBAR', 'fooBAR', 'i;unicode-casemap', 'equals', true], + ['FOOBAR', 'FOO', 'i;unicode-casemap', 'starts-with', true], + ['FOOBAR', 'foo', 'i;unicode-casemap', 'starts-with', true], + ['FOOBAR', 'BAR', 'i;unicode-casemap', 'starts-with', false], + ['FOOBAR', 'bar', 'i;unicode-casemap', 'starts-with', false], + ['FOOBAR', 'FOO', 'i;unicode-casemap', 'ends-with', false], + ['FOOBAR', 'foo', 'i;unicode-casemap', 'ends-with', false], + ['FOOBAR', 'BAR', 'i;unicode-casemap', 'ends-with', true], + ['FOOBAR', 'bar', 'i;unicode-casemap', 'ends-with', true], + ]; } /** * @expectedException Sabre\DAV\Exception\BadRequest */ - public function testBadCollation() { + function testBadCollation() { - StringUtil::textMatch('foobar','foo','blabla','contains'); + StringUtil::textMatch('foobar', 'foo', 'blabla', 'contains'); } @@ -77,13 +77,13 @@ class StringUtilTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception\BadRequest */ - public function testBadMatchType() { + function testBadMatchType() { - StringUtil::textMatch('foobar','foo','i;octet','booh'); + StringUtil::textMatch('foobar', 'foo', 'i;octet', 'booh'); } - public function testEnsureUTF8_ascii() { + function testEnsureUTF8_ascii() { $inputString = "harkema"; $outputString = "harkema"; @@ -95,7 +95,7 @@ class StringUtilTest extends \PHPUnit_Framework_TestCase { } - public function testEnsureUTF8_latin1() { + function testEnsureUTF8_latin1() { $inputString = "m\xfcnster"; $outputString = "münster"; @@ -107,7 +107,7 @@ class StringUtilTest extends \PHPUnit_Framework_TestCase { } - public function testEnsureUTF8_utf8() { + function testEnsureUTF8_utf8() { $inputString = "m\xc3\xbcnster"; $outputString = "münster"; diff --git a/vendor/sabre/dav/tests/Sabre/DAV/TemporaryFileFilterTest.php b/vendor/sabre/dav/tests/Sabre/DAV/TemporaryFileFilterTest.php index 7122f4a01..6acd6b077 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/TemporaryFileFilterTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/TemporaryFileFilterTest.php @@ -25,7 +25,7 @@ class TemporaryFileFilterTest extends AbstractServer { $this->assertEquals(201, $this->response->status); $this->assertEquals('0', $this->response->getHeader('Content-Length')); - $this->assertEquals('Testing new file',file_get_contents(SABRE_TEMPDIR . '/testput.txt')); + $this->assertEquals('Testing new file', file_get_contents(SABRE_TEMPDIR . '/testput.txt')); } @@ -39,11 +39,11 @@ class TemporaryFileFilterTest extends AbstractServer { $this->assertEquals('', $this->response->body); $this->assertEquals(201, $this->response->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Temp' => ['true'], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); - $this->assertFalse(file_exists(SABRE_TEMPDIR . '/._testput.txt'),'._testput.txt should not exist in the regular file structure.'); + $this->assertFalse(file_exists(SABRE_TEMPDIR . '/._testput.txt'), '._testput.txt should not exist in the regular file structure.'); } @@ -57,20 +57,20 @@ class TemporaryFileFilterTest extends AbstractServer { $this->assertEquals('', $this->response->body); $this->assertEquals(201, $this->response->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Temp' => ['true'], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); - $this->assertFalse(file_exists(SABRE_TEMPDIR . '/._testput.txt'),'._testput.txt should not exist in the regular file structure.'); + $this->assertFalse(file_exists(SABRE_TEMPDIR . '/._testput.txt'), '._testput.txt should not exist in the regular file structure.'); $this->server->exec(); $this->assertEquals(412, $this->response->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Temp' => ['true'], 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); } @@ -83,9 +83,9 @@ class TemporaryFileFilterTest extends AbstractServer { $this->assertEquals('', $this->response->body); $this->assertEquals(201, $this->response->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Temp' => ['true'], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); $request = new HTTP\Request('GET', '/._testput.txt'); @@ -93,13 +93,13 @@ class TemporaryFileFilterTest extends AbstractServer { $this->server->exec(); $this->assertEquals(200, $this->response->status); - $this->assertEquals(array( - 'X-Sabre-Temp' => ['true'], + $this->assertEquals([ + 'X-Sabre-Temp' => ['true'], 'Content-Length' => [16], - 'Content-Type' => ['application/octet-stream'], - ),$this->response->getHeaders()); + 'Content-Type' => ['application/octet-stream'], + ], $this->response->getHeaders()); - $this->assertEquals('Testing new file',stream_get_contents($this->response->body)); + $this->assertEquals('Testing new file', stream_get_contents($this->response->body)); } @@ -125,11 +125,11 @@ class TemporaryFileFilterTest extends AbstractServer { $this->server->exec(); $this->assertEquals(201, $this->response->status); - $this->assertEquals('application/xml; charset=utf-8',$this->response->getHeader('Content-Type')); - $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/',$this->response->getHeader('Lock-Token'))===1,'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); - $this->assertEquals('true',$this->response->getHeader('X-Sabre-Temp')); + $this->assertEquals('application/xml; charset=utf-8', $this->response->getHeader('Content-Type')); + $this->assertTrue(preg_match('/^<opaquelocktoken:(.*)>$/', $this->response->getHeader('Lock-Token')) === 1, 'We did not get a valid Locktoken back (' . $this->response->getHeader('Lock-Token') . ')'); + $this->assertEquals('true', $this->response->getHeader('X-Sabre-Temp')); - $this->assertFalse(file_exists(SABRE_TEMPDIR . '/._testlock.txt'),'._testlock.txt should not exist in the regular file structure.'); + $this->assertFalse(file_exists(SABRE_TEMPDIR . '/._testlock.txt'), '._testlock.txt should not exist in the regular file structure.'); } @@ -143,20 +143,20 @@ class TemporaryFileFilterTest extends AbstractServer { $this->assertEquals('', $this->response->body); $this->assertEquals(201, $this->response->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Temp' => ['true'], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); $request = new HTTP\Request('DELETE', '/._testput.txt'); $this->server->httpRequest = $request; $this->server->exec(); - $this->assertEquals(204, $this->response->status, "Incorrect status code received. Full body:\n". $this->response->body); - $this->assertEquals(array( + $this->assertEquals(204, $this->response->status, "Incorrect status code received. Full body:\n" . $this->response->body); + $this->assertEquals([ 'X-Sabre-Temp' => ['true'], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); - $this->assertEquals('',$this->response->body); + $this->assertEquals('', $this->response->body); } @@ -169,30 +169,30 @@ class TemporaryFileFilterTest extends AbstractServer { $this->assertEquals('', $this->response->body); $this->assertEquals(201, $this->response->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Temp' => ['true'], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); $request = new HTTP\Request('PROPFIND', '/._testput.txt'); $this->server->httpRequest = ($request); $this->server->exec(); - $this->assertEquals(207, $this->response->status,'Incorrect status code returned. Body: ' . $this->response->body); - $this->assertEquals(array( + $this->assertEquals(207, $this->response->status, 'Incorrect status code returned. Body: ' . $this->response->body); + $this->assertEquals([ 'X-Sabre-Temp' => ['true'], 'Content-Type' => ['application/xml; charset=utf-8'], - ),$this->response->getHeaders()); + ], $this->response->getHeaders()); - $body = preg_replace("/xmlns(:[A-Za-z0-9_])?=(\"|\')DAV:(\"|\')/","xmlns\\1=\"urn:DAV\"",$this->response->body); + $body = preg_replace("/xmlns(:[A-Za-z0-9_])?=(\"|\')DAV:(\"|\')/", "xmlns\\1=\"urn:DAV\"", $this->response->body); $xml = simplexml_load_string($body); - $xml->registerXPathNamespace('d','urn:DAV'); + $xml->registerXPathNamespace('d', 'urn:DAV'); list($data) = $xml->xpath('/d:multistatus/d:response/d:href'); - $this->assertEquals('/._testput.txt',(string)$data,'href element should have been /._testput.txt'); + $this->assertEquals('/._testput.txt', (string)$data, 'href element should have been /._testput.txt'); $data = $xml->xpath('/d:multistatus/d:response/d:propstat/d:prop/d:resourcetype'); - $this->assertEquals(1,count($data)); + $this->assertEquals(1, count($data)); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/TestPlugin.php b/vendor/sabre/dav/tests/Sabre/DAV/TestPlugin.php index bb5ea6acc..619ac03fd 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/TestPlugin.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/TestPlugin.php @@ -2,9 +2,8 @@ namespace Sabre\DAV; -use - Sabre\HTTP\RequestInterface, - Sabre\HTTP\ResponseInterface; +use Sabre\HTTP\RequestInterface; +use Sabre\HTTP\ResponseInterface; class TestPlugin extends ServerPlugin { @@ -24,7 +23,7 @@ class TestPlugin extends ServerPlugin { function initialize(Server $server) { - $server->on('beforeMethod', [$this,'beforeMethod']); + $server->on('beforeMethod', [$this, 'beforeMethod']); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php b/vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php index 9516c2390..ad33200c8 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php @@ -16,18 +16,18 @@ class TreeTest extends \PHPUnit_Framework_TestCase { function testCopy() { $tree = new TreeMock(); - $tree->copy('hi','hi2'); + $tree->copy('hi', 'hi2'); $this->assertArrayHasKey('hi2', $tree->getNodeForPath('')->newDirectories); $this->assertEquals('foobar', $tree->getNodeForPath('hi/file')->get()); - $this->assertEquals(array('test1'=>'value'), $tree->getNodeForPath('hi/file')->getProperties(array())); + $this->assertEquals(['test1' => 'value'], $tree->getNodeForPath('hi/file')->getProperties([])); } function testMove() { $tree = new TreeMock(); - $tree->move('hi','hi2'); + $tree->move('hi', 'hi2'); $this->assertEquals('hi2', $tree->getNodeForPath('hi')->getName()); $this->assertTrue($tree->getNodeForPath('hi')->isRenamed); @@ -37,7 +37,7 @@ class TreeTest extends \PHPUnit_Framework_TestCase { function testDeepMove() { $tree = new TreeMock(); - $tree->move('hi/sub','hi2'); + $tree->move('hi/sub', 'hi2'); $this->assertArrayHasKey('hi2', $tree->getNodeForPath('')->newDirectories); $this->assertTrue($tree->getNodeForPath('hi/sub')->isDeleted); @@ -56,7 +56,7 @@ class TreeTest extends \PHPUnit_Framework_TestCase { $tree = new TreeMock(); $children = $tree->getChildren(''); - $this->assertEquals(2,count($children)); + $this->assertEquals(2, count($children)); $this->assertEquals('hi', $children[0]->getName()); } @@ -85,12 +85,12 @@ class TreeTest extends \PHPUnit_Framework_TestCase { class TreeMock extends Tree { - private $nodes = array(); + private $nodes = []; function __construct() { $file = new TreeFileTester('file'); - $file->properties = ['test1'=>'value']; + $file->properties = ['test1' => 'value']; $file->data = 'foobar'; parent::__construct( @@ -113,8 +113,8 @@ class TreeMock extends Tree { class TreeDirectoryTester extends SimpleCollection { - public $newDirectories = array(); - public $newFiles = array(); + public $newDirectories = []; + public $newFiles = []; public $isDeleted = false; public $isRenamed = false; @@ -124,7 +124,7 @@ class TreeDirectoryTester extends SimpleCollection { } - function createFile($name,$data = null) { + function createFile($name, $data = null) { $this->newFiles[$name] = $data; @@ -132,7 +132,7 @@ class TreeDirectoryTester extends SimpleCollection { function getChild($name) { - if (isset($this->newDirectories[$name])) return new TreeDirectoryTester($name); + if (isset($this->newDirectories[$name])) return new self($name); if (isset($this->newFiles[$name])) return new TreeFileTester($name, $this->newFiles[$name]); return parent::getChild($name); @@ -225,7 +225,7 @@ class TreeMultiGetTester extends TreeDirectoryTester implements IMultiGet { function getMultipleChildren(array $paths) { $result = []; - foreach($paths as $path) { + foreach ($paths as $path) { try { $child = $this->getChild($path); $result[] = $child; diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/ACLMethodTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/ACLMethodTest.php index 4ecd42717..7d7a54d06 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/ACLMethodTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/ACLMethodTest.php @@ -14,6 +14,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { $acl = new Plugin(); $server = new DAV\Server(); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpAcl($server->httpRequest, $server->httpResponse); @@ -21,15 +22,14 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { } /** - - /** + /** * @expectedException Sabre\DAV\Exception\MethodNotAllowed */ function testNotSupportedByNode() { - $tree = array( + $tree = [ new DAV\SimpleCollection('test'), - ); + ]; $acl = new Plugin(); $server = new DAV\Server($tree); $server->httpRequest = new HTTP\Request(); @@ -37,6 +37,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { <d:acl xmlns:d="DAV:"> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpACL($server->httpRequest, $server->httpResponse); @@ -45,9 +46,9 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { function testSuccessSimple() { - $tree = array( - new MockACLNode('test',array()), - ); + $tree = [ + new MockACLNode('test', []), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); $server->httpRequest = new HTTP\Request(); @@ -57,6 +58,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { <d:acl xmlns:d="DAV:"> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $this->assertFalse($acl->httpACL($server->httpRequest, $server->httpResponse)); @@ -68,12 +70,12 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { */ function testUnrecognizedPrincipal() { - $tree = array( - new MockACLNode('test',array()), - ); + $tree = [ + new MockACLNode('test', []), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); - $server->httpRequest = new HTTP\Request('ACL','/test'); + $server->httpRequest = new HTTP\Request('ACL', '/test'); $body = '<?xml version="1.0"?> <d:acl xmlns:d="DAV:"> <d:ace> @@ -82,6 +84,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { </d:ace> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpACL($server->httpRequest, $server->httpResponse); @@ -93,15 +96,15 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { */ function testUnrecognizedPrincipal2() { - $tree = array( - new MockACLNode('test',array()), - new DAV\SimpleCollection('principals',array( + $tree = [ + new MockACLNode('test', []), + new DAV\SimpleCollection('principals', [ new DAV\SimpleCollection('notaprincipal'), - )), - ); + ]), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); - $server->httpRequest = new HTTP\Request('ACL','/test'); + $server->httpRequest = new HTTP\Request('ACL', '/test'); $body = '<?xml version="1.0"?> <d:acl xmlns:d="DAV:"> <d:ace> @@ -110,6 +113,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { </d:ace> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpACL($server->httpRequest, $server->httpResponse); @@ -121,12 +125,12 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { */ function testUnknownPrivilege() { - $tree = array( - new MockACLNode('test',array()), - ); + $tree = [ + new MockACLNode('test', []), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); - $server->httpRequest = new HTTP\Request('ACL','/test'); + $server->httpRequest = new HTTP\Request('ACL', '/test'); $body = '<?xml version="1.0"?> <d:acl xmlns:d="DAV:"> <d:ace> @@ -135,6 +139,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { </d:ace> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpACL($server->httpRequest, $server->httpResponse); @@ -146,20 +151,24 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { */ function testAbstractPrivilege() { - $tree = array( - new MockACLNode('test',array()), - ); + $tree = [ + new MockACLNode('test', []), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); - $server->httpRequest = new HTTP\Request('ACL','/test'); + $server->on('getSupportedPrivilegeSet', function($node, &$supportedPrivilegeSet) { + $supportedPrivilegeSet['{DAV:}foo'] = ['abstract' => true]; + }); + $server->httpRequest = new HTTP\Request('ACL', '/test'); $body = '<?xml version="1.0"?> <d:acl xmlns:d="DAV:"> <d:ace> - <d:grant><d:privilege><d:all /></d:privilege></d:grant> - <d:principal><d:href>/principals/notfound</d:href></d:principal> + <d:grant><d:privilege><d:foo /></d:privilege></d:grant> + <d:principal><d:href>/principals/foo/</d:href></d:principal> </d:ace> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpACL($server->httpRequest, $server->httpResponse); @@ -171,20 +180,20 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { */ function testUpdateProtectedPrivilege() { - $oldACL = array( - array( + $oldACL = [ + [ 'principal' => 'principals/notfound', 'privilege' => '{DAV:}write', 'protected' => true, - ), - ); + ], + ]; - $tree = array( - new MockACLNode('test',$oldACL), - ); + $tree = [ + new MockACLNode('test', $oldACL), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); - $server->httpRequest = new HTTP\Request('ACL','/test'); + $server->httpRequest = new HTTP\Request('ACL', '/test'); $body = '<?xml version="1.0"?> <d:acl xmlns:d="DAV:"> <d:ace> @@ -193,6 +202,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { </d:ace> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpACL($server->httpRequest, $server->httpResponse); @@ -204,20 +214,20 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { */ function testUpdateProtectedPrivilege2() { - $oldACL = array( - array( + $oldACL = [ + [ 'principal' => 'principals/notfound', 'privilege' => '{DAV:}write', 'protected' => true, - ), - ); + ], + ]; - $tree = array( - new MockACLNode('test',$oldACL), - ); + $tree = [ + new MockACLNode('test', $oldACL), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); - $server->httpRequest = new HTTP\Request('ACL','/test'); + $server->httpRequest = new HTTP\Request('ACL', '/test'); $body = '<?xml version="1.0"?> <d:acl xmlns:d="DAV:"> <d:ace> @@ -226,6 +236,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { </d:ace> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpACL($server->httpRequest, $server->httpResponse); @@ -237,20 +248,20 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { */ function testUpdateProtectedPrivilege3() { - $oldACL = array( - array( + $oldACL = [ + [ 'principal' => 'principals/notfound', 'privilege' => '{DAV:}write', 'protected' => true, - ), - ); + ], + ]; - $tree = array( - new MockACLNode('test',$oldACL), - ); + $tree = [ + new MockACLNode('test', $oldACL), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); - $server->httpRequest = new HTTP\Request('ACL','/test'); + $server->httpRequest = new HTTP\Request('ACL', '/test'); $body = '<?xml version="1.0"?> <d:acl xmlns:d="DAV:"> <d:ace> @@ -259,6 +270,7 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { </d:ace> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $acl->httpACL($server->httpRequest, $server->httpResponse); @@ -267,28 +279,28 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { function testSuccessComplex() { - $oldACL = array( - array( + $oldACL = [ + [ 'principal' => 'principals/foo', 'privilege' => '{DAV:}write', 'protected' => true, - ), - array( + ], + [ 'principal' => 'principals/bar', 'privilege' => '{DAV:}read', - ), - ); - - $tree = array( - $node = new MockACLNode('test',$oldACL), - new DAV\SimpleCollection('principals', array( - new MockPrincipal('foo','principals/foo'), - new MockPrincipal('baz','principals/baz'), - )), - ); + ], + ]; + + $tree = [ + $node = new MockACLNode('test', $oldACL), + new DAV\SimpleCollection('principals', [ + new MockPrincipal('foo', 'principals/foo'), + new MockPrincipal('baz', 'principals/baz'), + ]), + ]; $acl = new Plugin(); $server = new DAV\Server($tree); - $server->httpRequest = new HTTP\Request('ACL','/test'); + $server->httpRequest = new HTTP\Request('ACL', '/test'); $body = '<?xml version="1.0"?> <d:acl xmlns:d="DAV:"> <d:ace> @@ -302,23 +314,24 @@ class ACLMethodTest extends \PHPUnit_Framework_TestCase { </d:ace> </d:acl>'; $server->httpRequest->setBody($body); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin($acl); $this->assertFalse($acl->httpAcl($server->httpRequest, $server->httpResponse)); - $this->assertEquals(array( - array( + $this->assertEquals([ + [ 'principal' => 'principals/foo', 'privilege' => '{DAV:}write', 'protected' => true, - ), - array( + ], + [ 'principal' => 'principals/baz', 'privilege' => '{DAV:}write', 'protected' => false, - ), - ), $node->getACL()); + ], + ], $node->getACL()); } } diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/AllowAccessTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/AllowAccessTest.php index 14a80003a..f16693625 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/AllowAccessTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/AllowAccessTest.php @@ -3,7 +3,6 @@ namespace Sabre\DAVACL; use Sabre\DAV; -use Sabre\HTTP; class AllowAccessTest extends \PHPUnit_Framework_TestCase { @@ -14,13 +13,24 @@ class AllowAccessTest extends \PHPUnit_Framework_TestCase { function setUp() { - $nodes = array( - new DAV\SimpleCollection('testdir'), - ); + $nodes = [ + new DAV\Mock\Collection('testdir', [ + 'file1.txt' => 'contents', + ]), + ]; $this->server = new DAV\Server($nodes); + $this->server->addPlugin( + new DAV\Auth\Plugin( + new DAV\Auth\Backend\Mock() + ) + ); + // Login + $this->server->getPlugin('auth')->beforeMethod( + new \Sabre\HTTP\Request(), + new \Sabre\HTTP\Response() + ); $aclPlugin = new Plugin(); - $aclPlugin->allowAccessToNodesWithoutACL = true; $this->server->addPlugin($aclPlugin); } @@ -64,16 +74,7 @@ class AllowAccessTest extends \PHPUnit_Framework_TestCase { function testPUT() { $this->server->httpRequest->setMethod('PUT'); - $this->server->httpRequest->setUrl('/testdir'); - - $this->assertTrue($this->server->emit('beforeMethod', [$this->server->httpRequest, $this->server->httpResponse])); - - } - - function testACL() { - - $this->server->httpRequest->setMethod('ACL'); - $this->server->httpRequest->setUrl('/testdir'); + $this->server->httpRequest->setUrl('/testdir/file1.txt'); $this->assertTrue($this->server->emit('beforeMethod', [$this->server->httpRequest, $this->server->httpResponse])); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/BlockAccessTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/BlockAccessTest.php index be3e9dae9..ceae9aed0 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/BlockAccessTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/BlockAccessTest.php @@ -3,7 +3,6 @@ namespace Sabre\DAVACL; use Sabre\DAV; -use Sabre\HTTP; class BlockAccessTest extends \PHPUnit_Framework_TestCase { @@ -21,7 +20,17 @@ class BlockAccessTest extends \PHPUnit_Framework_TestCase { $this->server = new DAV\Server($nodes); $this->plugin = new Plugin(); - $this->plugin->allowAccessToNodesWithoutACL = false; + $this->plugin->setDefaultAcl([]); + $this->server->addPlugin( + new DAV\Auth\Plugin( + new DAV\Auth\Backend\Mock() + ) + ); + // Login + $this->server->getPlugin('auth')->beforeMethod( + new \Sabre\HTTP\Request(), + new \Sabre\HTTP\Response() + ); $this->server->addPlugin($this->plugin); } @@ -178,10 +187,10 @@ class BlockAccessTest extends \PHPUnit_Framework_TestCase { 200 => [], 404 => [], 403 => [ - '{DAV:}displayname' => null, + '{DAV:}displayname' => null, '{DAV:}getcontentlength' => null, - '{DAV:}bar' => null, - '{DAV:}owner' => null, + '{DAV:}bar' => null, + '{DAV:}owner' => null, ], ]; diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/AceConflictTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/AceConflictTest.php index fc48af67f..1cdf2949f 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/AceConflictTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/AceConflictTest.php @@ -11,24 +11,24 @@ class AceConflictTest extends \PHPUnit_Framework_TestCase { $ex = new AceConflict('message'); $server = new DAV\Server(); - $dom = new \DOMDocument('1.0','utf-8'); - $root = $dom->createElementNS('DAV:','d:root'); + $dom = new \DOMDocument('1.0', 'utf-8'); + $root = $dom->createElementNS('DAV:', 'd:root'); $dom->appendChild($root); $ex->serialize($server, $root); - $xpaths = array( - '/d:root' => 1, + $xpaths = [ + '/d:root' => 1, '/d:root/d:no-ace-conflict' => 1, - ); + ]; // Reloading because PHP DOM sucks $dom2 = new \DOMDocument('1.0', 'utf-8'); $dom2->loadXML($dom->saveXML()); $dxpath = new \DOMXPath($dom2); - $dxpath->registerNamespace('d','DAV:'); - foreach($xpaths as $xpath=>$count) { + $dxpath->registerNamespace('d', 'DAV:'); + foreach ($xpaths as $xpath => $count) { $this->assertEquals($count, $dxpath->query($xpath)->length, 'Looking for : ' . $xpath . ', we could only find ' . $dxpath->query($xpath)->length . ' elements, while we expected ' . $count); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NeedPrivilegesExceptionTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NeedPrivilegesExceptionTest.php index 7e66adab6..b13e7722d 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NeedPrivilegesExceptionTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NeedPrivilegesExceptionTest.php @@ -4,41 +4,41 @@ namespace Sabre\DAVACL\Exception; use Sabre\DAV; -class NeedPrivilegesTest extends \PHPUnit_Framework_TestCase { +class NeedPrivilegesExceptionTest extends \PHPUnit_Framework_TestCase { function testSerialize() { $uri = 'foo'; - $privileges = array( + $privileges = [ '{DAV:}read', '{DAV:}write', - ); + ]; $ex = new NeedPrivileges($uri, $privileges); $server = new DAV\Server(); - $dom = new \DOMDocument('1.0','utf-8'); - $root = $dom->createElementNS('DAV:','d:root'); + $dom = new \DOMDocument('1.0', 'utf-8'); + $root = $dom->createElementNS('DAV:', 'd:root'); $dom->appendChild($root); $ex->serialize($server, $root); - $xpaths = array( - '/d:root' => 1, - '/d:root/d:need-privileges' => 1, - '/d:root/d:need-privileges/d:resource' => 2, - '/d:root/d:need-privileges/d:resource/d:href' => 2, - '/d:root/d:need-privileges/d:resource/d:privilege' => 2, - '/d:root/d:need-privileges/d:resource/d:privilege/d:read' => 1, + $xpaths = [ + '/d:root' => 1, + '/d:root/d:need-privileges' => 1, + '/d:root/d:need-privileges/d:resource' => 2, + '/d:root/d:need-privileges/d:resource/d:href' => 2, + '/d:root/d:need-privileges/d:resource/d:privilege' => 2, + '/d:root/d:need-privileges/d:resource/d:privilege/d:read' => 1, '/d:root/d:need-privileges/d:resource/d:privilege/d:write' => 1, - ); + ]; // Reloading because PHP DOM sucks $dom2 = new \DOMDocument('1.0', 'utf-8'); $dom2->loadXML($dom->saveXML()); $dxpath = new \DOMXPath($dom2); - $dxpath->registerNamespace('d','DAV:'); - foreach($xpaths as $xpath=>$count) { + $dxpath->registerNamespace('d', 'DAV:'); + foreach ($xpaths as $xpath => $count) { $this->assertEquals($count, $dxpath->query($xpath)->length, 'Looking for : ' . $xpath . ', we could only find ' . $dxpath->query($xpath)->length . ' elements, while we expected ' . $count); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NoAbstractTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NoAbstractTest.php index 2406c1c38..f52b17371 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NoAbstractTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NoAbstractTest.php @@ -11,24 +11,24 @@ class NoAbstractTest extends \PHPUnit_Framework_TestCase { $ex = new NoAbstract('message'); $server = new DAV\Server(); - $dom = new \DOMDocument('1.0','utf-8'); - $root = $dom->createElementNS('DAV:','d:root'); + $dom = new \DOMDocument('1.0', 'utf-8'); + $root = $dom->createElementNS('DAV:', 'd:root'); $dom->appendChild($root); $ex->serialize($server, $root); - $xpaths = array( - '/d:root' => 1, + $xpaths = [ + '/d:root' => 1, '/d:root/d:no-abstract' => 1, - ); + ]; // Reloading because PHP DOM sucks $dom2 = new \DOMDocument('1.0', 'utf-8'); $dom2->loadXML($dom->saveXML()); $dxpath = new \DOMXPath($dom2); - $dxpath->registerNamespace('d','DAV:'); - foreach($xpaths as $xpath=>$count) { + $dxpath->registerNamespace('d', 'DAV:'); + foreach ($xpaths as $xpath => $count) { $this->assertEquals($count, $dxpath->query($xpath)->length, 'Looking for : ' . $xpath . ', we could only find ' . $dxpath->query($xpath)->length . ' elements, while we expected ' . $count); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NotRecognizedPrincipalTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NotRecognizedPrincipalTest.php index 6077b0ba5..df89aaf84 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NotRecognizedPrincipalTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NotRecognizedPrincipalTest.php @@ -11,24 +11,24 @@ class NotRecognizedPrincipalTest extends \PHPUnit_Framework_TestCase { $ex = new NotRecognizedPrincipal('message'); $server = new DAV\Server(); - $dom = new \DOMDocument('1.0','utf-8'); - $root = $dom->createElementNS('DAV:','d:root'); + $dom = new \DOMDocument('1.0', 'utf-8'); + $root = $dom->createElementNS('DAV:', 'd:root'); $dom->appendChild($root); $ex->serialize($server, $root); - $xpaths = array( - '/d:root' => 1, + $xpaths = [ + '/d:root' => 1, '/d:root/d:recognized-principal' => 1, - ); + ]; // Reloading because PHP DOM sucks $dom2 = new \DOMDocument('1.0', 'utf-8'); $dom2->loadXML($dom->saveXML()); $dxpath = new \DOMXPath($dom2); - $dxpath->registerNamespace('d','DAV:'); - foreach($xpaths as $xpath=>$count) { + $dxpath->registerNamespace('d', 'DAV:'); + foreach ($xpaths as $xpath => $count) { $this->assertEquals($count, $dxpath->query($xpath)->length, 'Looking for : ' . $xpath . ', we could only find ' . $dxpath->query($xpath)->length . ' elements, while we expected ' . $count); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NotSupportedPrivilegeTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NotSupportedPrivilegeTest.php index 8e7b3685d..50623952b 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NotSupportedPrivilegeTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/Exception/NotSupportedPrivilegeTest.php @@ -11,24 +11,24 @@ class NotSupportedPrivilegeTest extends \PHPUnit_Framework_TestCase { $ex = new NotSupportedPrivilege('message'); $server = new DAV\Server(); - $dom = new \DOMDocument('1.0','utf-8'); - $root = $dom->createElementNS('DAV:','d:root'); + $dom = new \DOMDocument('1.0', 'utf-8'); + $root = $dom->createElementNS('DAV:', 'd:root'); $dom->appendChild($root); $ex->serialize($server, $root); - $xpaths = array( - '/d:root' => 1, + $xpaths = [ + '/d:root' => 1, '/d:root/d:not-supported-privilege' => 1, - ); + ]; // Reloading because PHP DOM sucks $dom2 = new \DOMDocument('1.0', 'utf-8'); $dom2->loadXML($dom->saveXML()); $dxpath = new \DOMXPath($dom2); - $dxpath->registerNamespace('d','DAV:'); - foreach($xpaths as $xpath=>$count) { + $dxpath->registerNamespace('d', 'DAV:'); + foreach ($xpaths as $xpath => $count) { $this->assertEquals($count, $dxpath->query($xpath)->length, 'Looking for : ' . $xpath . ', we could only find ' . $dxpath->query($xpath)->length . ' elements, while we expected ' . $count); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/ExpandPropertiesTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/ExpandPropertiesTest.php index 5e99f2e73..0612b5474 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/ExpandPropertiesTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/ExpandPropertiesTest.php @@ -11,31 +11,31 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { function getServer() { - $tree = array( - new DAV\Mock\PropertiesCollection('node1', [], array( + $tree = [ + new DAV\Mock\PropertiesCollection('node1', [], [ '{http://sabredav.org/ns}simple' => 'foo', '{http://sabredav.org/ns}href' => new DAV\Xml\Property\Href('node2'), - '{DAV:}displayname' => 'Node 1', - )), - new DAV\Mock\PropertiesCollection('node2', [], array( + '{DAV:}displayname' => 'Node 1', + ]), + new DAV\Mock\PropertiesCollection('node2', [], [ + '{http://sabredav.org/ns}simple' => 'simple', + '{http://sabredav.org/ns}hreflist' => new DAV\Xml\Property\Href(['node1', 'node3']), + '{DAV:}displayname' => 'Node 2', + ]), + new DAV\Mock\PropertiesCollection('node3', [], [ '{http://sabredav.org/ns}simple' => 'simple', - '{http://sabredav.org/ns}hreflist' => new DAV\Xml\Property\Href(['node1','node3']), - '{DAV:}displayname' => 'Node 2', - )), - new DAV\Mock\PropertiesCollection('node3', [], array( - '{http://sabredav.org/ns}simple' => 'simple', - '{DAV:}displayname' => 'Node 3', - )), - ); + '{DAV:}displayname' => 'Node 3', + ]), + ]; $fakeServer = new DAV\Server($tree); $fakeServer->sapi = new HTTP\SapiMock(); $fakeServer->debugExceptions = true; $fakeServer->httpResponse = new HTTP\ResponseMock(); $plugin = new Plugin(); - $plugin->allowAccessToNodesWithoutACL = true; - + $plugin->allowUnauthenticatedAccess = false; $this->assertTrue($plugin instanceof Plugin); + $fakeServer->addPlugin($plugin); $this->assertEquals($plugin, $fakeServer->getPlugin('acl')); @@ -53,11 +53,11 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { <d:property name="href" namespace="http://sabredav.org/ns" /> </d:expand-property>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/node1', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -67,38 +67,38 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { $server->exec(); - $this->assertEquals(207, $server->httpResponse->status,'Incorrect status code received. Full body: ' . $server->httpResponse->body); - $this->assertEquals(array( + $this->assertEquals(207, $server->httpResponse->status, 'Incorrect status code received. Full body: ' . $server->httpResponse->body); + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:multistatus', - '/d:multistatus/d:response' => 1, - '/d:multistatus/d:response/d:href' => 1, - '/d:multistatus/d:response/d:propstat' => 2, - '/d:multistatus/d:response/d:propstat/d:prop' => 2, + '/d:multistatus/d:response' => 1, + '/d:multistatus/d:response/d:href' => 1, + '/d:multistatus/d:response/d:propstat' => 2, + '/d:multistatus/d:response/d:propstat/d:prop' => 2, '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:simple' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:href' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:simple' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:href' => 1, '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:href' => 1, - ); + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - $xml->registerXPathNamespace('s','http://sabredav.org/ns'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + $xml->registerXPathNamespace('s', 'http://sabredav.org/ns'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response: ' . $server->httpResponse->body); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response: ' . $server->httpResponse->body); } @@ -116,11 +116,11 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { </d:property> </d:expand-property>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/node1', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -131,39 +131,39 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(207, $server->httpResponse->status, 'Incorrect response status received. Full response body: ' . $server->httpResponse->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:multistatus', - '/d:multistatus/d:response' => 1, - '/d:multistatus/d:response/d:href' => 1, - '/d:multistatus/d:response/d:propstat' => 1, - '/d:multistatus/d:response/d:propstat/d:prop' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:href' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response/d:href' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response/d:propstat' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response/d:propstat/d:prop' => 1, + '/d:multistatus/d:response' => 1, + '/d:multistatus/d:response/d:href' => 1, + '/d:multistatus/d:response/d:propstat' => 1, + '/d:multistatus/d:response/d:propstat/d:prop' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:href' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response/d:href' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response/d:propstat' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response/d:propstat/d:prop' => 1, '/d:multistatus/d:response/d:propstat/d:prop/s:href/d:response/d:propstat/d:prop/d:displayname' => 1, - ); + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - $xml->registerXPathNamespace('s','http://sabredav.org/ns'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + $xml->registerXPathNamespace('s', 'http://sabredav.org/ns'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . ' Full response body: ' . $server->httpResponse->getBodyAsString()); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . ' Full response body: ' . $server->httpResponse->getBodyAsString()); } @@ -181,11 +181,11 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { </d:property> </d:expand-property>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/node2', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -196,39 +196,39 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(207, $server->httpResponse->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:multistatus', - '/d:multistatus/d:response' => 1, - '/d:multistatus/d:response/d:href' => 1, - '/d:multistatus/d:response/d:propstat' => 1, - '/d:multistatus/d:response/d:propstat/d:prop' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response' => 2, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:href' => 2, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat' => 2, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop' => 2, + '/d:multistatus/d:response' => 1, + '/d:multistatus/d:response/d:href' => 1, + '/d:multistatus/d:response/d:propstat' => 1, + '/d:multistatus/d:response/d:propstat/d:prop' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response' => 2, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:href' => 2, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat' => 2, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop' => 2, '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/d:displayname' => 2, - ); + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - $xml->registerXPathNamespace('s','http://sabredav.org/ns'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + $xml->registerXPathNamespace('s', 'http://sabredav.org/ns'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result)); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result)); } @@ -249,11 +249,11 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { </d:property> </d:expand-property>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/node2', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -264,45 +264,45 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(207, $server->httpResponse->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:multistatus', - '/d:multistatus/d:response' => 1, - '/d:multistatus/d:response/d:href' => 1, - '/d:multistatus/d:response/d:propstat' => 1, - '/d:multistatus/d:response/d:propstat/d:prop' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response' => 2, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:href' => 2, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat' => 3, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop' => 3, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/d:displayname' => 2, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href' => 2, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response/d:href' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response/d:propstat' => 1, - '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response/d:propstat/d:prop' => 1, + '/d:multistatus/d:response' => 1, + '/d:multistatus/d:response/d:href' => 1, + '/d:multistatus/d:response/d:propstat' => 1, + '/d:multistatus/d:response/d:propstat/d:prop' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response' => 2, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:href' => 2, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat' => 3, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop' => 3, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/d:displayname' => 2, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href' => 2, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response/d:href' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response/d:propstat' => 1, + '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response/d:propstat/d:prop' => 1, '/d:multistatus/d:response/d:propstat/d:prop/s:hreflist/d:response/d:propstat/d:prop/s:href/d:response/d:propstat/d:prop/d:displayname' => 1, - ); + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - $xml->registerXPathNamespace('s','http://sabredav.org/ns'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + $xml->registerXPathNamespace('s', 'http://sabredav.org/ns'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result)); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result)); } diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/MockACLNode.php b/vendor/sabre/dav/tests/Sabre/DAVACL/MockACLNode.php index 7b3e8fc12..2d9744e29 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/MockACLNode.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/MockACLNode.php @@ -3,14 +3,13 @@ namespace Sabre\DAVACL; use Sabre\DAV; -use Sabre\HTTP; class MockACLNode extends DAV\Node implements IACL { public $name; public $acl; - function __construct($name, array $acl = array()) { + function __construct($name, array $acl = []) { $this->name = $name; $this->acl = $acl; diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/MockPrincipal.php b/vendor/sabre/dav/tests/Sabre/DAVACL/MockPrincipal.php index dd8542b8d..934906802 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/MockPrincipal.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/MockPrincipal.php @@ -3,16 +3,15 @@ namespace Sabre\DAVACL; use Sabre\DAV; -use Sabre\HTTP; class MockPrincipal extends DAV\Node implements IPrincipal { public $name; public $principalUrl; - public $groupMembership = array(); - public $groupMemberSet = array(); + public $groupMembership = []; + public $groupMemberSet = []; - function __construct($name,$principalUrl,array $groupMembership = array(), array $groupMemberSet = array()) { + function __construct($name, $principalUrl, array $groupMembership = [], array $groupMemberSet = []) { $this->name = $name; $this->principalUrl = $principalUrl; @@ -35,7 +34,7 @@ class MockPrincipal extends DAV\Node implements IPrincipal { function getAlternateUriSet() { - return array(); + return []; } @@ -63,4 +62,3 @@ class MockPrincipal extends DAV\Node implements IPrincipal { } } - diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PluginAdminTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PluginAdminTest.php index fb7516a78..8552448f5 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PluginAdminTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PluginAdminTest.php @@ -5,7 +5,6 @@ namespace Sabre\DAVACL; use Sabre\DAV; use Sabre\HTTP; - require_once 'Sabre/DAVACL/MockACLNode.php'; require_once 'Sabre/HTTP/ResponseMock.php'; @@ -17,10 +16,10 @@ class PluginAdminTest extends \PHPUnit_Framework_TestCase { $principalBackend = new PrincipalBackend\Mock(); - $tree = array( - new MockACLNode('adminonly', array()), + $tree = [ + new MockACLNode('adminonly', []), new PrincipalCollection($principalBackend), - ); + ]; $this->server = new DAV\Server($tree); $this->server->sapi = new HTTP\SapiMock(); @@ -33,11 +32,11 @@ class PluginAdminTest extends \PHPUnit_Framework_TestCase { $plugin = new Plugin(); $this->server->addPlugin($plugin); - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'OPTIONS', - 'HTTP_DEPTH' => 1, - 'REQUEST_URI' => '/adminonly', - )); + 'HTTP_DEPTH' => 1, + 'REQUEST_URI' => '/adminonly', + ]); $response = new HTTP\ResponseMock(); @@ -56,16 +55,16 @@ class PluginAdminTest extends \PHPUnit_Framework_TestCase { function testAdminAccess() { $plugin = new Plugin(); - $plugin->adminPrincipals = array( + $plugin->adminPrincipals = [ 'principals/admin', - ); + ]; $this->server->addPlugin($plugin); - $request = HTTP\Sapi::createFromServerArray(array( + $request = HTTP\Sapi::createFromServerArray([ 'REQUEST_METHOD' => 'OPTIONS', - 'HTTP_DEPTH' => 1, - 'REQUEST_URI' => '/adminonly', - )); + 'HTTP_DEPTH' => 1, + 'REQUEST_URI' => '/adminonly', + ]); $response = new HTTP\ResponseMock(); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PluginPropertiesTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PluginPropertiesTest.php index e5b7e1a3f..5762ac902 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PluginPropertiesTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PluginPropertiesTest.php @@ -10,6 +10,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { function testPrincipalCollectionSet() { $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $plugin->principalCollectionSet = [ 'principals1', 'principals2', @@ -25,8 +26,8 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $result = $server->getPropertiesForPath('', $requestedProperties); $result = $result[0]; - $this->assertEquals(1,count($result[200])); - $this->assertArrayHasKey('{DAV:}principal-collection-set',$result[200]); + $this->assertEquals(1, count($result[200])); + $this->assertArrayHasKey('{DAV:}principal-collection-set', $result[200]); $this->assertInstanceOf('Sabre\\DAV\\Xml\\Property\\Href', $result[200]['{DAV:}principal-collection-set']); $expected = [ @@ -56,8 +57,8 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $result = $fakeServer->getPropertiesForPath('', $requestedProperties); $result = $result[0]; - $this->assertEquals(1,count($result[200])); - $this->assertArrayHasKey('{DAV:}current-user-principal',$result[200]); + $this->assertEquals(1, count($result[200])); + $this->assertArrayHasKey('{DAV:}current-user-principal', $result[200]); $this->assertInstanceOf('Sabre\DAVACL\Xml\Property\Principal', $result[200]['{DAV:}current-user-principal']); $this->assertEquals(Xml\Property\Principal::UNAUTHENTICATED, $result[200]['{DAV:}current-user-principal']->getType()); @@ -67,8 +68,8 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $result = $fakeServer->getPropertiesForPath('', $requestedProperties); $result = $result[0]; - $this->assertEquals(1,count($result[200])); - $this->assertArrayHasKey('{DAV:}current-user-principal',$result[200]); + $this->assertEquals(1, count($result[200])); + $this->assertArrayHasKey('{DAV:}current-user-principal', $result[200]); $this->assertInstanceOf('Sabre\DAVACL\Xml\Property\Principal', $result[200]['{DAV:}current-user-principal']); $this->assertEquals(Xml\Property\Principal::HREF, $result[200]['{DAV:}current-user-principal']->getType()); $this->assertEquals('principals/admin/', $result[200]['{DAV:}current-user-principal']->getHref()); @@ -78,6 +79,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { function testSupportedPrivilegeSet() { $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $server = new DAV\Server(); $server->addPlugin($plugin); @@ -88,8 +90,8 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $result = $server->getPropertiesForPath('', $requestedProperties); $result = $result[0]; - $this->assertEquals(1,count($result[200])); - $this->assertArrayHasKey('{DAV:}supported-privilege-set',$result[200]); + $this->assertEquals(1, count($result[200])); + $this->assertArrayHasKey('{DAV:}supported-privilege-set', $result[200]); $this->assertInstanceOf('Sabre\\DAVACL\\Xml\\Property\\SupportedPrivilegeSet', $result[200]['{DAV:}supported-privilege-set']); $server = new DAV\Server(); @@ -98,26 +100,25 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $result = $server->xml->write('{DAV:}root', $prop); $xpaths = [ - '/d:root' => 1, - '/d:root/d:supported-privilege' => 1, - '/d:root/d:supported-privilege/d:privilege' => 1, - '/d:root/d:supported-privilege/d:privilege/d:all' => 1, - '/d:root/d:supported-privilege/d:abstract' => 1, - '/d:root/d:supported-privilege/d:supported-privilege' => 2, - '/d:root/d:supported-privilege/d:supported-privilege/d:privilege' => 2, - '/d:root/d:supported-privilege/d:supported-privilege/d:privilege/d:read' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:privilege/d:write' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege' => 8, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege' => 8, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:read-acl' => 1, + '/d:root' => 1, + '/d:root/d:supported-privilege' => 1, + '/d:root/d:supported-privilege/d:privilege' => 1, + '/d:root/d:supported-privilege/d:privilege/d:all' => 1, + '/d:root/d:supported-privilege/d:abstract' => 0, + '/d:root/d:supported-privilege/d:supported-privilege' => 2, + '/d:root/d:supported-privilege/d:supported-privilege/d:privilege' => 2, + '/d:root/d:supported-privilege/d:supported-privilege/d:privilege/d:read' => 1, + '/d:root/d:supported-privilege/d:supported-privilege/d:privilege/d:write' => 1, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege' => 7, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege' => 7, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:read-acl' => 1, '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:read-current-user-privilege-set' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:write-content' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:write-properties' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:write-acl' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:bind' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:unbind' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:unlock' => 1, - '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:abstract' => 0, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:write-content' => 1, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:write-properties' => 1, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:bind' => 1, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:unbind' => 1, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:privilege/d:unlock' => 1, + '/d:root/d:supported-privilege/d:supported-privilege/d:supported-privilege/d:abstract' => 0, ]; @@ -126,10 +127,10 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $dom2->loadXML($result); $dxpath = new \DOMXPath($dom2); - $dxpath->registerNamespace('d','DAV:'); - foreach($xpaths as $xpath=>$count) { + $dxpath->registerNamespace('d', 'DAV:'); + foreach ($xpaths as $xpath => $count) { - $this->assertEquals($count, $dxpath->query($xpath)->length, 'Looking for : ' . $xpath . ', we could only find ' . $dxpath->query($xpath)->length . ' elements, while we expected ' . $count. ' Full XML: ' . $result); + $this->assertEquals($count, $dxpath->query($xpath)->length, 'Looking for : ' . $xpath . ', we could only find ' . $dxpath->query($xpath)->length . ' elements, while we expected ' . $count . ' Full XML: ' . $result); } @@ -138,6 +139,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { function testACL() { $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $nodes = [ new MockACLNode('foo', [ @@ -147,7 +149,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { ] ]), new DAV\SimpleCollection('principals', [ - $principal = new MockPrincipal('admin','principals/admin'), + $principal = new MockPrincipal('admin', 'principals/admin'), ]), ]; @@ -167,8 +169,8 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $result = $server->getPropertiesForPath('foo', $requestedProperties); $result = $result[0]; - $this->assertEquals(1,count($result[200]),'The {DAV:}acl property did not return from the list. Full list: ' . print_r($result, true)); - $this->assertArrayHasKey('{DAV:}acl',$result[200]); + $this->assertEquals(1, count($result[200]), 'The {DAV:}acl property did not return from the list. Full list: ' . print_r($result, true)); + $this->assertArrayHasKey('{DAV:}acl', $result[200]); $this->assertInstanceOf('Sabre\\DAVACL\\Xml\Property\\Acl', $result[200]['{DAV:}acl']); } @@ -176,6 +178,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { function testACLRestrictions() { $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $nodes = [ new MockACLNode('foo', [ @@ -185,7 +188,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { ] ]), new DAV\SimpleCollection('principals', [ - $principal = new MockPrincipal('admin','principals/admin'), + $principal = new MockPrincipal('admin', 'principals/admin'), ]), ]; @@ -205,8 +208,8 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $result = $server->getPropertiesForPath('foo', $requestedProperties); $result = $result[0]; - $this->assertEquals(1,count($result[200]),'The {DAV:}acl-restrictions property did not return from the list. Full list: ' . print_r($result, true)); - $this->assertArrayHasKey('{DAV:}acl-restrictions',$result[200]); + $this->assertEquals(1, count($result[200]), 'The {DAV:}acl-restrictions property did not return from the list. Full list: ' . print_r($result, true)); + $this->assertArrayHasKey('{DAV:}acl-restrictions', $result[200]); $this->assertInstanceOf('Sabre\\DAVACL\\Xml\\Property\\AclRestrictions', $result[200]['{DAV:}acl-restrictions']); } @@ -215,7 +218,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $tree = [ new DAV\SimpleCollection('principals', [ - $principal = new MockPrincipal('user','principals/user'), + $principal = new MockPrincipal('user', 'principals/user'), ]) ]; @@ -223,6 +226,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { //$plugin = new DAV\Auth\Plugin(new DAV\Auth\MockBackend()) //$fakeServer->addPlugin($plugin); $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $fakeServer->addPlugin($plugin); $requestedProperties = [ @@ -243,7 +247,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $tree = [ new DAV\SimpleCollection('principals', [ - $principal = new MockPrincipal('user','principals/user'), + $principal = new MockPrincipal('user', 'principals/user'), ]), ]; @@ -251,6 +255,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { //$plugin = new DAV\Auth\Plugin(new DAV\Auth\MockBackend()); //$fakeServer->addPlugin($plugin); $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $fakeServer->addPlugin($plugin); $requestedProperties = [ @@ -272,7 +277,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $tree = [ new DAV\SimpleCollection('principals', [ - $principal = new MockPrincipal('user','principals/user'), + $principal = new MockPrincipal('user', 'principals/user'), ]), ]; @@ -280,6 +285,7 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { //$plugin = new DAV\Auth\Plugin(new DAV\Auth\MockBackend()); //$fakeServer->addPlugin($plugin); $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $fakeServer->addPlugin($plugin); $requestedProperties = [ @@ -301,12 +307,13 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $tree = [ new DAV\SimpleCollection('principals', [ - $principal = new MockPrincipal('user','principals/user'), + $principal = new MockPrincipal('user', 'principals/user'), ]), ]; $fakeServer = new DAV\Server($tree); $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $fakeServer->addPlugin($plugin); $requestedProperties = [ @@ -328,12 +335,13 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $tree = [ new DAV\SimpleCollection('principals', [ - $principal = new MockPrincipal('user','principals/user'), + $principal = new MockPrincipal('user', 'principals/user'), ]), ]; $fakeServer = new DAV\Server($tree); $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $fakeServer->addPlugin($plugin); $requestedProperties = [ diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PluginUpdatePropertiesTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PluginUpdatePropertiesTest.php index 64cedd142..0147e6a61 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PluginUpdatePropertiesTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PluginUpdatePropertiesTest.php @@ -3,28 +3,25 @@ namespace Sabre\DAVACL; use Sabre\DAV; -use Sabre\HTTP; - - -require_once 'Sabre/DAVACL/MockPrincipal.php'; class PluginUpdatePropertiesTest extends \PHPUnit_Framework_TestCase { function testUpdatePropertiesPassthrough() { - $tree = array( + $tree = [ new DAV\SimpleCollection('foo'), - ); + ]; $server = new DAV\Server($tree); + $server->addPlugin(new DAV\Auth\Plugin()); $server->addPlugin(new Plugin()); - $result = $server->updateProperties('foo', array( + $result = $server->updateProperties('foo', [ '{DAV:}foo' => 'bar', - )); + ]); - $expected = array( + $expected = [ '{DAV:}foo' => 403, - ); + ]; $this->assertEquals($expected, $result); @@ -32,35 +29,39 @@ class PluginUpdatePropertiesTest extends \PHPUnit_Framework_TestCase { function testRemoveGroupMembers() { - $tree = array( - new MockPrincipal('foo','foo'), - ); + $tree = [ + new MockPrincipal('foo', 'foo'), + ]; $server = new DAV\Server($tree); - $server->addPlugin(new Plugin()); + $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; + $server->addPlugin($plugin); - $result = $server->updateProperties('foo', array( + $result = $server->updateProperties('foo', [ '{DAV:}group-member-set' => null, - )); + ]); - $expected = array( + $expected = [ '{DAV:}group-member-set' => 204 - ); + ]; $this->assertEquals($expected, $result); - $this->assertEquals(array(),$tree[0]->getGroupMemberSet()); + $this->assertEquals([], $tree[0]->getGroupMemberSet()); } function testSetGroupMembers() { $tree = [ - new MockPrincipal('foo','foo'), + new MockPrincipal('foo', 'foo'), ]; $server = new DAV\Server($tree); - $server->addPlugin(new Plugin()); + $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; + $server->addPlugin($plugin); $result = $server->updateProperties('foo', [ - '{DAV:}group-member-set' => new DAV\Xml\Property\Href(['/bar','/baz'], true), + '{DAV:}group-member-set' => new DAV\Xml\Property\Href(['/bar', '/baz'], true), ]); $expected = [ @@ -68,7 +69,7 @@ class PluginUpdatePropertiesTest extends \PHPUnit_Framework_TestCase { ]; $this->assertEquals($expected, $result); - $this->assertEquals(['bar', 'baz'],$tree[0]->getGroupMemberSet()); + $this->assertEquals(['bar', 'baz'], $tree[0]->getGroupMemberSet()); } @@ -77,15 +78,17 @@ class PluginUpdatePropertiesTest extends \PHPUnit_Framework_TestCase { */ function testSetBadValue() { - $tree = array( - new MockPrincipal('foo','foo'), - ); + $tree = [ + new MockPrincipal('foo', 'foo'), + ]; $server = new DAV\Server($tree); - $server->addPlugin(new Plugin()); + $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; + $server->addPlugin($plugin); - $result = $server->updateProperties('foo', array( + $result = $server->updateProperties('foo', [ '{DAV:}group-member-set' => new \StdClass(), - )); + ]); } @@ -95,10 +98,12 @@ class PluginUpdatePropertiesTest extends \PHPUnit_Framework_TestCase { new DAV\SimpleCollection('foo'), ]; $server = new DAV\Server($tree); - $server->addPlugin(new Plugin()); + $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; + $server->addPlugin($plugin); $result = $server->updateProperties('foo', [ - '{DAV:}group-member-set' => new DAV\Xml\Property\Href(['/bar','/baz'],false), + '{DAV:}group-member-set' => new DAV\Xml\Property\Href(['/bar', '/baz'], false), ]); $expected = [ diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/AbstractPDOTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/AbstractPDOTest.php index 3814ebc0d..9fef3018d 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/AbstractPDOTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/AbstractPDOTest.php @@ -5,10 +5,24 @@ namespace Sabre\DAVACL\PrincipalBackend; use Sabre\DAV; use Sabre\HTTP; - abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { - abstract function getPDO(); + use DAV\DbTestHelperTrait; + + function setUp() { + + $this->dropTables(['principals', 'groupmembers']); + $this->createSchema('principals'); + + $pdo = $this->getPDO(); + + $pdo->query("INSERT INTO principals (uri,email,displayname) VALUES ('principals/user','user@example.org','User')"); + $pdo->query("INSERT INTO principals (uri,email,displayname) VALUES ('principals/group','group@example.org','Group')"); + + $pdo->query("INSERT INTO groupmembers (principal_id,member_id) VALUES (5,4)"); + + } + function testConstruct() { @@ -26,21 +40,26 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $pdo = $this->getPDO(); $backend = new PDO($pdo); - $expected = array( - array( - 'uri' => 'principals/user', + $expected = [ + [ + 'uri' => 'principals/admin', + '{http://sabredav.org/ns}email-address' => 'admin@example.org', + '{DAV:}displayname' => 'Administrator', + ], + [ + 'uri' => 'principals/user', '{http://sabredav.org/ns}email-address' => 'user@example.org', - '{DAV:}displayname' => 'User', - ), - array( - 'uri' => 'principals/group', + '{DAV:}displayname' => 'User', + ], + [ + 'uri' => 'principals/group', '{http://sabredav.org/ns}email-address' => 'group@example.org', - '{DAV:}displayname' => 'Group', - ), - ); + '{DAV:}displayname' => 'Group', + ], + ]; $this->assertEquals($expected, $backend->getPrincipalsByPrefix('principals')); - $this->assertEquals(array(), $backend->getPrincipalsByPrefix('foo')); + $this->assertEquals([], $backend->getPrincipalsByPrefix('foo')); } @@ -52,12 +71,12 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $pdo = $this->getPDO(); $backend = new PDO($pdo); - $expected = array( - 'id' => 1, - 'uri' => 'principals/user', + $expected = [ + 'id' => 4, + 'uri' => 'principals/user', '{http://sabredav.org/ns}email-address' => 'user@example.org', - '{DAV:}displayname' => 'User', - ); + '{DAV:}displayname' => 'User', + ]; $this->assertEquals($expected, $backend->getPrincipalByPath('principals/user')); $this->assertEquals(null, $backend->getPrincipalByPath('foo')); @@ -68,9 +87,9 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $pdo = $this->getPDO(); $backend = new PDO($pdo); - $expected = array('principals/user'); + $expected = ['principals/user']; - $this->assertEquals($expected,$backend->getGroupMemberSet('principals/group')); + $this->assertEquals($expected, $backend->getGroupMemberSet('principals/group')); } @@ -78,9 +97,9 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $pdo = $this->getPDO(); $backend = new PDO($pdo); - $expected = array('principals/group'); + $expected = ['principals/group']; - $this->assertEquals($expected,$backend->getGroupMembership('principals/user')); + $this->assertEquals($expected, $backend->getGroupMembership('principals/user')); } @@ -90,15 +109,15 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { // Start situation $backend = new PDO($pdo); - $this->assertEquals(array('principals/user'), $backend->getGroupMemberSet('principals/group')); + $this->assertEquals(['principals/user'], $backend->getGroupMemberSet('principals/group')); // Removing all principals - $backend->setGroupMemberSet('principals/group', array()); - $this->assertEquals(array(), $backend->getGroupMemberSet('principals/group')); + $backend->setGroupMemberSet('principals/group', []); + $this->assertEquals([], $backend->getGroupMemberSet('principals/group')); // Adding principals again - $backend->setGroupMemberSet('principals/group', array('principals/user')); - $this->assertEquals(array('principals/user'), $backend->getGroupMemberSet('principals/group')); + $backend->setGroupMemberSet('principals/group', ['principals/user']); + $this->assertEquals(['principals/user'], $backend->getGroupMemberSet('principals/group')); } @@ -109,17 +128,17 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $backend = new PDO($pdo); - $result = $backend->searchPrincipals('principals', array('{DAV:}blabla' => 'foo')); - $this->assertEquals(array(), $result); + $result = $backend->searchPrincipals('principals', ['{DAV:}blabla' => 'foo']); + $this->assertEquals([], $result); - $result = $backend->searchPrincipals('principals', array('{DAV:}displayname' => 'ou')); - $this->assertEquals(array('principals/group'), $result); + $result = $backend->searchPrincipals('principals', ['{DAV:}displayname' => 'ou']); + $this->assertEquals(['principals/group'], $result); - $result = $backend->searchPrincipals('principals', array('{DAV:}displayname' => 'UsEr', '{http://sabredav.org/ns}email-address' => 'USER@EXAMPLE')); - $this->assertEquals(array('principals/user'), $result); + $result = $backend->searchPrincipals('principals', ['{DAV:}displayname' => 'UsEr', '{http://sabredav.org/ns}email-address' => 'USER@EXAMPLE']); + $this->assertEquals(['principals/user'], $result); - $result = $backend->searchPrincipals('mom', array('{DAV:}displayname' => 'UsEr', '{http://sabredav.org/ns}email-address' => 'USER@EXAMPLE')); - $this->assertEquals(array(), $result); + $result = $backend->searchPrincipals('mom', ['{DAV:}displayname' => 'UsEr', '{http://sabredav.org/ns}email-address' => 'USER@EXAMPLE']); + $this->assertEquals([], $result); } @@ -137,12 +156,12 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $this->assertTrue($result); - $this->assertEquals(array( - 'id' => 1, - 'uri' => 'principals/user', - '{DAV:}displayname' => 'pietje', + $this->assertEquals([ + 'id' => 4, + 'uri' => 'principals/user', + '{DAV:}displayname' => 'pietje', '{http://sabredav.org/ns}email-address' => 'user@example.org', - ), $backend->getPrincipalByPath('principals/user')); + ], $backend->getPrincipalByPath('principals/user')); } @@ -153,7 +172,7 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $propPatch = new DAV\PropPatch([ '{DAV:}displayname' => 'pietje', - '{DAV:}unknown' => 'foo', + '{DAV:}unknown' => 'foo', ]); $backend->updatePrincipal('principals/user', $propPatch); @@ -161,17 +180,17 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { $this->assertFalse($result); - $this->assertEquals(array( + $this->assertEquals([ '{DAV:}displayname' => 424, - '{DAV:}unknown' => 403 - ), $propPatch->getResult()); + '{DAV:}unknown' => 403 + ], $propPatch->getResult()); - $this->assertEquals(array( - 'id' => '1', - 'uri' => 'principals/user', - '{DAV:}displayname' => 'User', + $this->assertEquals([ + 'id' => '4', + 'uri' => 'principals/user', + '{DAV:}displayname' => 'User', '{http://sabredav.org/ns}email-address' => 'user@example.org', - ), $backend->getPrincipalByPath('principals/user')); + ], $backend->getPrincipalByPath('principals/user')); } diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/PDOMySQLTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/PDOMySQLTest.php index 83353c86c..8779eb69f 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/PDOMySQLTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/PDOMySQLTest.php @@ -2,49 +2,8 @@ namespace Sabre\DAVACL\PrincipalBackend; -use Sabre\DAV; -use Sabre\HTTP; - - -require_once 'Sabre/TestUtil.php'; - class PDOMySQLTest extends AbstractPDOTest { - function getPDO() { - - if (!SABRE_HASMYSQL) $this->markTestSkipped('MySQL driver is not available, or not properly configured'); - $pdo = \Sabre\TestUtil::getMySQLDB(); - if (!$pdo) $this->markTestSkipped('Could not connect to MySQL database'); - $pdo->query("DROP TABLE IF EXISTS principals"); - $pdo->query(<<<SQL -create table principals ( - id integer unsigned not null primary key auto_increment, - uri varchar(50), - email varchar(80), - displayname VARCHAR(80), - vcardurl VARCHAR(80), - unique(uri) -) -SQL - ); - - $pdo->query("INSERT INTO principals (uri,email,displayname) VALUES ('principals/user','user@example.org','User')"); - $pdo->query("INSERT INTO principals (uri,email,displayname) VALUES ('principals/group','group@example.org','Group')"); - $pdo->query("DROP TABLE IF EXISTS groupmembers"); - $pdo->query(<<<SQL -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) -) -SQL - ); - - $pdo->query("INSERT INTO groupmembers (principal_id,member_id) VALUES (2,1)"); - - return $pdo; - - } + public $driver = 'mysql'; } diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/PDOSqliteTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/PDOSqliteTest.php index f335ed51f..48454981d 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/PDOSqliteTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalBackend/PDOSqliteTest.php @@ -2,44 +2,8 @@ namespace Sabre\DAVACL\PrincipalBackend; -use Sabre\DAV; -use Sabre\HTTP; +class PDOSqliteTest extends AbstractPDOTest { - -require_once 'Sabre/DAV/Auth/Backend/AbstractPDOTest.php'; - -class PDOSQLiteTest extends AbstractPDOTest { - - function tearDown() { - - if (file_exists(SABRE_TEMPDIR . '/pdobackend')) unlink(SABRE_TEMPDIR . '/pdobackend'); - if (file_exists(SABRE_TEMPDIR . '/pdobackend2')) unlink(SABRE_TEMPDIR . '/pdobackend2'); - - } - - function getPDO() { - - if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available'); - $pdo = new \PDO('sqlite:'.SABRE_TEMPDIR.'/pdobackend'); - $pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); - $pdo->query('CREATE TABLE principals (id INTEGER PRIMARY KEY ASC, uri TEXT, email VARCHAR(80), displayname VARCHAR(80))'); - $pdo->query('INSERT INTO principals VALUES (1, "principals/user","user@example.org","User")'); - $pdo->query('INSERT INTO principals VALUES (2, "principals/group","group@example.org","Group")'); - - $pdo->query(<<<SQL -CREATE TABLE groupmembers ( - id INTEGER PRIMARY KEY ASC, - principal_id INT, - member_id INT, - UNIQUE(principal_id, member_id) -) -SQL - ); - - $pdo->query("INSERT INTO groupmembers (principal_id,member_id) VALUES (2,1)"); - - return $pdo; - - } + public $driver = 'sqlite'; } diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalCollectionTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalCollectionTest.php index f51d2dcce..bcf78821b 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalCollectionTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalCollectionTest.php @@ -2,26 +2,22 @@ namespace Sabre\DAVACL; -use Sabre\DAV; -use Sabre\HTTP; - - class PrincipalCollectionTest extends \PHPUnit_Framework_TestCase { - public function testBasic() { + function testBasic() { $backend = new PrincipalBackend\Mock(); $pc = new PrincipalCollection($backend); $this->assertTrue($pc instanceof PrincipalCollection); - $this->assertEquals('principals',$pc->getName()); + $this->assertEquals('principals', $pc->getName()); } /** * @depends testBasic */ - public function testGetChildren() { + function testGetChildren() { $backend = new PrincipalBackend\Mock(); $pc = new PrincipalCollection($backend); @@ -29,7 +25,7 @@ class PrincipalCollectionTest extends \PHPUnit_Framework_TestCase { $children = $pc->getChildren(); $this->assertTrue(is_array($children)); - foreach($children as $child) { + foreach ($children as $child) { $this->assertTrue($child instanceof IPrincipal); } @@ -39,7 +35,7 @@ class PrincipalCollectionTest extends \PHPUnit_Framework_TestCase { * @depends testBasic * @expectedException Sabre\DAV\Exception\MethodNotAllowed */ - public function testGetChildrenDisable() { + function testGetChildrenDisable() { $backend = new PrincipalBackend\Mock(); $pc = new PrincipalCollection($backend); @@ -49,7 +45,7 @@ class PrincipalCollectionTest extends \PHPUnit_Framework_TestCase { } - public function testFindByUri() { + function testFindByUri() { $backend = new PrincipalBackend\Mock(); $pc = new PrincipalCollection($backend); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalPropertySearchTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalPropertySearchTest.php index 8e4c86782..60e156d9a 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalPropertySearchTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalPropertySearchTest.php @@ -23,6 +23,7 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { $fakeServer->debugExceptions = true; $plugin = new MockPlugin(); $plugin->allowAccessToNodesWithoutACL = true; + $plugin->allowUnauthenticatedAccess = false; $this->assertTrue($plugin instanceof Plugin); $fakeServer->addPlugin($plugin); @@ -48,11 +49,11 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { </d:prop> </d:principal-property-search>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '1', 'REQUEST_URI' => '/principals', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -63,10 +64,10 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(400, $server->httpResponse->getStatus(), $server->httpResponse->getBodyAsString()); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $server->httpResponse->getHeaders()); } @@ -87,11 +88,11 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { </d:prop> </d:principal-property-search>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/principals', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -102,11 +103,11 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(207, $server->httpResponse->getStatus(), "Full body: " . $server->httpResponse->getBodyAsString()); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - 'Vary' => ['Brief,Prefer'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + 'Vary' => ['Brief,Prefer'], + ], $server->httpResponse->getHeaders()); } @@ -127,11 +128,11 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { </d:prop> </d:principal-property-search>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -142,36 +143,36 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(207, $server->httpResponse->status, $server->httpResponse->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - 'Vary' => ['Brief,Prefer'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + 'Vary' => ['Brief,Prefer'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:multistatus', - '/d:multistatus/d:response' => 2, - '/d:multistatus/d:response/d:href' => 2, - '/d:multistatus/d:response/d:propstat' => 4, - '/d:multistatus/d:response/d:propstat/d:prop' => 4, - '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 2, + '/d:multistatus/d:response' => 2, + '/d:multistatus/d:response/d:href' => 2, + '/d:multistatus/d:response/d:propstat' => 4, + '/d:multistatus/d:response/d:propstat/d:prop' => 4, + '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 2, '/d:multistatus/d:response/d:propstat/d:prop/d:getcontentlength' => 2, - '/d:multistatus/d:response/d:propstat/d:status' => 4, - ); + '/d:multistatus/d:response/d:propstat/d:status' => 4, + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); } @@ -200,11 +201,11 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { </d:prop> </d:principal-property-search>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -215,36 +216,36 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(207, $server->httpResponse->status, $server->httpResponse->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - 'Vary' => ['Brief,Prefer'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + 'Vary' => ['Brief,Prefer'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:multistatus', - '/d:multistatus/d:response' => 0, - '/d:multistatus/d:response/d:href' => 0, - '/d:multistatus/d:response/d:propstat' => 0, - '/d:multistatus/d:response/d:propstat/d:prop' => 0, - '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 0, + '/d:multistatus/d:response' => 0, + '/d:multistatus/d:response/d:href' => 0, + '/d:multistatus/d:response/d:propstat' => 0, + '/d:multistatus/d:response/d:propstat/d:prop' => 0, + '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 0, '/d:multistatus/d:response/d:propstat/d:prop/d:getcontentlength' => 0, - '/d:multistatus/d:response/d:propstat/d:status' => 0, - ); + '/d:multistatus/d:response/d:propstat/d:status' => 0, + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); } @@ -272,11 +273,11 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { </d:prop> </d:principal-property-search>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -287,36 +288,36 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(207, $server->httpResponse->status, $server->httpResponse->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - 'Vary' => ['Brief,Prefer'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + 'Vary' => ['Brief,Prefer'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:multistatus', - '/d:multistatus/d:response' => 2, - '/d:multistatus/d:response/d:href' => 2, - '/d:multistatus/d:response/d:propstat' => 4, - '/d:multistatus/d:response/d:propstat/d:prop' => 4, - '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 2, + '/d:multistatus/d:response' => 2, + '/d:multistatus/d:response/d:href' => 2, + '/d:multistatus/d:response/d:propstat' => 4, + '/d:multistatus/d:response/d:propstat/d:prop' => 4, + '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 2, '/d:multistatus/d:response/d:propstat/d:prop/d:getcontentlength' => 2, - '/d:multistatus/d:response/d:propstat/d:status' => 4, - ); + '/d:multistatus/d:response/d:propstat/d:status' => 4, + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); } @@ -337,11 +338,11 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { </d:prop> </d:principal-property-search>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -352,30 +353,30 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(207, $server->httpResponse->status, $server->httpResponse->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - 'Vary' => ['Brief,Prefer'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + 'Vary' => ['Brief,Prefer'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:multistatus', '/d:multistatus/d:response' => 0, - ); + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); } @@ -386,10 +387,10 @@ class MockPlugin extends Plugin { function getCurrentUserPrivilegeSet($node) { - return array( + return [ '{DAV:}read', '{DAV:}write', - ); + ]; } diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalSearchPropertySetTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalSearchPropertySetTest.php index 952dc174a..fa1314d10 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalSearchPropertySetTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalSearchPropertySetTest.php @@ -21,6 +21,7 @@ class PrincipalSearchPropertySetTest extends \PHPUnit_Framework_TestCase { $fakeServer->sapi = new HTTP\SapiMock(); $fakeServer->httpResponse = new HTTP\ResponseMock(); $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $this->assertTrue($plugin instanceof Plugin); $fakeServer->addPlugin($plugin); $this->assertEquals($plugin, $fakeServer->getPlugin('acl')); @@ -34,11 +35,11 @@ class PrincipalSearchPropertySetTest extends \PHPUnit_Framework_TestCase { $xml = '<?xml version="1.0"?> <d:principal-search-property-set xmlns:d="DAV:" />'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '1', 'REQUEST_URI' => '/principals', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -49,10 +50,10 @@ class PrincipalSearchPropertySetTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(400, $server->httpResponse->status); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $server->httpResponse->getHeaders()); } @@ -61,11 +62,11 @@ class PrincipalSearchPropertySetTest extends \PHPUnit_Framework_TestCase { $xml = '<?xml version="1.0"?> <d:principal-search-property-set xmlns:d="DAV:"><d:ohell /></d:principal-search-property-set>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/principals', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -76,10 +77,10 @@ class PrincipalSearchPropertySetTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(400, $server->httpResponse->status, $server->httpResponse->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $server->httpResponse->getHeaders()); } @@ -88,11 +89,11 @@ class PrincipalSearchPropertySetTest extends \PHPUnit_Framework_TestCase { $xml = '<?xml version="1.0"?> <d:principal-search-property-set xmlns:d="DAV:"/>'; - $serverVars = array( + $serverVars = [ 'REQUEST_METHOD' => 'REPORT', 'HTTP_DEPTH' => '0', 'REQUEST_URI' => '/principals', - ); + ]; $request = HTTP\Sapi::createFromServerArray($serverVars); $request->setBody($xml); @@ -103,34 +104,34 @@ class PrincipalSearchPropertySetTest extends \PHPUnit_Framework_TestCase { $server->exec(); $this->assertEquals(200, $server->httpResponse->status, $server->httpResponse->body); - $this->assertEquals(array( + $this->assertEquals([ 'X-Sabre-Version' => [DAV\Version::VERSION], - 'Content-Type' => ['application/xml; charset=utf-8'], - ), $server->httpResponse->getHeaders()); + 'Content-Type' => ['application/xml; charset=utf-8'], + ], $server->httpResponse->getHeaders()); - $check = array( + $check = [ '/d:principal-search-property-set', - '/d:principal-search-property-set/d:principal-search-property' => 2, - '/d:principal-search-property-set/d:principal-search-property/d:prop' => 2, - '/d:principal-search-property-set/d:principal-search-property/d:prop/d:displayname' => 1, + '/d:principal-search-property-set/d:principal-search-property' => 2, + '/d:principal-search-property-set/d:principal-search-property/d:prop' => 2, + '/d:principal-search-property-set/d:principal-search-property/d:prop/d:displayname' => 1, '/d:principal-search-property-set/d:principal-search-property/d:prop/s:email-address' => 1, - '/d:principal-search-property-set/d:principal-search-property/d:description' => 2, - ); + '/d:principal-search-property-set/d:principal-search-property/d:description' => 2, + ]; $xml = simplexml_load_string($server->httpResponse->body); - $xml->registerXPathNamespace('d','DAV:'); - $xml->registerXPathNamespace('s','http://sabredav.org/ns'); - foreach($check as $v1=>$v2) { + $xml->registerXPathNamespace('d', 'DAV:'); + $xml->registerXPathNamespace('s', 'http://sabredav.org/ns'); + foreach ($check as $v1 => $v2) { - $xpath = is_int($v1)?$v2:$v1; + $xpath = is_int($v1) ? $v2 : $v1; $result = $xml->xpath($xpath); $count = 1; if (!is_int($v1)) $count = $v2; - $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); + $this->assertEquals($count, count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body); } diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalTest.php index 03fd9d64d..20622ad17 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PrincipalTest.php @@ -7,10 +7,10 @@ use Sabre\HTTP; class PrincipalTest extends \PHPUnit_Framework_TestCase { - public function testConstruct() { + function testConstruct() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); $this->assertTrue($principal instanceof Principal); } @@ -18,65 +18,65 @@ class PrincipalTest extends \PHPUnit_Framework_TestCase { /** * @expectedException Sabre\DAV\Exception */ - public function testConstructNoUri() { + function testConstructNoUri() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array()); + $principal = new Principal($principalBackend, []); } - public function testGetName() { + function testGetName() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $this->assertEquals('admin',$principal->getName()); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $this->assertEquals('admin', $principal->getName()); } - public function testGetDisplayName() { + function testGetDisplayName() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $this->assertEquals('admin',$principal->getDisplayname()); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $this->assertEquals('admin', $principal->getDisplayname()); - $principal = new Principal($principalBackend, array( - 'uri' => 'principals/admin', + $principal = new Principal($principalBackend, [ + 'uri' => 'principals/admin', '{DAV:}displayname' => 'Mr. Admin' - )); - $this->assertEquals('Mr. Admin',$principal->getDisplayname()); + ]); + $this->assertEquals('Mr. Admin', $principal->getDisplayname()); } - public function testGetProperties() { + function testGetProperties() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array( - 'uri' => 'principals/admin', - '{DAV:}displayname' => 'Mr. Admin', + $principal = new Principal($principalBackend, [ + 'uri' => 'principals/admin', + '{DAV:}displayname' => 'Mr. Admin', '{http://www.example.org/custom}custom' => 'Custom', '{http://sabredav.org/ns}email-address' => 'admin@example.org', - )); + ]); - $keys = array( + $keys = [ '{DAV:}displayname', '{http://www.example.org/custom}custom', '{http://sabredav.org/ns}email-address', - ); + ]; $props = $principal->getProperties($keys); - foreach($keys as $key) $this->assertArrayHasKey($key,$props); + foreach ($keys as $key) $this->assertArrayHasKey($key, $props); - $this->assertEquals('Mr. Admin',$props['{DAV:}displayname']); + $this->assertEquals('Mr. Admin', $props['{DAV:}displayname']); $this->assertEquals('admin@example.org', $props['{http://sabredav.org/ns}email-address']); } - public function testUpdateProperties() { + function testUpdateProperties() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); - $propPatch = new DAV\PropPatch(array('{DAV:}yourmom' => 'test')); + $propPatch = new DAV\PropPatch(['{DAV:}yourmom' => 'test']); $result = $principal->propPatch($propPatch); $result = $propPatch->commit(); @@ -84,123 +84,123 @@ class PrincipalTest extends \PHPUnit_Framework_TestCase { } - public function testGetPrincipalUrl() { + function testGetPrincipalUrl() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $this->assertEquals('principals/admin',$principal->getPrincipalUrl()); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $this->assertEquals('principals/admin', $principal->getPrincipalUrl()); } - public function testGetAlternateUriSet() { + function testGetAlternateUriSet() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array( - 'uri' => 'principals/admin', - '{DAV:}displayname' => 'Mr. Admin', + $principal = new Principal($principalBackend, [ + 'uri' => 'principals/admin', + '{DAV:}displayname' => 'Mr. Admin', '{http://www.example.org/custom}custom' => 'Custom', '{http://sabredav.org/ns}email-address' => 'admin@example.org', - '{DAV:}alternate-URI-set' => array( + '{DAV:}alternate-URI-set' => [ 'mailto:admin+1@example.org', 'mailto:admin+2@example.org', 'mailto:admin@example.org', - ), - )); + ], + ]); - $expected = array( + $expected = [ 'mailto:admin+1@example.org', 'mailto:admin+2@example.org', 'mailto:admin@example.org', - ); + ]; - $this->assertEquals($expected,$principal->getAlternateUriSet()); + $this->assertEquals($expected, $principal->getAlternateUriSet()); } - public function testGetAlternateUriSetEmpty() { + function testGetAlternateUriSetEmpty() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array( + $principal = new Principal($principalBackend, [ 'uri' => 'principals/admin', - )); + ]); - $expected = array(); + $expected = []; - $this->assertEquals($expected,$principal->getAlternateUriSet()); + $this->assertEquals($expected, $principal->getAlternateUriSet()); } - public function testGetGroupMemberSet() { + function testGetGroupMemberSet() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $this->assertEquals(array(),$principal->getGroupMemberSet()); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $this->assertEquals([], $principal->getGroupMemberSet()); } - public function testGetGroupMembership() { + function testGetGroupMembership() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $this->assertEquals(array(),$principal->getGroupMembership()); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $this->assertEquals([], $principal->getGroupMembership()); } - public function testSetGroupMemberSet() { + function testSetGroupMemberSet() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $principal->setGroupMemberSet(array('principals/foo')); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $principal->setGroupMemberSet(['principals/foo']); - $this->assertEquals(array( - 'principals/admin' => array('principals/foo'), - ), $principalBackend->groupMembers); + $this->assertEquals([ + 'principals/admin' => ['principals/foo'], + ], $principalBackend->groupMembers); } - public function testGetOwner() { + function testGetOwner() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $this->assertEquals('principals/admin',$principal->getOwner()); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $this->assertEquals('principals/admin', $principal->getOwner()); } - public function testGetGroup() { + function testGetGroup() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); $this->assertNull($principal->getGroup()); } - public function testGetACl() { + function testGetACl() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $this->assertEquals(array( - array( - 'privilege' => '{DAV:}read', - 'principal' => '{DAV:}authenticated', + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $this->assertEquals([ + [ + 'privilege' => '{DAV:}all', + 'principal' => '{DAV:}owner', 'protected' => true, - ) - ),$principal->getACL()); + ] + ], $principal->getACL()); } /** - * @expectedException Sabre\DAV\Exception\MethodNotAllowed + * @expectedException \Sabre\DAV\Exception\Forbidden */ - public function testSetACl() { + function testSetACl() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); - $principal->setACL(array()); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); + $principal->setACL([]); } - public function testGetSupportedPrivilegeSet() { + function testGetSupportedPrivilegeSet() { $principalBackend = new PrincipalBackend\Mock(); - $principal = new Principal($principalBackend, array('uri' => 'principals/admin')); + $principal = new Principal($principalBackend, ['uri' => 'principals/admin']); $this->assertNull($principal->getSupportedPrivilegeSet()); } diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/SimplePluginTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/SimplePluginTest.php index fb73cc16a..2de0ba6a8 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/SimplePluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/SimplePluginTest.php @@ -5,7 +5,6 @@ namespace Sabre\DAVACL; use Sabre\DAV; use Sabre\HTTP; - require_once 'Sabre/DAVACL/MockPrincipal.php'; require_once 'Sabre/DAVACL/MockACLNode.php'; @@ -14,21 +13,22 @@ class SimplePluginTest extends \PHPUnit_Framework_TestCase { function testValues() { $aclPlugin = new Plugin(); - $this->assertEquals('acl',$aclPlugin->getPluginName()); + $this->assertEquals('acl', $aclPlugin->getPluginName()); $this->assertEquals( - array('access-control', 'calendarserver-principal-property-search'), + ['access-control', 'calendarserver-principal-property-search'], $aclPlugin->getFeatures() ); $this->assertEquals( - array( + [ '{DAV:}expand-property', + '{DAV:}principal-match', '{DAV:}principal-property-search', '{DAV:}principal-search-property-set' - ), + ], $aclPlugin->getSupportedReportSet('')); - $this->assertEquals(array('ACL'), $aclPlugin->getMethods('')); + $this->assertEquals(['ACL'], $aclPlugin->getMethods('')); $this->assertEquals( @@ -39,90 +39,84 @@ class SimplePluginTest extends \PHPUnit_Framework_TestCase { function testGetFlatPrivilegeSet() { - $expected = array( - '{DAV:}all' => array( - 'privilege' => '{DAV:}all', - 'abstract' => true, - 'aggregates' => array( + $expected = [ + '{DAV:}all' => [ + 'privilege' => '{DAV:}all', + 'abstract' => false, + 'aggregates' => [ '{DAV:}read', '{DAV:}write', - ), - 'concrete' => null, - ), - '{DAV:}read' => array( - 'privilege' => '{DAV:}read', - 'abstract' => false, - 'aggregates' => array( + ], + 'concrete' => '{DAV:}all', + ], + '{DAV:}read' => [ + 'privilege' => '{DAV:}read', + 'abstract' => false, + 'aggregates' => [ '{DAV:}read-acl', '{DAV:}read-current-user-privilege-set', - ), + ], 'concrete' => '{DAV:}read', - ), - '{DAV:}read-acl' => array( - 'privilege' => '{DAV:}read-acl', - 'abstract' => false, - 'aggregates' => array(), - 'concrete' => '{DAV:}read-acl', - ), - '{DAV:}read-current-user-privilege-set' => array( - 'privilege' => '{DAV:}read-current-user-privilege-set', - 'abstract' => false, - 'aggregates' => array(), - 'concrete' => '{DAV:}read-current-user-privilege-set', - ), - '{DAV:}write' => array( - 'privilege' => '{DAV:}write', - 'abstract' => false, - 'aggregates' => array( - '{DAV:}write-acl', + ], + '{DAV:}read-acl' => [ + 'privilege' => '{DAV:}read-acl', + 'abstract' => false, + 'aggregates' => [], + 'concrete' => '{DAV:}read-acl', + ], + '{DAV:}read-current-user-privilege-set' => [ + 'privilege' => '{DAV:}read-current-user-privilege-set', + 'abstract' => false, + 'aggregates' => [], + 'concrete' => '{DAV:}read-current-user-privilege-set', + ], + '{DAV:}write' => [ + 'privilege' => '{DAV:}write', + 'abstract' => false, + 'aggregates' => [ '{DAV:}write-properties', '{DAV:}write-content', + '{DAV:}unlock', '{DAV:}bind', '{DAV:}unbind', - '{DAV:}unlock', - ), + ], 'concrete' => '{DAV:}write', - ), - '{DAV:}write-acl' => array( - 'privilege' => '{DAV:}write-acl', - 'abstract' => false, - 'aggregates' => array(), - 'concrete' => '{DAV:}write-acl', - ), - '{DAV:}write-properties' => array( - 'privilege' => '{DAV:}write-properties', - 'abstract' => false, - 'aggregates' => array(), - 'concrete' => '{DAV:}write-properties', - ), - '{DAV:}write-content' => array( - 'privilege' => '{DAV:}write-content', - 'abstract' => false, - 'aggregates' => array(), - 'concrete' => '{DAV:}write-content', - ), - '{DAV:}unlock' => array( - 'privilege' => '{DAV:}unlock', - 'abstract' => false, - 'aggregates' => array(), - 'concrete' => '{DAV:}unlock', - ), - '{DAV:}bind' => array( - 'privilege' => '{DAV:}bind', - 'abstract' => false, - 'aggregates' => array(), - 'concrete' => '{DAV:}bind', - ), - '{DAV:}unbind' => array( - 'privilege' => '{DAV:}unbind', - 'abstract' => false, - 'aggregates' => array(), - 'concrete' => '{DAV:}unbind', - ), - - ); + ], + '{DAV:}write-properties' => [ + 'privilege' => '{DAV:}write-properties', + 'abstract' => false, + 'aggregates' => [], + 'concrete' => '{DAV:}write-properties', + ], + '{DAV:}write-content' => [ + 'privilege' => '{DAV:}write-content', + 'abstract' => false, + 'aggregates' => [], + 'concrete' => '{DAV:}write-content', + ], + '{DAV:}unlock' => [ + 'privilege' => '{DAV:}unlock', + 'abstract' => false, + 'aggregates' => [], + 'concrete' => '{DAV:}unlock', + ], + '{DAV:}bind' => [ + 'privilege' => '{DAV:}bind', + 'abstract' => false, + 'aggregates' => [], + 'concrete' => '{DAV:}bind', + ], + '{DAV:}unbind' => [ + 'privilege' => '{DAV:}unbind', + 'abstract' => false, + 'aggregates' => [], + 'concrete' => '{DAV:}unbind', + ], + + ]; $plugin = new Plugin(); + $plugin->allowUnauthenticatedAccess = false; $server = new DAV\Server(); $server->addPlugin($plugin); $this->assertEquals($expected, $plugin->getFlatPrivilegeSet('')); @@ -132,24 +126,26 @@ class SimplePluginTest extends \PHPUnit_Framework_TestCase { function testCurrentUserPrincipalsNotLoggedIn() { $acl = new Plugin(); + $acl->allowUnauthenticatedAccess = false; $server = new DAV\Server(); $server->addPlugin($acl); - $this->assertEquals(array(),$acl->getCurrentUserPrincipals()); + $this->assertEquals([], $acl->getCurrentUserPrincipals()); } function testCurrentUserPrincipalsSimple() { - $tree = array( + $tree = [ - new DAV\SimpleCollection('principals', array( - new MockPrincipal('admin','principals/admin'), - )) + new DAV\SimpleCollection('principals', [ + new MockPrincipal('admin', 'principals/admin'), + ]) - ); + ]; $acl = new Plugin(); + $acl->allowUnauthenticatedAccess = false; $server = new DAV\Server($tree); $server->addPlugin($acl); @@ -159,24 +155,25 @@ class SimplePluginTest extends \PHPUnit_Framework_TestCase { //forcing login $auth->beforeMethod(new HTTP\Request(), new HTTP\Response()); - $this->assertEquals(array('principals/admin'),$acl->getCurrentUserPrincipals()); + $this->assertEquals(['principals/admin'], $acl->getCurrentUserPrincipals()); } function testCurrentUserPrincipalsGroups() { - $tree = array( + $tree = [ - new DAV\SimpleCollection('principals', array( - new MockPrincipal('admin','principals/admin',array('principals/administrators', 'principals/everyone')), - new MockPrincipal('administrators','principals/administrators',array('principals/groups'), array('principals/admin')), - new MockPrincipal('everyone','principals/everyone',array(), array('principals/admin')), - new MockPrincipal('groups','principals/groups',array(), array('principals/administrators')), - )) + new DAV\SimpleCollection('principals', [ + new MockPrincipal('admin', 'principals/admin', ['principals/administrators', 'principals/everyone']), + new MockPrincipal('administrators', 'principals/administrators', ['principals/groups'], ['principals/admin']), + new MockPrincipal('everyone', 'principals/everyone', [], ['principals/admin']), + new MockPrincipal('groups', 'principals/groups', [], ['principals/administrators']), + ]) - ); + ]; $acl = new Plugin(); + $acl->allowUnauthenticatedAccess = false; $server = new DAV\Server($tree); $server->addPlugin($acl); @@ -186,75 +183,77 @@ class SimplePluginTest extends \PHPUnit_Framework_TestCase { //forcing login $auth->beforeMethod(new HTTP\Request(), new HTTP\Response()); - $expected = array( + $expected = [ 'principals/admin', 'principals/administrators', 'principals/everyone', 'principals/groups', - ); + ]; - $this->assertEquals($expected,$acl->getCurrentUserPrincipals()); + $this->assertEquals($expected, $acl->getCurrentUserPrincipals()); // The second one should trigger the cache and be identical - $this->assertEquals($expected,$acl->getCurrentUserPrincipals()); + $this->assertEquals($expected, $acl->getCurrentUserPrincipals()); } function testGetACL() { - $acl = array( - array( + $acl = [ + [ 'principal' => 'principals/admin', 'privilege' => '{DAV:}read', - ), - array( + ], + [ 'principal' => 'principals/admin', 'privilege' => '{DAV:}write', - ), - ); + ], + ]; - $tree = array( - new MockACLNode('foo',$acl), - ); + $tree = [ + new MockACLNode('foo', $acl), + ]; $server = new DAV\Server($tree); $aclPlugin = new Plugin(); + $aclPlugin->allowUnauthenticatedAccess = false; $server->addPlugin($aclPlugin); - $this->assertEquals($acl,$aclPlugin->getACL('foo')); + $this->assertEquals($acl, $aclPlugin->getACL('foo')); } function testGetCurrentUserPrivilegeSet() { - $acl = array( - array( + $acl = [ + [ 'principal' => 'principals/admin', 'privilege' => '{DAV:}read', - ), - array( + ], + [ 'principal' => 'principals/user1', 'privilege' => '{DAV:}read', - ), - array( + ], + [ 'principal' => 'principals/admin', 'privilege' => '{DAV:}write', - ), - ); + ], + ]; - $tree = array( - new MockACLNode('foo',$acl), + $tree = [ + new MockACLNode('foo', $acl), - new DAV\SimpleCollection('principals', array( - new MockPrincipal('admin','principals/admin'), - )), + new DAV\SimpleCollection('principals', [ + new MockPrincipal('admin', 'principals/admin'), + ]), - ); + ]; $server = new DAV\Server($tree); $aclPlugin = new Plugin(); + $aclPlugin->allowUnauthenticatedAccess = false; $server->addPlugin($aclPlugin); $auth = new DAV\Auth\Plugin(new DAV\Auth\Backend\Mock()); @@ -263,52 +262,51 @@ class SimplePluginTest extends \PHPUnit_Framework_TestCase { //forcing login $auth->beforeMethod(new HTTP\Request(), new HTTP\Response()); - $expected = array( + $expected = [ '{DAV:}write', - '{DAV:}write-acl', '{DAV:}write-properties', '{DAV:}write-content', - '{DAV:}bind', - '{DAV:}unbind', '{DAV:}unlock', + '{DAV:}write-acl', '{DAV:}read', '{DAV:}read-acl', '{DAV:}read-current-user-privilege-set', - ); + ]; - $this->assertEquals($expected,$aclPlugin->getCurrentUserPrivilegeSet('foo')); + $this->assertEquals($expected, $aclPlugin->getCurrentUserPrivilegeSet('foo')); } function testCheckPrivileges() { - $acl = array( - array( + $acl = [ + [ 'principal' => 'principals/admin', 'privilege' => '{DAV:}read', - ), - array( + ], + [ 'principal' => 'principals/user1', 'privilege' => '{DAV:}read', - ), - array( + ], + [ 'principal' => 'principals/admin', 'privilege' => '{DAV:}write', - ), - ); + ], + ]; - $tree = array( - new MockACLNode('foo',$acl), + $tree = [ + new MockACLNode('foo', $acl), - new DAV\SimpleCollection('principals', array( - new MockPrincipal('admin','principals/admin'), - )), + new DAV\SimpleCollection('principals', [ + new MockPrincipal('admin', 'principals/admin'), + ]), - ); + ]; $server = new DAV\Server($tree); $aclPlugin = new Plugin(); + $aclPlugin->allowUnauthenticatedAccess = false; $server->addPlugin($aclPlugin); $auth = new DAV\Auth\Plugin(new DAV\Auth\Backend\Mock()); @@ -317,11 +315,7 @@ class SimplePluginTest extends \PHPUnit_Framework_TestCase { //forcing login //$auth->beforeMethod('GET','/'); - $this->assertFalse($aclPlugin->checkPrivileges('foo', array('{DAV:}read'), Plugin::R_PARENT, false)); + $this->assertFalse($aclPlugin->checkPrivileges('foo', ['{DAV:}read'], Plugin::R_PARENT, false)); } } - - - - diff --git a/vendor/sabre/dav/tests/Sabre/DAVServerTest.php b/vendor/sabre/dav/tests/Sabre/DAVServerTest.php index d329b5b05..35f240d23 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVServerTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVServerTest.php @@ -27,6 +27,7 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { protected $setupCalDAVICSExport = false; protected $setupLocks = false; protected $setupFiles = false; + protected $setupSharing = false; protected $setupPropertyStorage = false; /** @@ -90,6 +91,13 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { protected $locksPlugin; /** + * Sharing plugin. + * + * @var \Sabre\DAV\Sharing\Plugin + */ + protected $sharingPlugin; + + /* * @var Sabre\DAV\PropertyStorage\Plugin */ protected $propertyStoragePlugin; @@ -102,6 +110,12 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { function setUp() { + $this->initializeEverything(); + + } + + function initializeEverything() { + $this->setUpBackends(); $this->setUpTree(); @@ -113,6 +127,10 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { $this->caldavPlugin = new CalDAV\Plugin(); $this->server->addPlugin($this->caldavPlugin); } + if ($this->setupCalDAVSharing || $this->setupSharing) { + $this->sharingPlugin = new DAV\Sharing\Plugin(); + $this->server->addPlugin($this->sharingPlugin); + } if ($this->setupCalDAVSharing) { $this->caldavSharingPlugin = new CalDAV\SharingPlugin(); $this->server->addPlugin($this->caldavSharingPlugin); @@ -132,10 +150,6 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { $this->carddavPlugin = new CardDAV\Plugin(); $this->server->addPlugin($this->carddavPlugin); } - if ($this->setupACL) { - $this->aclPlugin = new DAVACL\Plugin(); - $this->server->addPlugin($this->aclPlugin); - } if ($this->setupLocks) { $this->locksPlugin = new DAV\Locks\Plugin( $this->locksBackend @@ -149,13 +163,15 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { $this->server->addPlugin($this->propertyStoragePlugin); } if ($this->autoLogin) { - $authBackend = new DAV\Auth\Backend\Mock(); - $authBackend->setPrincipal('principals/' . $this->autoLogin); - $this->authPlugin = new DAV\Auth\Plugin($authBackend); - $this->server->addPlugin($this->authPlugin); - - // This will trigger the actual login procedure - $this->authPlugin->beforeMethod(new Request(), new Response()); + $this->autoLogin($this->autoLogin); + } + if ($this->setupACL) { + $this->aclPlugin = new DAVACL\Plugin(); + if (!$this->autoLogin) { + $this->aclPlugin->allowUnauthenticatedAccess = false; + } + $this->aclPlugin->adminPrincipals = ['principals/admin']; + $this->server->addPlugin($this->aclPlugin); } } @@ -166,22 +182,54 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { * You can either pass an instance of Sabre\HTTP\Request, or an array, * which will then be used as the _SERVER array. * + * If $expectedStatus is set, we'll compare it with the HTTP status of + * the returned response. If it doesn't match, we'll immediately fail + * the test. + * * @param array|\Sabre\HTTP\Request $request + * @param int $expectedStatus * @return \Sabre\HTTP\Response */ - function request($request) { + function request($request, $expectedStatus = null) { if (is_array($request)) { $request = HTTP\Request::createFromServerArray($request); } + $response = new HTTP\ResponseMock(); + $this->server->httpRequest = $request; - $this->server->httpResponse = new HTTP\ResponseMock(); + $this->server->httpResponse = $response; $this->server->exec(); + if ($expectedStatus) { + $responseBody = $expectedStatus !== $response->getStatus() ? $response->getBodyAsString() : ''; + $this->assertEquals($expectedStatus, $response->getStatus(), 'Incorrect HTTP status received for request. Response body: ' . $responseBody); + } return $this->server->httpResponse; } + /** + * This function takes a username and sets the server in a state where + * this user is logged in, and no longer requires an authentication check. + * + * @param string $userName + */ + function autoLogin($userName) { + $authBackend = new DAV\Auth\Backend\Mock(); + $authBackend->setPrincipal('principals/' . $userName); + $this->authPlugin = new DAV\Auth\Plugin($authBackend); + + // If the auth plugin already exists, we're removing its hooks: + if ($oldAuth = $this->server->getPlugin('auth')) { + $this->server->removeListener('beforeMethod', [$oldAuth, 'beforeMethod']); + } + $this->server->addPlugin($this->authPlugin); + + // This will trigger the actual login procedure + $this->authPlugin->beforeMethod(new Request(), new Response()); + } + /** * Override this to provide your own Tree for your test-case. */ @@ -200,10 +248,14 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { ); } - if ($this->setupCardDAV || $this->setupCalDAV) { + if ($this->setupCalDAV) { $this->tree[] = new CalDAV\Principal\Collection( $this->principalBackend ); + } elseif ($this->setupCardDAV || $this->setupACL) { + $this->tree[] = new DAVACL\PrincipalCollection( + $this->principalBackend + ); } if ($this->setupFiles) { @@ -231,7 +283,7 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { if ($this->setupCardDAV && is_null($this->carddavBackend)) { $this->carddavBackend = new CardDAV\Backend\Mock($this->carddavAddressBooks, $this->carddavCards); } - if ($this->setupCardDAV || $this->setupCalDAV) { + if ($this->setupCardDAV || $this->setupCalDAV || $this->setupACL) { $this->principalBackend = new DAVACL\PrincipalBackend\Mock(); } if ($this->setupLocks) { @@ -244,7 +296,7 @@ abstract class DAVServerTest extends \PHPUnit_Framework_TestCase { } - function assertHTTPStatus($expectedStatus, HTTP\Request $req) { + function assertHttpStatus($expectedStatus, HTTP\Request $req) { $resp = $this->request($req); $this->assertEquals((int)$expectedStatus, (int)$resp->status, 'Incorrect HTTP status received: ' . $resp->body); diff --git a/vendor/sabre/dav/tests/Sabre/TestUtil.php b/vendor/sabre/dav/tests/Sabre/TestUtil.php index 20bce1ea0..9df94915f 100644 --- a/vendor/sabre/dav/tests/Sabre/TestUtil.php +++ b/vendor/sabre/dav/tests/Sabre/TestUtil.php @@ -11,17 +11,17 @@ class TestUtil { */ static function clearTempDir() { - self::deleteTree(SABRE_TEMPDIR,false); + self::deleteTree(SABRE_TEMPDIR, false); } - static private function deleteTree($path,$deleteRoot = true) { + private static function deleteTree($path, $deleteRoot = true) { - foreach(scandir($path) as $node) { + foreach (scandir($path) as $node) { - if ($node=='.' || $node=='..') continue; - $myPath = $path.'/'. $node; + if ($node == '.' || $node == '..') continue; + $myPath = $path . '/' . $node; if (is_file($myPath)) { unlink($myPath); } else { @@ -38,8 +38,8 @@ class TestUtil { static function getMySQLDB() { try { - $pdo = new \PDO(SABRE_MYSQLDSN,SABRE_MYSQLUSER,SABRE_MYSQLPASS); - $pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); + $pdo = new \PDO(SABRE_MYSQLDSN, SABRE_MYSQLUSER, SABRE_MYSQLPASS); + $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); return $pdo; } catch (\PDOException $e) { return null; @@ -49,10 +49,23 @@ class TestUtil { static function getSQLiteDB() { - $pdo = new \PDO('sqlite:'.SABRE_TEMPDIR.'/pdobackend'); - $pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); + $pdo = new \PDO('sqlite:' . SABRE_TEMPDIR . '/pdobackend'); + $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); return $pdo; } + static function getPgSqlDB() { + + //try { + $pdo = new \PDO(SABRE_PGSQLDSN); + $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + return $pdo; + //} catch (\PDOException $e) { + // return null; + //} + + } + + } diff --git a/vendor/sabre/dav/tests/bootstrap.php b/vendor/sabre/dav/tests/bootstrap.php index 325ccd3c7..26eb32aa2 100644 --- a/vendor/sabre/dav/tests/bootstrap.php +++ b/vendor/sabre/dav/tests/bootstrap.php @@ -7,28 +7,30 @@ $autoLoader = include __DIR__ . '/../vendor/autoload.php'; // SabreDAV tests auto loading $autoLoader->add('Sabre\\', __DIR__); // VObject tests auto loading -$autoLoader->addPsr4('Sabre\\VObject\\',__DIR__ . '/../vendor/sabre/vobject/tests/VObject'); -$autoLoader->addPsr4('Sabre\\Xml\\',__DIR__ . '/../vendor/sabre/xml/tests/Sabre/Xml'); +$autoLoader->addPsr4('Sabre\\VObject\\', __DIR__ . '/../vendor/sabre/vobject/tests/VObject'); +$autoLoader->addPsr4('Sabre\\Xml\\', __DIR__ . '/../vendor/sabre/xml/tests/Sabre/Xml'); date_default_timezone_set('UTC'); $config = [ 'SABRE_TEMPDIR' => dirname(__FILE__) . '/temp/', - 'SABRE_HASSQLITE' => in_array('sqlite',PDO::getAvailableDrivers()), - 'SABRE_HASMYSQL' => in_array('mysql',PDO::getAvailableDrivers()), - 'SABRE_MYSQLDSN' => 'mysql:host=127.0.0.1;dbname=sabredav', - 'SABRE_MYSQLUSER' => 'root', + 'SABRE_HASSQLITE' => in_array('sqlite', PDO::getAvailableDrivers()), + 'SABRE_HASMYSQL' => in_array('mysql', PDO::getAvailableDrivers()), + 'SABRE_HASPGSQL' => in_array('pgsql', PDO::getAvailableDrivers()), + 'SABRE_MYSQLDSN' => 'mysql:host=127.0.0.1;dbname=sabredav_test', + 'SABRE_MYSQLUSER' => 'sabredav', 'SABRE_MYSQLPASS' => '', + 'SABRE_PGSQLDSN' => 'pgsql:host=localhost;dbname=sabredav_test;user=sabredav;password=sabredav', ]; if (file_exists(__DIR__ . '/config.user.php')) { include __DIR__ . '/config.user.php'; - foreach($userConfig as $key=>$value) { + foreach ($userConfig as $key => $value) { $config[$key] = $value; } } -foreach($config as $key=>$value) { +foreach ($config as $key => $value) { if (!defined($key)) define($key, $value); } diff --git a/vendor/sabre/dav/tests/phpunit.xml b/vendor/sabre/dav/tests/phpunit.xml index db475f12b..e16ec38b5 100644 --- a/vendor/sabre/dav/tests/phpunit.xml +++ b/vendor/sabre/dav/tests/phpunit.xml @@ -6,22 +6,15 @@ convertWarningsToExceptions="true" strict="true" > + <testsuite name="sabre-vobject"> + <directory>../vendor/sabre/vobject/tests/VObject</directory> + </testsuite> <testsuite name="sabre-event"> <directory>../vendor/sabre/event/tests/</directory> </testsuite> - <testsuite name="sabre-uri"> - <directory>../vendor/sabre/uri/tests/</directory> - </testsuite> - <testsuite name="sabre-xml"> - <directory>../vendor/sabre/xml/tests/Sabre/Xml/</directory> - </testsuite> <testsuite name="sabre-http"> <directory>../vendor/sabre/http/tests/HTTP</directory> </testsuite> - <testsuite name="sabre-vobject"> - <directory>../vendor/sabre/vobject/tests/VObject</directory> - </testsuite> - <testsuite name="sabre-dav"> <directory>Sabre/DAV</directory> </testsuite> diff --git a/vendor/sabre/vobject/ChangeLog.md b/vendor/sabre/vobject/ChangeLog.md new file mode 100644 index 000000000..60501f930 --- /dev/null +++ b/vendor/sabre/vobject/ChangeLog.md @@ -0,0 +1,563 @@ +ChangeLog +========= + +3.4.5 (2015-06-02) +------------------ + +* #229: Converting vcards from 3.0 to 4.0 that contained a `LANG` property + would throw an error. + + +3.4.4 (2015-05-27) +------------------ + +* #228: Fixed a 'party crasher' bug in the iTip broker. This would break + scheduling in some cases. + + +3.4.3 (2015-05-19) +------------------ + +* #219: Corrected validation of `EXDATE` properties with more than one value. +* #212: `BYSETPOS` with values below `-1` was broken and could cause infinite + loops. +* #211: Fix `BYDAY=-5TH` in recurrence iterator. (@lindquist) +* #216: `ENCODING` parameter is now validated for all document types. +* #217: Initializing vCard `DATE` objects with a PHP DateTime object will now + work correctly. (@thomascube) + + +3.4.2 (2015-02-25) +------------------ + +* #210: iTip: Replying to an event without a master event was broken. + + +3.4.1 (2015-02-24) +------------------ + +* A minor change to ensure that unittests work correctly in the sabre/dav + test-suite. + + +3.4.0 (2015-02-23) +------------------ + +* #196: Made parsing recurrence rules a lot faster on big calendars. +* Updated windows timezone mappings to latest unicode version. +* #202: Support for parsing and validating `VAVAILABILITY` components. (@Hywan) +* #195: PHP 5.3 compatibility in 'generatevcards' script. (@rickdenhaan) +* #205: Improving handling of multiple `EXDATE` when processing iTip changes. + (@armin-hackmann) +* #187: Fixed validator rules for `LAST-MODIFIED` properties. +* #188: Retain floating times when generating instances using + `Recur\EventIterator`. +* #203: Skip tests for timezones that are not supported on older PHP versions, + instead of a hard fail. +* #204: Dealing a bit better with vCard date-time values that contained + milliseconds. (which is normally invalid). (@armin-hackmann) + + +3.3.5 (2015-01-09) +------------------ + +* #168: Expanding calendars now removes objects with recurrence rules that + don't have a valid recurrence instance. +* #177: SCHEDULE-STATUS should not contain a reason phrase, only a status + code. +* #175: Parser can now read and skip the UTF-8 BOM. +* #179: Added `isFloating` to `DATE-TIME` properties. +* #179: Fixed jCal serialization of floating `DATE-TIME` properties. +* #173: vCard converter failed for `X-ABDATE` properties that had no + `X-ABLABEL`. +* #180: Added `PROFILE_CALDAV` and `PROFILE_CARDDAV` to enable validation rules + specific for CalDAV/CardDAV servers. +* #176: A missing `UID` is no longer an error, but a warning for the vCard + validator, unless `PROFILE_CARDDAV` is specified. + + +3.3.4 (2014-11-19) +------------------ + +* #154: Converting `ANNIVERSARY` to `X-ANNIVERSARY` and `X-ABDATE` and + vice-versa when converting to/from vCard 4. +* #154: It's now possible to easily select all vCard properties belonging to + a single group with `$vcard->{'ITEM1.'}` syntax. (@armin-hackmann) +* #156: Simpler way to check if a string is UTF-8. (@Hywan) +* Unittest improvements. +* #159: The recurrence iterator, freebusy generator and iCalendar DATE and + DATE-TIME properties can now all accept a reference timezone when working + floating times or all-day events. +* #159: Master events will no longer get a `RECURRENCE-ID` when expanding. +* #159: `RECURRENCE-ID` for all-day events will now be correct when expanding. +* #163: Added a `getTimeZone()` method to `VTIMEZONE` components. + + +3.3.3 (2014-10-09) +------------------ + +* #142: `CANCEL` and `REPLY` messages now include the `DTSTART` from the + original event. +* #143: `SCHEDULE-AGENT` on the `ORGANIZER` property is respected. +* #144: `PARTSTAT=NEEDS-ACTION` is now set for new invites, if no `PARTSTAT` is + set to support the inbox feature of iOS. +* #147: Bugs related to scheduling all-day events. +* #148: Ignore events that have attendees but no organizer. +* #149: Avoiding logging errors during timezone detection. This is a workaround + for a PHP bug. +* Support for "Line Islands Standard Time" windows timezone. +* #154: Correctly work around vCard parameters that have a value but no name. + + +3.3.2 (2014-09-19) +------------------ + +* Changed: iTip broker now sets RSVP status to false when replies are received. +* #118: iTip Message now has a `getScheduleStatus()` method. +* #119: Support for detecting 'significant changes'. +* #120: Support for `SCHEDULE-FORCE-SEND`. +* #121: iCal demands parameters containing the + sign to be quoted. +* #122: Don't generate REPLY messages for events that have been cancelled. +* #123: Added `SUMMARY` to iTip messages. +* #130: Incorrect validation rules for `RELATED` (should be `RELATED-TO`). +* #128: `ATTACH` in iCalendar is `URI` by default, not `BINARY`. +* #131: RRULE that doesn't provide a single valid instance now throws an + exception. +* #136: Validator rejects *all* control characters. We were missing a few. +* #133: Splitter objects will throw exceptions when receiving incompatible + objects. +* #127: Attendees who delete recurring event instances events they had already + declined earlier will no longer generate another reply. +* #125: Send CANCEL messages when ORGANIZER property gets deleted. + + +3.3.1 (2014-08-18) +------------------ + +* Changed: It's now possible to pass DateTime objects when using the magic + setters on properties. (`$event->DTSTART = new DateTime('now')`). +* #111: iTip Broker does not process attendee adding events to EXDATE. +* #112: EventIterator now sets TZID on RECURRENCE-ID. +* #113: Timezone support during creation of iTip REPLY messages. +* #114: VTIMEZONE is retained when generating new REQUEST objects. +* #114: Support for 'MAILTO:' style email addresses (in uppercase) in the iTip + broker. This improves evolution support. +* #115: Using REQUEST-STATUS from REPLY messages and now propegating that into + SCHEDULE-STATUS. + + +3.3.0 (2014-08-07) +------------------ + +* We now use PSR-4 for the directory structure. This means that everything + that was used to be in the `lib/Sabre/VObject` directory is now moved to + `lib/`. If you use composer to load this library, you shouldn't have to do + anything about that though. +* VEVENT now get populated with a DTSTAMP and UID property by default. +* BC Break: Removed the 'includes.php' file. Use composer instead. +* #103: Added support for processing [iTip][iTip] messages. This allows a user + to parse incoming iTip messages and apply the result on existing calendars, + or automatically generate invites/replies/cancellations based on changes that + a user made on objects. +* #75, #58, #18: Fixes related to overriding the first event in recurrences. +* Added: VCalendar::getBaseComponent to find the 'master' component in a + calendar. +* #51: Support for iterating RDATE properties. +* Fixed: Issue #101: RecurrenceIterator::nextMonthly() shows events that are + excluded events with wrong time + + +3.2.4 (2014-07-14) +------------------ + +* Added: Issue #98. The VCardConverter now takes `X-APPLE-OMIT-YEAR` into + consideration when converting between vCard 3 and 4. +* Fixed: Issue #96. Some support for Yahoo's broken vcards. +* Fixed: PHP 5.3 support was broken in the cli tool. + + +3.2.3 (2014-06-12) +------------------ + +* Validator now checks if DUE and DTSTART are of the same type in VTODO, and + ensures that DUE is always after DTSTART. +* Removed documentation from source repository, to http://sabre.io/vobject/ +* Expanded the vobject cli tool validation output to make it easier to find + issues. +* Fixed: vobject repair. It was not working for iCalendar objects. + + +3.2.2 (2014-05-07) +------------------ + +* Minor tweak in unittests to make it run on PHP 5.5.12. Json-prettifying + slightly changed which caused the test to fail. + + +3.2.1 (2014-05-03) +------------------ + +* Minor tweak to make the unittests run with the latest hhvm on travis. +* Updated timezone definitions. +* Updated copyright links to point to http://sabre.io/ + + +3.2.0 (2014-04-02) +------------------ + +* Now hhvm compatible! +* The validator can now detect a _lot_ more problems. Many rules for both + iCalendar and vCard were added. +* Added: bin/generate_vcards, a utility to generate random vcards for testing + purposes. Patches are welcome to add more data. +* Updated: Windows timezone mapping to latest version from unicode.org +* Changed: The timezone maps are now loaded in from external files, in + lib/Sabre/VObject/timezonedata. +* Added: Fixing badly encoded URL's from google contacts vcards. +* Fixed: Issue #68. Couldn't decode properties ending in a colon. +* Fixed: Issue #72. RecurrenceIterator should respect timezone in the UNTIL + clause. +* Fixed: Issue #67. BYMONTH limit on DAILY recurrences. +* Fixed: Issue #26. Return a more descriptive error when coming across broken + BYDAY rules. +* Fixed: Issue #28. Incorrect timezone detection for some timezones. +* Fixed: Issue #70. Casting a parameter with a null value to string would fail. +* Added: Support for rfc6715 and rfc6474. +* Added: Support for DateTime objects in the VCard DATE-AND-OR-TIME property. +* Added: UUIDUtil, for easily creating unique identifiers. +* Fixed: Issue #83. Creating new VALUE=DATE objects using php's DateTime. +* Fixed: Issue #86. Don't go into an infinite loop when php errors are + disabled and an invalid file is read. + + +3.1.4 (2014-03-30) +------------------ + +* Fixed: Issue #87: Several compatibility fixes related to timezone handling + changes in PHP 5.5.10. + + +3.1.3 (2013-10-02) +------------------ + +* Fixed: Support from properties from draft-daboo-valarm-extensions-04. Issue + #56. +* Fixed: Issue #54. Parsing a stream of multiple vcards separated by more than + one newline. Thanks @Vedmak for the patch. +* Fixed: Serializing vcard 2.1 parameters with no name caused a literal '1' to + be inserted. +* Added: VCardConverter removed properties that are no longer supported in vCard + 4.0. +* Added: vCards with a minimum number of values (such as N), but don't have that + many, are now automatically padded with empty components. +* Added: The vCard validator now also checks for a minimum number of components, + and has the ability to repair these. +* Added: Some support for vCard 2.1 in the VCard converter, to upgrade to vCard + 3.0 or 4.0. +* Fixed: Issue 60 Use Document::$componentMap when instantiating the top-level + VCalendar and VCard components. +* Fixed: Issue 62: Parsing iCalendar parameters with no value. +* Added: --forgiving option to vobject utility. +* Fixed: Compound properties such as ADR were not correctly split up in vCard + 2.1 quoted printable-encoded properties. +* Fixed: Issue 64: Encoding of binary properties of converted vCards. Thanks + @DominikTo for the patch. + + +3.1.2 (2013-08-13) +------------------ + +* Fixed: Setting correct property group on VCard conversion + + +3.1.1 (2013-08-02) +------------------ + +* Fixed: Issue #53. A regression in RecurrenceIterator. + + +3.1.0 (2013-07-27) +------------------ + +* Added: bad-ass new cli debugging utility (in bin/vobject). +* Added: jCal and jCard parser. +* Fixed: URI properties should not escape ; and ,. +* Fixed: VCard 4 documents now correctly use URI as a default value-type for + PHOTO and others. BINARY no longer exists in vCard 4. +* Added: Utility to convert between 2.1, 3.0 and 4.0 vCards. +* Added: You can now add() multiple parameters to a property in one call. +* Added: Parameter::has() for easily checking if a parameter value exists. +* Added: VCard::preferred() to find a preferred email, phone number, etc for a + contact. +* Changed: All $duration properties are now public. +* Added: A few validators for iCalendar documents. +* Fixed: Issue #50. RecurrenceIterator gives incorrect result when exception + events are out of order in the iCalendar file. +* Fixed: Issue #48. Overridden events in the recurrence iterator that were past + the UNTIL date were ignored. +* Added: getDuration for DURATION values such as TRIGGER. Thanks to + @SimonSimCity. +* Fixed: Issue #52. vCard 2.1 parameters with no name may lose values if there's + more than 1. Thanks to @Vedmak. + + +3.0.0 (2013-06-21) +------------------ + +* Fixed: includes.php file was still broken. Our tool to generate it had some + bugs. + + +3.0.0-beta4 (2013-06-21) +------------------------ + +* Fixed: includes.php was no longer up to date. + + +3.0.0-beta3 (2013-06-17) +------------------------ + +* Added: OPTION_FORGIVING now also allows slashes in property names. +* Fixed: DateTimeParser no longer fails on dates with years < 1000 & > 4999 +* Fixed: Issue 36: Workaround for the recurrenceiterator and caldav events with + a missing base event. +* Fixed: jCard encoding of TIME properties. +* Fixed: jCal encoding of REQUEST-STATUS, GEO and PERIOD values. + + +3.0.0-beta2 (2013-06-10) +------------------------ + +* Fixed: Corrected includes.php file. +* Fixed: vCard date-time parser supported extended-format dates as well. +* Changed: Properties have been moved to an ICalendar or VCard directory. +* Fixed: Couldn't parse vCard 3 extended format dates and times. +* Fixed: Couldn't export jCard DATE values correctly. +* Fixed: Recursive loop in ICalendar\DateTime property. + + +3.0.0-beta1 (2013-06-07) +------------------------ + +* Added: jsonSerialize() for creating jCal and jCard documents. +* Added: helper method to parse vCard dates and times. +* Added: Specialized classes for FLOAT, LANGUAGE-TAG, TIME, TIMESTAMP, + DATE-AND-OR-TIME, CAL-ADDRESS, UNKNOWN and UTC-OFFSET properties. +* Removed: CommaSeparatedText property. Now included into Text. +* Fixed: Multiple parameters with the same name are now correctly encoded. +* Fixed: Parameter values containing a comma are now enclosed in double-quotes. +* Fixed: Iterating parameter values should now fully work as expected. +* Fixed: Support for vCard 2.1 nameless parameters. +* Changed: $valueMap, $componentMap and $propertyMap now all use fully-qualified + class names, so they are actually overridable. +* Fixed: Updating DATE-TIME to DATE values now behaves like expected. + + +3.0.0-alpha4 (2013-05-31) +------------------------- + +* Added: It's now possible to send parser options to the splitter classes. +* Added: A few tweaks to improve component and property creation. + + +3.0.0-alpha3 (2013-05-13) +------------------------- + +* Changed: propertyMap, valueMap and componentMap are now static properties. +* Changed: Component::remove() will throw an exception when trying to a node + that's not a child of said component. +* Added: Splitter objects are now faster, line numbers are accurately reported + and use less memory. +* Added: MimeDir parser can now continue parsing with the same stream buffer. +* Fixed: vobjectvalidate.php is operational again. +* Fixed: \r is properly stripped in text values. +* Fixed: QUOTED-PRINTABLE is now correctly encoded as well as encoded, for + vCards 2.1. +* Fixed: Parser assumes vCard 2.1, if no version was supplied. + + +3.0.0-alpha2 (2013-05-22) +------------------------- + +* Fixed: vCard URL properties were referencing a non-existant class. + + +3.0.0-alpha1 (2013-05-21) +------------------------- + +* Fixed: Now correctly dealing with escaping of properties. This solves the + problem with double-backslashes where they don't belong. +* Added: Easy support for properties with more than one value, using setParts + and getParts. +* Added: Support for broken 2.1 vCards produced by microsoft. +* Added: Automatically decoding quoted-printable values. +* Added: Automatically decoding base64 values. +* Added: Decoding RFC6868 parameter values (uses ^ as an escape character). +* Added: Fancy new MimeDir parser that can also parse streams. +* Added: Automatically mapping many, many properties to a property-class with + specialized API's. +* Added: remove() method for easily removing properties and sub-components + components. +* Changed: Components, Properties and Parameters can no longer be created with + Component::create, Property::create and Parameter::create. They must instead + be created through the root component. (A VCalendar or VCard object). +* Changed: API for DateTime properties has slightly changed. +* Changed: the ->value property is now protected everywhere. Use getParts() and + getValue() instead. +* BC Break: No support for mac newlines (\r). Never came across these anyway. +* Added: add() method to the Property class. +* Added: It's now possible to easy set multi-value properties as arrays. +* Added: When setting date-time properties you can just pass PHP's DateTime + object. +* Added: New components automatically get a bunch of default properties, such as + VERSION and CALSCALE. +* Added: You can add new sub-components much quicker with the magic setters, and + add() method. + + +2.1.7 (2015-01-21) +------------------ + +* Fixed: Issue #94, a workaround for bad escaping of ; and , in compound + properties. It's not a full solution, but it's an improvement for those + stuck in the 2.1 versions. + + +2.1.6 (2014-12-10) +------------------ + +* Fixed: Minor change to make sure that unittests succeed on every PHP version. + + +2.1.5 (2014-06-03) +------------------ + +* Fixed: #94: Better parameter escaping. +* Changed: Documentation cleanups. + + +2.1.4 (2014-03-30) +------------------ + +* Fixed: Issue #87: Several compatibility fixes related to timezone handling + changes in PHP 5.5.10. + + +2.1.3 (2013-10-02) +------------------ + +* Fixed: Issue #55. \r must be stripped from property values. +* Fixed: Issue #65. Putting quotes around parameter values that contain a colon. + + +2.1.2 (2013-08-02) +------------------ + +* Fixed: Issue #53. A regression in RecurrenceIterator. + + +2.1.1 (2013-07-27) +------------------ + +* Fixed: Issue #50. RecurrenceIterator gives incorrect result when exception + events are out of order in the iCalendar file. +* Fixed: Issue #48. Overridden events in the recurrence iterator that were past + the UNTIL date were ignored. + + +2.1.0 (2013-06-17) +------------------ + +* This version is fully backwards compatible with 2.0.\*. However, it contains a + few new API's that mimic the VObject 3 API. This allows it to be used a + 'bridge' version. Specifically, this new version exists so SabreDAV 1.7 and + 1.8 can run with both the 2 and 3 versions of this library. +* Added: Property\DateTime::hasTime(). +* Added: Property\MultiDateTime::hasTime(). +* Added: Property::getValue(). +* Added: Document class. +* Added: Document::createComponent and Document::createProperty. +* Added: Parameter::getValue(). + + +2.0.7 (2013-03-05) +------------------ + +* Fixed: Microsoft re-uses their magic numbers for different timezones, + specifically id 2 for both Sarajevo and Lisbon). A workaround was added to + deal with this. + + +2.0.6 (2013-02-17) +------------------ + +* Fixed: The reader now properly parses parameters without a value. + + +2.0.5 (2012-11-05) +------------------ + +* Fixed: The FreeBusyGenerator is now properly using the factory methods for + creation of components and properties. + + +2.0.4 (2012-11-02) +------------------ + +* Added: Known Lotus Notes / Domino timezone id's. + + +2.0.3 (2012-10-29) +------------------ + +* Added: Support for 'GMT+????' format in TZID's. +* Added: Support for formats like SystemV/EST5EDT in TZID's. +* Fixed: RecurrenceIterator now repairs recurrence rules where UNTIL < DTSTART. +* Added: Support for BYHOUR in FREQ=DAILY (@hollodk). +* Added: Support for BYHOUR and BYDAY in FREQ=WEEKLY. + + +2.0.2 (2012-10-06) +------------------ + +* Added: includes.php file, to load the entire library in one go. +* Fixed: A problem with determining alarm triggers for TODO's. + + +2.0.1 (2012-09-22) +------------------ + +* Removed: Element class. It wasn't used. +* Added: Basic validation and repair methods for broken input data. +* Fixed: RecurrenceIterator could infinitely loop when an INTERVAL of 0 was + specified. +* Added: A cli script that can validate and automatically repair vcards and + iCalendar objects. +* Added: A new 'Compound' property, that can automatically split up parts for + properties such as N, ADR, ORG and CATEGORIES. +* Added: Splitter classes, that can split up large objects (such as exports) + into individual objects (thanks @DominikTO and @armin-hackmann). +* Added: VFREEBUSY component, which allows easily checking wether timeslots are + available. +* Added: The Reader class now has a 'FORGIVING' option, which allows it to parse + properties with incorrect characters in the name (at this time, it just allows + underscores). +* Added: Also added the 'IGNORE_INVALID_LINES' option, to completely disregard + any invalid lines. +* Fixed: A bug in Windows timezone-id mappings for times created in Greenlands + timezone (sorry Greenlanders! I do care!). +* Fixed: DTEND was not generated correctly for VFREEBUSY reports. +* Fixed: Parser is at least 25% faster with real-world data. + + +2.0.0 (2012-08-08) +------------------ + +* VObject is now a separate project from SabreDAV. See the SabreDAV changelog + for version information before 2.0. +* New: VObject library now uses PHP 5.3 namespaces. +* New: It's possible to specify lists of parameters when constructing + properties. +* New: made it easier to construct the FreeBusyGenerator. + +[iTip]: http://tools.ietf.org/html/rfc5546 diff --git a/vendor/sabre/vobject/lib/Property/Float.php b/vendor/sabre/vobject/lib/Property/Float.php new file mode 100644 index 000000000..25bcd3db2 --- /dev/null +++ b/vendor/sabre/vobject/lib/Property/Float.php @@ -0,0 +1,104 @@ +<?php + +namespace Sabre\VObject\Property; + +use + Sabre\VObject\Property; + +/** + * Float property + * + * This object represents FLOAT values. These can be 1 or more floating-point + * numbers. + * + * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). + * @author Evert Pot (http://evertpot.com/) + * @license http://sabre.io/license/ Modified BSD License + */ +class Float extends Property { + + /** + * In case this is a multi-value property. This string will be used as a + * delimiter. + * + * @var string|null + */ + public $delimiter = ';'; + + /** + * Sets a raw value coming from a mimedir (iCalendar/vCard) file. + * + * This has been 'unfolded', so only 1 line will be passed. Unescaping is + * not yet done, but parameters are not included. + * + * @param string $val + * @return void + */ + public function setRawMimeDirValue($val) { + + $val = explode($this->delimiter, $val); + foreach($val as &$item) { + $item = (float)$item; + } + $this->setParts($val); + + } + + /** + * Returns a raw mime-dir representation of the value. + * + * @return string + */ + public function getRawMimeDirValue() { + + return implode( + $this->delimiter, + $this->getParts() + ); + + } + + /** + * Returns the type of value. + * + * This corresponds to the VALUE= parameter. Every property also has a + * 'default' valueType. + * + * @return string + */ + public function getValueType() { + + return "FLOAT"; + + } + + /** + * Returns the value, in the format it should be encoded for json. + * + * This method must always return an array. + * + * @return array + */ + public function getJsonValue() { + + $val = array_map( + function($item) { + + return (float)$item; + + }, + $this->getParts() + ); + + // Special-casing the GEO property. + // + // See: + // http://tools.ietf.org/html/draft-ietf-jcardcal-jcal-04#section-3.4.1.2 + if ($this->name==='GEO') { + return array($val); + } else { + return $val; + } + + } +} diff --git a/vendor/sabre/vobject/lib/Property/Integer.php b/vendor/sabre/vobject/lib/Property/Integer.php new file mode 100644 index 000000000..db000156f --- /dev/null +++ b/vendor/sabre/vobject/lib/Property/Integer.php @@ -0,0 +1,72 @@ +<?php + +namespace Sabre\VObject\Property; + +use + Sabre\VObject\Property; + +/** + * Integer property + * + * This object represents INTEGER values. These are always a single integer. + * They may be preceeded by either + or -. + * + * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). + * @author Evert Pot (http://evertpot.com/) + * @license http://sabre.io/license/ Modified BSD License + */ +class Integer extends Property { + + /** + * Sets a raw value coming from a mimedir (iCalendar/vCard) file. + * + * This has been 'unfolded', so only 1 line will be passed. Unescaping is + * not yet done, but parameters are not included. + * + * @param string $val + * @return void + */ + public function setRawMimeDirValue($val) { + + $this->setValue((int)$val); + + } + + /** + * Returns a raw mime-dir representation of the value. + * + * @return string + */ + public function getRawMimeDirValue() { + + return $this->value; + + } + + /** + * Returns the type of value. + * + * This corresponds to the VALUE= parameter. Every property also has a + * 'default' valueType. + * + * @return string + */ + public function getValueType() { + + return "INTEGER"; + + } + + /** + * Returns the value, in the format it should be encoded for json. + * + * This method must always return an array. + * + * @return array + */ + public function getJsonValue() { + + return array((int)$this->getValue()); + + } +} diff --git a/vendor/sabre/vobject/lib/RecurrenceIterator.php b/vendor/sabre/vobject/lib/RecurrenceIterator.php new file mode 100644 index 000000000..92ea03ffe --- /dev/null +++ b/vendor/sabre/vobject/lib/RecurrenceIterator.php @@ -0,0 +1,21 @@ +<?php + +namespace Sabre\VObject; + +use Sabre\VObject\Recur\EventIterator; + +/** + * RecurrenceIterator + * + * This class is deprecated. Use Sabre\VObject\Recur\EventIterator instead. + * This class will be removed from a future version. + * + * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). + * @author Evert Pot (http://evertpot.com/) + * @deprecated + * @license http://sabre.io/license Modified BSD License + */ +class RecurrenceIterator extends EventIterator { + + +} diff --git a/vendor/sabre/xml/.travis.yml b/vendor/sabre/xml/.travis.yml index 19a61a2c8..9bba4d451 100644 --- a/vendor/sabre/xml/.travis.yml +++ b/vendor/sabre/xml/.travis.yml @@ -4,6 +4,7 @@ php: - 5.5 - 5.6 - 7 + - nightly - hhvm matrix: @@ -11,10 +12,14 @@ matrix: sudo: false -cache: vendor +cache: + directories: + - $HOME/.composer/cache script: - ./bin/phpunit --configuration tests/phpunit.xml.dist - ./bin/sabre-cs-fixer fix . --dry-run --diff -before_script: composer install +before_script: + - phpenv config-rm xdebug.ini; true + - composer install diff --git a/vendor/sabre/xml/CHANGELOG.md b/vendor/sabre/xml/CHANGELOG.md index 3d8eb0fcb..a8085401b 100644 --- a/vendor/sabre/xml/CHANGELOG.md +++ b/vendor/sabre/xml/CHANGELOG.md @@ -1,6 +1,17 @@ ChangeLog ========= +1.4.2 (????-??-??) +------------------ + +* The `contextStack` in the Reader object is now correctly rolled back in + error conditions (@staabm). +* repeatingElements deserializer now still parses if a bare element name + without clark notation was given. +* `$elementMap` in the Reader now also supports bare element names. +* `Service::expect()` can now also work with bare element names. + + 1.4.1 (2016-03-12) ----------------- diff --git a/vendor/sabre/xml/lib/Deserializer/functions.php b/vendor/sabre/xml/lib/Deserializer/functions.php index fe88a6db8..2e5d877e9 100644 --- a/vendor/sabre/xml/lib/Deserializer/functions.php +++ b/vendor/sabre/xml/lib/Deserializer/functions.php @@ -14,7 +14,7 @@ use Sabre\Xml\Reader; * deserializer functions. */ -/* +/** * The 'keyValue' deserializer parses all child elements, and outputs them as * a "key=>value" array. * @@ -213,7 +213,7 @@ function valueObject(Reader $reader, $className, $namespace) { } -/* +/** * This deserializer helps you deserialize xml structures that look like * this: * @@ -240,6 +240,9 @@ function valueObject(Reader $reader, $className, $namespace) { */ function repeatingElements(Reader $reader, $childElementName) { + if ($childElementName[0] !== '{') { + $childElementName = '{}' . $childElementName; + } $result = []; foreach ($reader->parseGetElements() as $element) { diff --git a/vendor/sabre/xml/lib/Reader.php b/vendor/sabre/xml/lib/Reader.php index 7cba76c59..f35dc8537 100644 --- a/vendor/sabre/xml/lib/Reader.php +++ b/vendor/sabre/xml/lib/Reader.php @@ -142,7 +142,12 @@ class Reader extends XMLReader { // choice. See: // // https://bugs.php.net/bug.php?id=64230 - if (!@$this->read()) return false; + if (!@$this->read()) { + if (!is_null($elementMap)) { + $this->popContext(); + } + return false; + } while (true) { @@ -152,6 +157,9 @@ class Reader extends XMLReader { if ($errors) { libxml_clear_errors(); + if (!is_null($elementMap)) { + $this->popContext(); + } throw new LibXMLException($errors); } } @@ -170,6 +178,9 @@ class Reader extends XMLReader { $this->read(); break 2; case self::NONE : + if (!is_null($elementMap)) { + $this->popContext(); + } throw new ParseException('We hit the end of the document prematurely. This likely means that some parser "eats" too many elements. Do not attempt to continue parsing.'); default : // Advance to the next element @@ -282,8 +293,13 @@ class Reader extends XMLReader { */ function getDeserializerForElementName($name) { + if (!array_key_exists($name, $this->elementMap)) { - return ['Sabre\\Xml\\Element\\Base', 'xmlDeserialize']; + if (substr($name, 0, 2) == '{}' && array_key_exists(substr($name, 2), $this->elementMap)) { + $name = substr($name, 2); + } else { + return ['Sabre\\Xml\\Element\\Base', 'xmlDeserialize']; + } } $deserializer = $this->elementMap[$name]; diff --git a/vendor/sabre/xml/lib/Service.php b/vendor/sabre/xml/lib/Service.php index b2603a4c7..09ee341cf 100644 --- a/vendor/sabre/xml/lib/Service.php +++ b/vendor/sabre/xml/lib/Service.php @@ -151,8 +151,14 @@ class Service { $r->contextUri = $contextUri; $r->xml($input); + $rootElementName = (array)$rootElementName; + + foreach ($rootElementName as &$rEl) { + if ($rEl[0] !== '{') $rEl = '{}' . $rEl; + } + $result = $r->parse(); - if (!in_array($result['name'], (array)$rootElementName, true)) { + if (!in_array($result['name'], $rootElementName, true)) { throw new ParseException('Expected ' . implode(' or ', (array)$rootElementName) . ' but received ' . $result['name'] . ' as the root element'); } return $result['value']; -- cgit v1.2.3 From aab9766c53e42c3141d0497fce78977d262efbc1 Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Sun, 29 May 2016 00:33:28 +0200 Subject: missed some files --- vendor/CHANGELOG.md | 2311 ++++++++++++++++++++ vendor/LICENSE | 27 + vendor/README.md | 36 + vendor/examples/addressbookserver.php | 57 + vendor/examples/calendarserver.php | 76 + vendor/examples/fileserver.php | 56 + vendor/examples/groupwareserver.php | 101 + vendor/examples/minimal.php | 20 + vendor/examples/sql/mysql.addressbooks.sql | 28 + vendor/examples/sql/mysql.calendars.sql | 76 + vendor/examples/sql/mysql.locks.sql | 12 + vendor/examples/sql/mysql.principals.sql | 20 + vendor/examples/sql/mysql.propertystorage.sql | 9 + vendor/examples/sql/mysql.users.sql | 9 + vendor/examples/sql/pgsql.addressbooks.sql | 44 + vendor/examples/sql/pgsql.calendars.sql | 105 + vendor/examples/sql/pgsql.locks.sql | 19 + vendor/examples/sql/pgsql.principals.sql | 30 + vendor/examples/sql/pgsql.propertystorage.sql | 13 + vendor/examples/sql/pgsql.users.sql | 14 + vendor/examples/sql/sqlite.addressbooks.sql | 28 + vendor/examples/sql/sqlite.calendars.sql | 76 + vendor/examples/sql/sqlite.locks.sql | 12 + vendor/examples/sql/sqlite.principals.sql | 20 + vendor/examples/sql/sqlite.propertystorage.sql | 10 + vendor/examples/sql/sqlite.users.sql | 9 + vendor/examples/webserver/apache2_htaccess.conf | 16 + vendor/examples/webserver/apache2_vhost.conf | 29 + vendor/examples/webserver/apache2_vhost_cgi.conf | 21 + vendor/sabre/dav/bin/migrateto17.php | 284 --- vendor/sabre/dav/examples/addressbookserver.php | 57 - .../sabre/dav/examples/sql/mysql.addressbook.sql | 28 - vendor/sabre/dav/examples/sql/mysql.calendars.sql | 76 - vendor/sabre/dav/examples/sql/mysql.locks.sql | 12 - vendor/sabre/dav/examples/sql/mysql.principals.sql | 20 - vendor/sabre/dav/examples/sql/mysql.users.sql | 9 - .../sabre/dav/examples/sql/pgsql.addressbook.sql | 52 - vendor/sabre/dav/examples/sql/pgsql.calendars.sql | 105 - vendor/sabre/dav/examples/sql/pgsql.locks.sql | 19 - vendor/sabre/dav/examples/sql/pgsql.principals.sql | 30 - vendor/sabre/dav/examples/sql/pgsql.users.sql | 14 - .../sabre/dav/examples/sql/sqlite.addressbooks.sql | 28 - vendor/sabre/dav/examples/sql/sqlite.calendars.sql | 76 - vendor/sabre/dav/examples/sql/sqlite.locks.sql | 12 - .../sabre/dav/examples/sql/sqlite.principals.sql | 20 - vendor/sabre/dav/examples/sql/sqlite.users.sql | 9 - .../dav/examples/webserver/apache2_htaccess.conf | 16 - .../dav/examples/webserver/apache2_vhost.conf | 29 - .../dav/examples/webserver/apache2_vhost_cgi.conf | 21 - vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php | 48 - vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php | 72 - .../tests/Sabre/CalDAV/ShareableCalendarTest.php | 60 - vendor/sabre/dav/tests/phpunit.xml | 40 - vendor/sabre/vobject/ChangeLog.md | 563 ----- vendor/sabre/vobject/lib/Property/Float.php | 104 - vendor/sabre/vobject/lib/Property/Integer.php | 72 - vendor/sabre/vobject/lib/RecurrenceIterator.php | 21 - 57 files changed, 3284 insertions(+), 1897 deletions(-) create mode 100644 vendor/CHANGELOG.md create mode 100644 vendor/LICENSE create mode 100644 vendor/README.md create mode 100644 vendor/examples/addressbookserver.php create mode 100644 vendor/examples/calendarserver.php create mode 100644 vendor/examples/fileserver.php create mode 100644 vendor/examples/groupwareserver.php create mode 100644 vendor/examples/minimal.php create mode 100644 vendor/examples/sql/mysql.addressbooks.sql create mode 100644 vendor/examples/sql/mysql.calendars.sql create mode 100644 vendor/examples/sql/mysql.locks.sql create mode 100644 vendor/examples/sql/mysql.principals.sql create mode 100644 vendor/examples/sql/mysql.propertystorage.sql create mode 100644 vendor/examples/sql/mysql.users.sql create mode 100644 vendor/examples/sql/pgsql.addressbooks.sql create mode 100644 vendor/examples/sql/pgsql.calendars.sql create mode 100644 vendor/examples/sql/pgsql.locks.sql create mode 100644 vendor/examples/sql/pgsql.principals.sql create mode 100644 vendor/examples/sql/pgsql.propertystorage.sql create mode 100644 vendor/examples/sql/pgsql.users.sql create mode 100644 vendor/examples/sql/sqlite.addressbooks.sql create mode 100644 vendor/examples/sql/sqlite.calendars.sql create mode 100644 vendor/examples/sql/sqlite.locks.sql create mode 100644 vendor/examples/sql/sqlite.principals.sql create mode 100644 vendor/examples/sql/sqlite.propertystorage.sql create mode 100644 vendor/examples/sql/sqlite.users.sql create mode 100644 vendor/examples/webserver/apache2_htaccess.conf create mode 100644 vendor/examples/webserver/apache2_vhost.conf create mode 100644 vendor/examples/webserver/apache2_vhost_cgi.conf delete mode 100755 vendor/sabre/dav/bin/migrateto17.php delete mode 100644 vendor/sabre/dav/examples/addressbookserver.php delete mode 100644 vendor/sabre/dav/examples/sql/mysql.addressbook.sql delete mode 100644 vendor/sabre/dav/examples/sql/mysql.calendars.sql delete mode 100644 vendor/sabre/dav/examples/sql/mysql.locks.sql delete mode 100644 vendor/sabre/dav/examples/sql/mysql.principals.sql delete mode 100644 vendor/sabre/dav/examples/sql/mysql.users.sql delete mode 100644 vendor/sabre/dav/examples/sql/pgsql.addressbook.sql delete mode 100644 vendor/sabre/dav/examples/sql/pgsql.calendars.sql delete mode 100644 vendor/sabre/dav/examples/sql/pgsql.locks.sql delete mode 100644 vendor/sabre/dav/examples/sql/pgsql.principals.sql delete mode 100644 vendor/sabre/dav/examples/sql/pgsql.users.sql delete mode 100644 vendor/sabre/dav/examples/sql/sqlite.addressbooks.sql delete mode 100644 vendor/sabre/dav/examples/sql/sqlite.calendars.sql delete mode 100644 vendor/sabre/dav/examples/sql/sqlite.locks.sql delete mode 100644 vendor/sabre/dav/examples/sql/sqlite.principals.sql delete mode 100644 vendor/sabre/dav/examples/sql/sqlite.users.sql delete mode 100644 vendor/sabre/dav/examples/webserver/apache2_htaccess.conf delete mode 100644 vendor/sabre/dav/examples/webserver/apache2_vhost.conf delete mode 100644 vendor/sabre/dav/examples/webserver/apache2_vhost_cgi.conf delete mode 100644 vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php delete mode 100644 vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php delete mode 100644 vendor/sabre/dav/tests/Sabre/CalDAV/ShareableCalendarTest.php delete mode 100644 vendor/sabre/dav/tests/phpunit.xml delete mode 100644 vendor/sabre/vobject/ChangeLog.md delete mode 100644 vendor/sabre/vobject/lib/Property/Float.php delete mode 100644 vendor/sabre/vobject/lib/Property/Integer.php delete mode 100644 vendor/sabre/vobject/lib/RecurrenceIterator.php diff --git a/vendor/CHANGELOG.md b/vendor/CHANGELOG.md new file mode 100644 index 000000000..079650965 --- /dev/null +++ b/vendor/CHANGELOG.md @@ -0,0 +1,2311 @@ +ChangeLog +========= + +3.2.0-beta1 (2016-05-20) +------------------------ + +* #833: Calendars throw exceptions when the sharing plugin is not enabled. +* #834: Return vCards exactly as they were stored if we don't need to convert + in between versions. + + +3.2.0-alpha1 (2016-05-09) +------------------------- + +* Database changes for CalDAV. If you are using the CalDAV PDO backends, you + must migrate. Run `./bin/migrateto32.php` for more info. +* Support for WebDAV Resource Sharing, an upcoming standard. +* Added support for sharing in the CalDAV PDO backend! Users can now invite + others to their calendar and give them read/read-write access! +* #397: Support for PSR-3. You can now log exceptions with your favourite + psr3-compatible logging tool. +* #825: Actual proper, tested support for PostgreSQL. We require version 9.5. +* Removed database migration script for sabre/dav 1.7. To update from that + version you now first need to update to sabre/dav 3.1. +* Removed deprecated function: `Sabre\DAV\Auth\Plugin::getCurrentUser()`. +* #774: Fixes for getting free disk space on Windows. +* #803: Major changes in the sharing API. If you were using an old sabre/dav + sharing api, head to the website for more detailed migration notes. +* #657: Support for optional auth using `{DAV:}unauthorized` and `{DAV:}all` + privileges. This allows you to assign a privilege to a resource, allowing + non-authenticated users to access it. For instance, this could allow you + to create a public read-only collection. +* #812 #814: ICS/VCF exporter now includes a more useful filename in its + `Content-Disposition` header. (@Xenopathic). +* #801: BC break: If you were using the `Href` object before, it's behavior + now changed a bit, and `LocalHref` was added to replace the old, default + behavior of `Href`. See the migration doc for more info. +* Removed `Sabre\DAVACL\Plugin::$allowAccessToNodesWithoutACL` setting. + Instead, you can provide a set of default ACL rules with + `Sabre\DAVACL\Plugin::setDefaultAcl()`. +* Introduced `Sabre\DAVACL\ACLTrait` which contains a default implementation + of `Sabre\DAV\IACL` with some sane defaults. We're using this trait all over + the place now, reducing the amount of boilerplate. +* Plugins can now control the "Supported Privilege Set". +* Added Sharing, ICSExport and VCFExport plugins to `groupwareserver.php` + example. +* The `{DAV:}all` privilege is now no longer abstract, so it can be assigned + directly. We're using the `{DAV:}all` privilege now in a lot of cases where + we before assigned both `{DAV:}read` and `{DAV:}write`. +* Resources that are not collections no longer support the `{DAV:}bind` and + `{DAV:}unbind` privileges. +* Corrected the CalDAV-scheduling related privileges. +* Doing an `UNLOCK` no longer requires the `{DAV:}write-content` privilege. +* Added a new `getPrincipalByUri` plugin event. Allowing plugins to request + quickly where a principal lives on a server. +* Renamed `phpunit.xml` to `phpunit.xml.dist` to make local modifications easy. +* Functionality from `IShareableCalendar` is merged into `ISharedCalendar`. +* #751: Fixed XML responses from failing `MKCOL` requests. +* #600: Support for `principal-match` ACL `REPORT`. +* #599: Support for `acl-principal-prop-set` ACL `REPORT`. +* #798: Added an index on `firstoccurence` field in MySQL CalDAV backend. This + should speed up common calendar-query requests. +* #759: DAV\Client is now able to actually correctly resolve relative urls. +* #671: We are no longer checking the `read-free-busy` privilege on individual + calendars during freebusy operations in the scheduling plugin. Instead, we + check the `schedule-query-freebusy` privilege on the target users' inbox, + which validates access for the entire account, per the spec. +* The zip release ships with [sabre/vobject 4.1.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.1.3 (2016-04-06) +------------------ + +* Set minimum libxml version to 2.7.0 in `composer.json`. +* #805: It wasn't possible to create calendars that hold events, journals and + todos using MySQL, because the `components` column was 1 byte too small. +* The zip release ships with [sabre/vobject 4.1.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.1.2 (2016-03-12) +------------------ + +* #784: Sync logs for address books were not correctly cleaned up after + deleting them. +* #787: Cannot use non-seekable stream-wrappers with range requests. +* Faster XML parsing and generating due to sabre/xml update. +* #793: The Sqlite schema is now more strict and more similar to the MySQL + schema. This solves a problem within Baikal. +* The zip release ships with [sabre/vobject 4.0.3][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.1.1 (2016-01-25) +------------------ + +* #755: The brower plugin and some operations would break when scheduling and + delegation would both be enabled. +* #757: A bunch of unittest improvements (@jakobsack). +* The zip release ships with [sabre/vobject 4.0.2][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. + + +3.1.0 (2016-01-06) +------------------ + +* Better error message when the browser plugin is not enabled. +* Added a super minimal server example. +* #730: Switched all mysql tables to `utf8mb4` character set, allowing you to + use emoji in some tables where you couldn't before. +* #710: Provide an Auth backend that acts as a helper for people implementing + OAuth2 Bearer token. (@fkooman). +* #729: Not all calls to `Sabre\DAV\Tree::getChildren()` were properly cached. +* #727: Added another workaround to make CalDAV work for Windows 10 clients. +* #742: Fixes to make sure that vobject 4 is correctly supported. +* #726: Better error reporting in `Client::propPatch`. We're now throwing + exceptions. +* #608: When a HTTP error is triggered during `Client:propFind`, we're now + throwing `Sabre\HTTP\ClientHttpException` instead of `Sabre\DAV\Exception`. + This new exception contains a LOT more information about the problem. +* #721: Events are now handled in the correct order for `COPY` requests. + Before this subtle bugs could appear that could cause data-loss. +* #747: Now throwing exceptions and setting the HTTP status to 500 in subtle + cases where no other plugin set a correct HTTP status. +* #686: Corrected PDO principal backend's findByURI for email addresses that + don't match the exact capitalization. +* #512: The client now has it's own `User-Agent`. +* #720: Some browser improvements. +* The zip release ships with [sabre/vobject 4.0.1][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. + + +3.1.0-alpha2 (2015-09-05) +------------------------- + +* Massive calendars and addressbooks should see a big drop in peak memory + usage. +* Fixed a privilege bug in the availability system. +* #697: Added a "tableName" member to the PropertyStorage PDO backend. (@Frzk). +* #699: PostgreSQL fix for the Locks PDO backend. (@TCKnet) +* Removed the `simplefsserver.php` example file. It's not simple enough. +* #703: PropPatch in client is not correctly encoded. +* #709: Throw exception when running into empty + `supported-calendar-component-set`. +* #711: Don't trigger deserializers for empty elements in `{DAV:}prop`. This + fixes issues when using sabre/dav as a client. +* The zip release ships with [sabre/vobject 4.0.0-alpha2][vobj], + [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. + + +3.1.0-alpha1 (2015-07-19) +------------------------- + +* Now requires PHP 5.5 +* Upgraded to vobject 4, which is a lot faster. +* Support for PHP 7. +* #690: Support for `calendar-availability`, draft 05. + [reference][calendar-availability]. +* #691: Workaround for broken Windows Phone client. +* The zip release ships with [sabre/vobject 4.0.0-alpha1][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. + + +3.0.9 (2016-04-06) +------------------ + +* Set minimum libxml version to 2.7.0 in `composer.json`. +* #727: Added another workaround to make CalDAV work for Windows 10 clients. +* #805: It wasn't possible to create calendars that hold events, journals and + todos using MySQL, because the `components` column was 1 byte too small. +* The zip release ships with [sabre/vobject 3.5.1][vobj], + [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.0.8 (2016-03-12) +------------------ + +* #784: Sync logs for address books were not correctly cleaned up after + deleting them. +* #787: Cannot use non-seekable stream-wrappers with range requests. +* Faster XML parsing and generating due to sabre/xml update. +* The zip release ships with [sabre/vobject 3.5.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.0.7 (2016-01-12) +------------------ + +* #752: PHP 7 support for 3.0 branch. (@DeepDiver1975) +* The zip release ships with [sabre/vobject 3.5.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. + + +3.0.6 (2016-01-04) +------------------ + +* #730: Switched all mysql tables to `utf8mb4` character set, allowing you to + use emoji in some tables where you couldn't before. +* #729: Not all calls to `Sabre\DAV\Tree::getChildren()` were properly cached. +* #734: Return `418 I'm a Teapot` when generating a multistatus response that + has resources with no returned properties. +* #740: Bugs in `migrate20.php` script. +* The zip release ships with [sabre/vobject 3.4.8][vobj], + [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. + + +3.0.5 (2015-09-15) +------------------ + +* #704: Fixed broken uri encoding in multistatus responses. This affected + at least CyberDuck, but probably also others. +* The zip release ships with [sabre/vobject 3.4.7][vobj], +* The zip release ships with [sabre/vobject 3.4.7][vobj], + [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. + + +3.0.4 (2015-09-06) +------------------ + +* #703: PropPatch in client is not correctly encoded. +* #709: Throw exception when running into empty + `supported-calendar-component-set`. +* #711: Don't trigger deserializers for empty elements in `{DAV:}prop`. This + fixes issues when using sabre/dav as a client. +* #705: A `MOVE` request that gets prevented from deleting the source resource + will still remove the target resource. Now all events are triggered before + any destructive operations. +* The zip release ships with [sabre/vobject 3.4.7][vobj], + [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. + + +3.0.3 (2015-08-06) +------------------ + +* #700: Digest Auth fails on `HEAD` requests. +* Fixed example files to no longer use now-deprecated realm argument. +* The zip release ships with [sabre/vobject 3.4.6][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. + + +3.0.2 (2015-07-21) +------------------ + +* #657: Migration script would break when coming a cross an iCalendar object + with no UID. +* #691: Workaround for broken Windows Phone client. +* Fixed a whole bunch of incorrect php docblocks. +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. + + +3.0.1 (2015-07-02) +------------------ + +* #674: Postgres sql file fixes. (@davesouthey) +* #677: Resources with the name '0' would not get retrieved when using + `Depth: infinity` in a `PROPFIND` request. +* #680: Fix 'autoprefixing' of dead `{DAV:}href` properties. +* #675: NTLM support in DAV\Client. (@k42b3) +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. + + +3.0.0 (2015-06-02) +------------------ + +* No changes since last beta. +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. + + +3.0.0-beta3 (2015-05-29) +------------------------ + +* Fixed deserializing href properties with no value. +* Fixed deserializing `{DAV:}propstat` without a `{DAV:}prop`. +* #668: More information about vcf-export-plugin in browser plugin. +* #669: Add export button to browser plugin for address books. (@mgee) +* #670: multiget report hrefs were not decoded. +* The zip release ships with [sabre/vobject 3.4.4][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. + + +3.0.0-beta2 (2015-05-27) +------------------------ + +* A node's properties should not overwrite properties that were already set. +* Some uris were not correctly encoded in notifications. +* The zip release ships with [sabre/vobject 3.4.4][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. + + +3.0.0-beta1 (2015-05-25) +------------------------ + +* `migrate22.php` is now called `migrate30.php`. +* Using php-cs-fixer for automated coding standards enforcement and fixing. +* #660: principals could break html output. +* #662: Fixed several bugs in the `share` request parser. +* #665: Fix a bug in serialization of complex properties in the proppatch + request in the client. +* #666: expand-property report did not correctly prepend the base uri when + generating uris, this caused delegation to break. +* #659: Don't throw errors when when etag-related checks are done on + collections. +* Fully supporting the updated `Prefer` header syntax, as defined in + [rfc7240][rfc7240]. +* The zip release ships with [sabre/vobject 3.4.3][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. + + +3.0.0-alpha1 (2015-05-19) +------------------------- + +* It's now possible to get all property information from files using the + browser plugin. +* Browser plugin will now show a 'calendar export' button when the + ics-export plugin is enabled. +* Some nodes that by default showed the current time as their last + modification time, now no longer has a last modification time. +* CardDAV namespace was missing from default namespaceMap. +* #646: Properties can now control their own HTML output in the browser plugin. +* #646: Nicer HTML output for the `{DAV:}acl` property. +* Browser plugin no longer shows a few properties that take up a lot of space, + but are likely not really interesting for most users. +* #654: Added a collection, `Sabre\DAVACL\FS\HomeCollection` for automatically + creating a private home collection per-user. +* Changed all MySQL columns from `VARCHAR` to `VARBINARY` where possible. +* Improved older migration scripts a bit to allow easier testing. +* The zip release ships with [sabre/vobject 3.4.3][vobj], + [sabre/http 4.0.0-alpha3][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 0.4.3][xml]. + + +2.2.0-alpha4 (2015-04-13) +------------------------- + +* Complete rewrite of the XML system. We now use our own [sabre/xml][xml], + which has a much smarter XML Reader and Writer. +* BC Break: It's no longer possible to instantiate the Locks plugin without + a locks backend. I'm not sure why this ever made sense. +* Simplified the Locking system and fixed a bug related to if tokens checking + locks unrelated to the current request. +* `FSExt` Directory and File no longer do custom property storage. This + functionality is already covered pretty well by the `PropertyStorage` plugin, + so please switch. +* Renamed `Sabre\CardDAV\UserAddressBooks` to `Sabre\CardDAV\AddressBookHome` + to be more consistent with `CalendarHome` as well as the CardDAV + specification. +* `Sabre\DAV\IExtendedCollection` now receives a `Sabre\DAV\MkCol` object as + its second argument, and no longer receives seperate properties and + resourcetype arguments. +* `MKCOL` now integrates better with propertystorage plugins. +* #623: Remove need of temporary files when working with Range requests. + (@dratini0) +* The zip release ships with [sabre/vobject 3.4.2][vobj], + [sabre/http 4.0.0-alpha1][http], [sabre/event 2.0.1][evnt], + [sabre/uri 1.0.0][uri] and [sabre/xml 0.4.3][xml]. + + +2.2.0-alpha3 (2015-02-25) +------------------------- + +* Contains all the changes introduced between 2.1.2 and 2.1.3. +* The zip release ships with [sabre/vobject 3.4.2][vobj], + [sabre/http 4.0.0-alpha1][http], [sabre/event 2.0.1][evnt] and + [sabre/uri 1.0.0][uri]. + + +2.2.0-alpha2 (2015-01-09) +------------------------- + +* Renamed `Sabre\DAV\Auth\Backend\BackendInterface::requireAuth` to + `challenge`, which is a more correct and better sounding name. +* The zip release ships with [sabre/vobject 3.3.5][vobj], + [sabre/http 3.0.4][http], [sabre/event 2.0.1][evnt]. + + +2.2.0-alpha1 (2014-12-10) +------------------------- + +* The browser plugin now has a new page with information about your sabredav + server, and shows information about every plugin that's loaded in the + system. +* #191: The Authentication system can now support multiple authentication + backends. +* Removed: all `$tableName` arguments from every PDO backend. This was already + deprecated, but has now been fully removed. All of these have been replaced + with public properties. +* Deleted several classes that were already deprecated much earlier: + * `Sabre\CalDAV\CalendarRootNode` + * `Sabre\CalDAV\UserCalendars` + * `Sabre\DAV\Exception\FileNotFound` + * `Sabre\DAV\Locks\Backend\FS` + * `Sabre\DAV\PartialUpdate\IFile` + * `Sabre\DAV\URLUtil` +* Removed: `Sabre\DAV\Client::addTrustedCertificates` and + `Sabre\DAV\Client::setVerifyPeer`. +* Removed: `Sabre\DAV\Plugin::getPlugin()` can now no longer return plugins + based on its class name. +* Removed: `Sabre\DAVACL\Plugin::getPrincipalByEmail()`. +* #560: GuessContentType plugin will now set content-type to + `application/octet-stream` if a better content-type could not be determined. +* #568: Added a `componentType` argument to `ICSExportPlugin`, allowing you to + specifically fetch `VEVENT`, `VTODO` or `VJOURNAL`. +* #582: Authentication backend interface changed to be stateless. If you + implemented your own authentication backend, make sure you upgrade your class + to the latest API! +* #582: `Sabre\DAV\Auth\Plugin::getCurrentUser()` is now deprecated. Use + `Sabre\DAV\Auth\Plugin::getCurrentPrincipal()` instead. +* #193: Fix `Sabre\DAV\FSExt\Directory::getQuotaInfo()` on windows. + + +2.1.11 (2016-??-??) +------------------- + +* #805: It wasn't possible to create calendars that hold events, journals and + todos using MySQL, because the `components` column was 1 byte too small. + + +2.1.10 (2016-03-10) +------------------- + +* #784: Sync logs for address books were not correctly cleaned up after + deleting them. + + +2.1.9 (2016-01-25) +------------------ + +* #674: PHP7 support (@DeepDiver1975). +* The zip release ships with [sabre/vobject 3.5.0][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.8 (2016-01-04) +------------------ + +* #729: Fixed a caching problem in the Tree object. +* #740: Bugs in `migrate20.php` script. +* The zip release ships with [sabre/vobject 3.4.8][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.7 (2015-09-05) +------------------ + +* #705: A `MOVE` request that gets prevented from deleting the source resource + will still remove the target resource. Now all events are triggered before + any destructive operations. +* The zip release ships with [sabre/vobject 3.4.7][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.6 (2015-07-21) +------------------ + +* #657: Migration script would break when coming a cross an iCalendar object + with no UID. +* #691: Workaround for broken Windows Phone client. +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.5 (2015-07-11) +------------------ + +* #677: Resources with the name '0' would not get retrieved when using + `Depth: infinity` in a `PROPFIND` request. +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.4 (2015-05-25) +------------------ + +* #651: Double-encoded path in the browser plugin. Should fix a few broken + links in some setups. +* #650: Correctly cleaning up change info after deleting calendars (@ErrOrnAmE). +* #658: Updating `schedule-calendar-default-URL` does not work well, so we're + disabling it until there's a better fix. +* The zip release ships with [sabre/vobject 3.4.3][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.3 (2015-02-25) +------------------ + +* #586: `SCHEDULE-STATUS` should not contain a reason-phrase. +* #539: Fixed a bug related to scheduling in shared calendars. +* #595: Support for calendar-timezone in iCalendar exports. +* #581: findByUri would send empty prefixes to the principal backend (@soydeedo) +* #611: Escaping a bit more HTML output in the browser plugin. (@LukasReschke) +* #610: Don't allow discovery of arbitrary files using `..` in the browser + plugin (@LukasReschke). +* Browser plugin now shows quota properties. +* #612: PropertyStorage didn't delete properties from nodes when a node's + parents get deleted. +* #581: Fixed problems related to finding attendee information during + scheduling. +* The zip release ships with [sabre/vobject 3.4.2][vobj], + [sabre/http 3.0.4][http], and [sabre/event 2.0.1][evnt]. + + +2.1.2 (2014-12-10) +------------------ + +* #566: Another issue related to the migration script, which would cause + scheduling to not work well for events that were already added before the + migration. +* #567: Doing freebusy requests on accounts that had 0 calendars would throw + a `E_NOTICE`. +* #572: `HEAD` requests trigger a PHP warning. +* #579: Browser plugin can throw exception for a few resourcetypes that didn't + have an icon defined. +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 3.0.4][http], and [sabre/event 2.0.1][evnt]. + + +2.1.1 (2014-11-22) +------------------ + +* #561: IMip Plugin didn't strip mailto: from email addresses. +* #566: Migration process had 2 problems related to adding the `uid` field + to the `calendarobjects` table. +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. + + +2.1.0 (2014-11-19) +------------------ + +* #541: CalDAV PDO backend didn't respect overridden PDO table names. +* #550: Scheduling invites are no longer delivered into shared calendars. +* #554: `calendar-multiget` `REPORT` did not work on inbox items. +* #555: The `calendar-timezone` property is now respected for floating times + and all-day events in the `calendar-query`, `calendar-multiget` and + `free-busy-query` REPORTs. +* #555: The `calendar-timezone` property is also respected for scheduling + free-busy requests. +* #547: CalDAV system too aggressively 'corrects' incoming iCalendar data, and + as a result doesn't return an etag for common cases. +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. + + +2.1.0-alpha2 (2014-10-23) +------------------------- + +* Added: calendar-user-address-set to default principal search properties + list. This should fix iOS attendee autocomplete support. +* Changed: Moved all 'notifications' functionality from `Sabre\CalDAV\Plugin` + to a new plugin: `Sabre\CalDAV\Notifications\Plugin`. If you want to use + notifications-related functionality, just add this plugin. +* Changed: Accessing the caldav inbox, outbox or notification collection no + longer triggers getCalendarsForUser() on backends. +* #533: New invites are no longer delivered to taks-only calendars. +* #538: Added `calendarObjectChange` event. +* Scheduling speedups. +* #539: added `afterResponse` event. (@joserobleda) +* Deprecated: All the "tableName" constructor arguments for all the PDO + backends are now deprecated. They still work, but will be removed in the + next major sabredav version. Every argument that is now deprecated can now + be accessed as a public property on the respective backends. +* #529: Added getCalendarObjectByUID to PDO backend, speeding up scheduling + operations on large calendars. +* The zip release ships with [sabre/vobject 3.3.3][vobj], + [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. + + +2.1.0-alpha1 (2014-09-23) +------------------------- + +* Added: Support for [rfc6638][rfc6638], also known as CalDAV Scheduling. +* Added: Automatically converting between vCard 3, 4 and jCard using the + `Accept:` header, in CardDAV reports, and automatically converting from + jCard to vCard upon `PUT`. It's important to note that your backends _may_ + now recieve both vCard 3.0 and 4.0. +* Added: #444. Collections can now opt-in to support high-speed `MOVE`. +* Changed: PropertyStorage backends now have a `move` method. +* Added: `beforeMove`, and `afterMove` events. +* Changed: A few database changes for the CalDAV PDO backend. Make sure you + run `bin/migrate21.php` to upgrade your database schema. +* Changed: CalDAV backends have a new method: `getCalendarObjectByUID`. This + method MUST be implemented by all backends, but the `AbstractBackend` has a + simple default implementation for this. +* Changed: `Sabre\CalDAV\UserCalendars` has been renamed to + `Sabre\CalDAV\CalendarHome`. +* Changed: `Sabre\CalDAV\CalendarRootNode` has been renamed to + `Sabre\CalDAV\CalendarRoot`. +* Changed: The IMipHandler has been completely removed. With CalDAV scheduling + support, it is no longer needed. It's functionality has been replaced by + `Sabre\CalDAV\Schedule\IMipPlugin`, which can now send emails for clients + other than iCal. +* Removed: `Sabre\DAV\ObjectTree` and `Sabre\DAV\Tree\FileSystem`. All this + functionality has been merged into `Sabre\DAV\Tree`. +* Changed: PrincipalBackend now has a findByUri method. +* Changed: `PrincipalBackend::searchPrincipals` has a new optional `test` + argument. +* Added: Support for the `{http://calendarserver.org/ns/}email-address-set` + property. +* #460: PropertyStorage must move properties during `MOVE` requests. +* Changed: Restructured the zip distribution to be a little bit more lean + and consistent. +* #524: Full support for the `test="anyof"` attribute in principal-search + `REPORT`. +* #472: Always returning lock tokens in the lockdiscovery property. +* Directory entries in the Browser plugin are sorted by type and name. + (@aklomp) +* #486: It's now possible to return additional properties when an 'allprop' + PROPFIND request is being done. (@aklomp) +* Changed: Now return HTTP errors when an addressbook-query REPORT is done + on a uri that's not a vcard. This should help with debugging this common + mistake. +* Changed: `PUT` requests with a `Content-Range` header now emit a 400 status + instead of 501, as per RFC7231. +* Added: Browser plugin can now display the contents of the + `{DAV:}supported-privilege-set` property. +* Added: Now reporting `CALDAV:max-resource-size`, but we're not actively + restricting it yet. +* Changed: CalDAV plugin is now responsible for reporting + `CALDAV:supported-collation-set` and `CALDAV:supported-calendar-data` + properties. +* Added: Now reporting `CARDDAV:max-resource-size`, but we're not actively + restricting it yet. +* Added: Support for `CARDDAV:supported-collation-set`. +* Changed: CardDAV plugin is now responsible for reporting + `CARDDAV:supported-address-data`. This functionality has been removed from + the CardDAV PDO backend. +* When a REPORT is not supported, we now emit HTTP error 415, instead of 403. +* #348: `HEAD` requests now work wherever `GET` also works. +* Changed: Lower priority for the iMip plugins `schedule` event listener. +* Added: #523 Custom CalDAV backends can now mark any calendar as read-only. +* The zip release ships with [sabre/vobject 3.3.3][vobj], + [sabre/http 3.0.0][http], and [sabre/event 2.0.0][evnt]. + + +2.0.9 (2015-09-04) +------------------ + +* #705: A `MOVE` request that gets prevented from deleting the source resource + will still remove the target resource. Now all events are triggered before + any destructive operations. +* The zip release ships with [sabre/vobject 3.4.6][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + + +2.0.8 (2015-07-11) +------------------ + +* #677: Resources with the name '0' would not get retrieved when using + `Depth: infinity` in a `PROPFIND` request. +* The zip release ships with [sabre/vobject 3.3.5][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.7 (2015-05-25) +------------------ + +* #650: Correctly cleaning up change info after deleting calendars (@ErrOrnAmE). +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.6 (2014-12-10) +------------------ + +* Added `Sabre\CalDAV\CalendarRoot` as an alias for + `Sabre\CalDAV\CalendarRootNode`. The latter is going to be deprecated in 2.1, + so this makes it slightly easier to write code that works in both branches. +* #497: Making sure we're initializing the sync-token field with a value after + migration. +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.5 (2014-10-14) +------------------ + +* #514: CalDAV PDO backend didn't work when overriding the 'calendar changes' + database table name. +* #515: 304 status code was not being sent when checking preconditions. +* The zip release ships with [sabre/vobject 3.3.3][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.4 (2014-08-27) +------------------ + +* #483: typo in calendars creation for PostgreSQL. +* #487: Locks are now automatically removed after a node has been deleted. +* #496: Improve CalDAV and CardDAV sync when there is no webdav-sync support. +* Added: Automatically mapping internal sync-tokens to getctag. +* The zip release ships with [sabre/vobject 3.3.1][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.3 (2014-07-14) +------------------ + +* #474: Fixed PropertyStorage `pathFilter()`. +* #476: CSP policy incorrect, causing stylesheets to not load in the browser + plugin. +* #475: Href properties in the browser plugin sometimes included a backslash. +* #478: `TooMuchMatches` exception never worked. This was fixed, and we also + took this opportunity to rename it to `TooManyMatches`. +* The zip release ships with [sabre/vobject 3.2.4][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.2 (2014-06-12) +------------------ + +* #470: Fixed compatibility with PHP < 5.4.14. +* #467: Fixed a problem in `examples/calendarserver.php`. +* #466: All the postgresql sample files have been updated. +* Fixed: An error would be thrown if a client did a propfind on a node the + user didn't have access to. +* Removed: Old and broken example code from the `examples/` directory. +* The zip release ships with [sabre/vobject 3.2.3][vobj], + [sabre/http 2.0.3][http], and [sabre/event 1.0.1][evnt]. + + +2.0.1 (2014-05-28) +------------------ + +* #459: PROPFIND requests on Files with no Depth header would return a fatal + error. +* #464: A PROPFIND allprops request should not return properties with status + 404. +* The zip release ships with [sabre/vobject 3.2.2][vobj], + [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. + + +2.0.0 (2014-05-22) +------------------ + +* The zip release ships with [sabre/vobject 3.2.2][vobj], + [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. +* Fixed: #456: Issue in sqlite migration script. +* Updated: MySQL database schema optimized by using more efficient column types. +* Cleaned up browser design. + + +2.0.0-beta1 (2014-05-15) +------------------------- + +* The zip release ships with [sabre/vobject 3.2.2][vobj], + [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. +* BC Break: Property updating and fetching got refactored. Read the [migration + document][mi20] for more information. This allows for creation of a generic + property storage, and other property-related functionality that was not + possible before. +* BC Break: Removed `propertyUpdate`, `beforeGetProperties` and + `afterGetProperties` events. +* Fixed: #413: Memory optimizations for the CardDAV PDO backend. +* Updated: Brand new browser plugin with more debugging features and a design + that is slightly less painful. +* Added: Support for the `{DAV:}supported-method-set` property server-wide. +* Making it easier for implementors to override how the CardDAV addressbook + home is located. +* Fixed: Issue #422 Preconditions were not being set on PUT on non-existant + files. Not really a chance for data-loss, but incorrect nevertheless. +* Fixed: Issue #428: Etag check with `If:` fails if the target is a collection. +* Fixed: Issues #430, #431, #433: Locks plugin didn't not properly release + filesystem based locks. +* Fixed: #443. Support for creating new calendar subscriptions for OS X 10.9.2 + and up. +* Removed: `Sabre\DAV\Server::NODE_*` constants. +* Moved all precondition checking into a central place, instead of having to + think about it on a per-method basis. +* jCal transformation for calendar-query REPORT now works again. +* Switched to PSR-4 +* Fixed: #175. Returning ETag header upon a failed `If-Match` or + `If-None-Match` check. +* Removed: `lib/Sabre/autoload.php`. Use `vendor/autoload.php` instead. +* Removed: all the rfc documentation from the sabre/dav source. This made the + package needlessly larger. +* Updated: Issue #439. Lots of updates in PATCH support. The + Sabre_DAV_PartialUpdate_IFile interface is now deprecated and will be + removed in a future version. +* Added: `Sabre\DAV\Exception\LengthRequired`. + +1.9.0-alpha2 (2014-01-14) +------------------------- + +* The zip release ships with sabre/vobject 3.1.3, sabre/http 2.0.1, and + sabre/event 1.0.0. +* Added: Browser can now inspect any node, if ?sabreaction=browser is appended. +* Fixed: Issue #178. Support for multiple items in the Timeout header. +* Fixed: Issue #382. Stricter checking if calendar-query is allowed to run. +* Added: Depth: Infinity support for PROPFIND request. Thanks Thomas Müller and + Markus Goetz. + + +1.9.0-alpha1 (2013-11-07) +------------------------- + +* The zip release ships with sabre/vobject 3.1.3, sabre/http 2.0.0alpha5, and + sabre/event 1.0.0. +* BC Break: The CardDAV and CalDAV BackendInterface each have a new method: + getMultipleCards and getMultipleCalendarObjects. The Abstract and PDO backends + have default implementations, but if you implement that interface directly, + this method is now required. +* BC Break: XML property classes now receive an extra argument in their + unserialize method ($propertyMap). This allows for recursively parsing + properties, if needed. +* BC Break: Now using sabre/event for event emitting/subscription. For plugin + authors this means Server::subscribeEvent is now Server::on, and + Server::broadcastEvent is now Server::emit. +* BC Break: Almost all core functionality moved into a CorePlugin. +* BC Break: Most events triggered by the server got an overhaul. +* Changed: Sabre\HTTP now moved into a dedicated sabre/http package. +* Added: Support for WebDAV-sync (rfc6578). +* Added: Support for caldav-subscriptions, which is an easy way for caldav + clients to manage a list of subscriptions on the server. +* Added: Support for emitting and receiving jCal instead of iCalendar for + CalDAV. +* Added: BasicCallback authenticaton backend, for creating simple authentication + systems without having to define any classes. +* Added: A $transactionType property on the server class. This can be used for + logging and performance measuring purposes. +* Fixed: If event handlers modify the request body from a PUT request, an ETag + is no longer sent back. +* Added: Sabre\DAV\IMultiGet to optimize requests that retrieve information + about lists of resources. +* Added: MultiGet support to default CalDAV and CardDAV backends, speeding up + the multiget and sync reports quite a bit! +* Added: ICSExportPlugin can now generate jCal, filter on time-ranges and expand + recurrences. +* Fixed: Read-only access to calendars still allows the sharee to modify basic + calendar properties, such as the displayname and color. +* Changed: The default supportedPrivilegeSet has changed. Most privileges are no + longer marked as abstract. +* Changed: More elegant ACL management for CalendarObject and Card nodes. +* Added: Browser plugin now marks a carddav directory as type Directory, and a + shared calendar as 'Shared'. +* Added: When debugExceptions is turned on, all previous exceptions are also + traversed. +* Removed: Got rid of the Version classes for CalDAV, CardDAV, HTTP, and DAVACL. + Now that there's no separate packages anymore, this makes a bit more sense. +* Added: Generalized the multistatus response parser a bit more, for better + re-use. +* Added: Sabre\DAV\Client now has support for complex properties for PROPPATCH. + (Issue #299). +* Added: Sabre\DAV\Client has support for gzip and deflate encoding. +* Added: Sabre\DAV\Client now has support for sending objects as streams. +* Added: Deserializer for {DAV:}current-user-privilege-set. +* Added: Addressbooks or backends can now specify custom acl rules when creating + cards. +* Added: The ability for plugins to validate custom tokens in If: headers. +* Changed: Completely refactored the Lock plugin to deal with the new If: header + system. +* Added: Checking preconditions for MOVE, COPY, DELETE and PROPPATCH methods. +* Added: has() method on DAV\Property\SupportedReportSet. +* Added: If header now gets checked (with ETag) all the time. Before the dealing + with the If-header was a responsibility of the Locking plugin. +* Fixed: Outbox access for delegates. +* Added: Issue 333: It's now possible to override the calendar-home in the + CalDAV plugin. +* Added: A negotiateContentType to HTTP\Request. A convenience method. +* Fixed: Issue 349: Denying copying or moving a resource into it's own subtree. +* Fixed: SabreDAV catches every exception again. +* Added: Issue #358, adding a component=vevent parameter to the content-types + for calendar objects, if the caldav backend provides this info. + + +1.8.12-stable (2015-01-21) +-------------------------- + +* The zip release ships with sabre/vobject 2.1.7. +* #568: Support empty usernames and passwords in basic auth. + + +1.8.11 (2014-12-10) +------------------- + +* The zip release ships with sabre/vobject 2.1.6. +* Updated: MySQL database schema optimized by using more efficient column types. +* #516: The DAV client will now only redirect to HTTP and HTTPS urls. + + +1.8.10 (2014-05-15) +------------------- + +* The zip release ships with sabre/vobject 2.1.4. +* includes changes from version 1.7.12. + + +1.8.9 (2014-02-26) +------------------ + +* The zip release ships with sabre/vobject 2.1.3. +* includes changes from version 1.7.11. + + +1.8.8 (2014-02-09) +------------------ + +* includes changes from version 1.7.10. +* The zip release ships with sabre/vobject 2.1.3. + +1.8.7 (2013-10-02) +------------------ + +* the zip release ships with sabre/vobject 2.1.3. +* includes changes from version 1.7.9. + + +1.8.6 (2013-06-18) +------------------ + +* The zip release ships with sabre/vobject 2.1.0. +* Includes changes from version 1.7.8. + + +1.8.5 (2013-04-11) +------------------ + +* The zip release ships with sabre/vobject 2.0.7. +* Includes changes from version 1.7.7. + + +1.8.4 (2013-04-08) +------------------ + +* The zip release ships with sabre/vobject 2.0.7. +* Includes changes from version 1.7.6. + + +1.8.3 (2013-03-01) +------------------ + +* The zip release ships with sabre/vobject 2.0.6. +* Includes changes from version 1.7.5. +* Fixed: organizer email-address for shared calendars is now prefixed with + mailto:, as it should. + + +1.8.2 (2013-01-19) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Includes changes from version 1.7.4. + + +1.8.1 (2012-12-01) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Includes changes from version 1.7.3. +* Fixed: Typo in 1.7 migration script caused it to fail. + + +1.8.0 (2012-11-08) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* BC Break: Moved the entire codebase to PHP namespaces. +* BC Break: Every backend package (CalDAV, CardDAV, Auth, Locks, Principals) now + has consistent naming conventions. There's a BackendInterface, and an + AbstractBackend class. +* BC Break: Changed a bunch of constructor signatures in the CalDAV package, to + reduce dependencies on the ACL package. +* BC Break: Sabre_CalDAV_ISharedCalendar now also has a getShares method, so + sharees can figure out who is also on a shared calendar. +* Added: Sabre_DAVACL_IPrincipalCollection interface, to advertise support for + principal-property-search on any node. +* Added: Simple console script to fire up a fileserver in the current directory + using PHP 5.4's built-in webserver. +* Added: Sharee's can now also read out the list of invites for a shared + calendar. +* Added: The Proxy principal classes now both implement an interface, for + greater flexiblity. + + +1.7.13 (2014-07-28) +------------------- + +* The zip release ships with sabre/vobject 2.1.4. +* Changed: Removed phing and went with a custom build script for now. + + +1.7.12 (2014-05-15) +------------------- + +* The zip release ships with sabre/vobject 2.1.4. +* Updated: Issue #439. Lots of updates in PATCH support. The + Sabre_DAV_PartialUpdate_IFile interface is now deprecated and will be removed + in a future version. +* Fixed: Restoring old setting after changing libxml_disable_entity_loader. +* Fixed: Issue #422: Preconditions were not being set on PUT on non-existant + files. Not really a chance for data-loss, but incorrect nevertheless. +* Fixed: Issue #427: Now checking preconditions on DELETE requests. +* Fixed: Issue #428: Etag check with If: fails if the target is a collection. +* Fixed: Issue #393: PATCH request with missing end-range was handled + incorrectly. +* Added: Sabre_DAV_Exception_LengthRequired to omit 411 errors. + + +1.7.11 (2014-02-26) +------------------- + +* The zip release ships with sabre/vobject 2.1.3. +* Fixed: Issue #407: large downloads failed. +* Fixed: Issue #414: XXE security problem on older PHP versions. + + +1.7.10 (2014-02-09) +------------------- + +* Fixed: Issue #374: Don't urlescape colon (:) when it's not required. +* Fixed: Potential security vulnerability in the http client. + + +1.7.9 (2013-10-02) +------------------ + +* The zip release ships with sabre/vobject 2.1.3. +* Fixed: Issue #365. Incorrect output when principal urls have spaces in them. +* Added: Issue #367: Automatically adding a UID to vcards that don't have them. + + +1.7.8 (2013-06-17) +------------------ + +* The zip release ships with sabre/vobject 2.1.0. +* Changed: Sabre\DAV\Client::verifyPeer is now a protected property (instead of + private). +* Fixed: Text was incorrectly escaped in the Href and HrefList properties, + disallowing urls with ampersands (&) in them. +* Added: deserializer for Sabre\DAVACL\Property\CurrentUserPrivilegeSet. +* Fixed: Issue 335: Client only deserializes properties with status 200. +* Fixed: Issue 341: Escaping xml in 423 Locked error responses. +* Added: Issue 339: beforeGetPropertiesForPath event. + + +1.7.7 (2013-04-11) +------------------ + +* The zip release ships with sabre/vobject 2.0.7. +* Fixed: Assets in the browser plugins were not being served on windows + machines. + + +1.7.6 (2013-04-08) +------------------ + +* The zip release ships with sabre/vobject 2.0.7. +* Fixed: vcardurl in database schema can now hold 255 characters instead of 80 + (which is often way to small). +* Fixed: The browser plugin potentially allowed people to open any arbitrary + file on windows servers (CVE-2013-1939). + + +1.7.5 (2013-03-01) +------------------ + +* The zip release ships with sabre/vobject 2.0.6. +* Change: No longer advertising support for 4.0 vcards. iOS and OS X address + book don't handle this well, and just advertising 3.0 support seems like the + most logical course of action. +* Added: ->setVerifyPeers to Sabre_DAV_Client (greatly resisting against it, + don't use this..). + + +1.7.4 (2013-01-19) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Changed: To be compatibile with MS Office 2011 for Mac, a workaround was + removed that was added to support old versions of Windows XP (pre-SP3). + Indeed! We needed a crazy workaround to work with one MS product in the past, + and we can't keep that workaround to be compatible with another MS product. +* Fixed: expand-properties REPORT had incorrect values for the href element. +* Fixed: Range requests now work for non-seekable streams. (Thanks Alfred + Klomp). +* Fixed: Changed serialization of {DAV:}getlastmodified and {DAV:}supportedlock + to improve compatiblity with MS Office 2011 for Mac. +* Changed: reverted the automatic translation of 'DAV:' xml namespaces to + 'urn:DAV' when parsing files. Issues were reported with libxml 2.6.32, on a + relatively recent debian release, so we'll wait till 2015 to take this one out + again. +* Added: Sabre_DAV_Exception_ServiceUnavailable, for emitting 503's. + + +1.7.3 (2012-12-01) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Fixed: Removing double slashes from getPropertiesForPath. +* Change: Marked a few more properties in the CardDAV as protected, instead of + private. +* Fixed: SharingPlugin now plays nicer with other plugins with similar + functionality. +* Fixed: Issue 174. Sending back HTTP/1.0 for requests with this version. + + +1.7.2 (2012-11-08) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Added: ACL plugin advertises support for 'calendarserver-principal- + property-search'. +* Fixed: [#153] Allowing for relative http principals in iMip requests. +* Added: Support for cs:first-name and cs:last-name properties in sharing + invites. +* Fixed: Made a bunch of properties protected, where they were private before. +* Added: Some non-standard properties for sharing to improve compatibility. +* Fixed: some bugfixes in postgres sql script. +* Fixed: When requesting some properties using PROPFIND, they could show up as + both '200 Ok' and '403 Forbidden'. +* Fixed: calendar-proxy principals were not checked for deeper principal + membership than 1 level. +* Fixed: setGroupMemberSet argument now correctly receives relative principal + urls, instead of the absolute ones. +* Fixed: Server class will filter out any bonus properties if any extra were + returned. This means the implementor of the IProperty class can be a bit + lazier when implementing. Note: bug numbers after this line refer to Google + Code tickets. We're using github now. + + +1.7.1 (2012-10-07) +------------------ + +* Fixed: include path problem in the migration script. + + +1.7.0 (2012-10-06) +------------------ + +* BC Break: The calendarobjects database table has a bunch of new fields, and a + migration script is required to ensure everything will keep working. Read the + wiki for more details. +* BC Break: The ICalendar interface now has a new method: calendarQuery. +* BC Break: In this version a number of classes have been deleted, that have + been previously deprecated. Namely: - Sabre_DAV_Directory (now: + Sabre_DAV_Collection) - Sabre_DAV_SimpleDirectory (now: + Sabre_DAV_SimpleCollection) +* BC Break: Sabre_CalDAV_Schedule_IMip::sendMessage now has an extra argument. + If you extended this class, you should fix this method. It's only used for + informational purposes. +* BC Break: The DAV: namespace is no longer converted to urn:DAV. This was a + workaround for a bug in older PHP versions (pre-5.3). +* Removed: Sabre.includes.php was deprecated, and is now removed. +* Removed: Sabre_CalDAV_Server was deprecated, and is now removed. Please use + Sabre_DAV_Server and check the examples in the examples/ directory. +* Changed: The Sabre_VObject library now spawned into it's own project! The + VObject library is still included in the SabreDAV zip package. +* Added: Experimental interfaces to allow implementation of caldav-sharing. Note + that no implementation is provided yet, just the api hooks. +* Added: Free-busy reporting compliant with the caldav-scheduling standard. This + allows iCal and other clients to fetch other users' free-busy data. +* Added: Experimental NotificationSupport interface to add caldav notifications. +* Added: VCF Export plugin. If enabled, it can generate an export of an entire + addressbook. +* Added: Support for PATCH using a SabreDAV format, to live-patch files. +* Added: Support for Prefer: return-minimal and Brief: t headers for PROPFIND + and PROPPATCH requests. +* Changed: Responsibility for dealing with the calendar-query is now moved from + the CalDAV plugin to the CalDAV backends. This allows for heavy optimizations. +* Changed: The CalDAV PDO backend is now a lot faster for common calendar + queries. +* Changed: We are now using the composer autoloader. +* Changed: The CalDAV backend now all implement an interface. +* Changed: Instead of Sabre_DAV_Property, Sabre_DAV_PropertyInterface is now the + basis of every property class. +* Update: Caching results for principal lookups. This should cut down queries + and performance for a number of heavy requests. +* Update: ObjectTree caches lookups much more aggresively, which will help + especially speeding up a bunch of REPORT queries. +* Added: Support for the schedule-calendar-transp property. +* Fixed: Marking both the text/calendar and text/x-vcard as UTF-8 encoded. +* Fixed: Workaround for the SOGO connector, as it doesn't understand receiving + "text/x-vcard; charset=utf-8" for a contenttype. +* Added: Sabre_DAV_Client now throws more specific exceptions in cases where we + already has an exception class. +* Added: Sabre_DAV_PartialUpdate. This plugin allows you to use the PATCH method + to update parts of a file. +* Added: Tons of timezone name mappings for Microsoft Exchange. +* Added: Support for an 'exception' event in the server class. +* Fixed: Uploaded VCards without a UID are now rejected. (thanks Dominik!) +* Fixed: Rejecting calendar objects if they are not in the + supported-calendar-component list. (thanks Armin!) +* Fixed: Issue 219: serialize() now reorders correctly. +* Fixed: Sabre_DAV_XMLUtil no longer returns empty $dom->childNodes if there is + whitespace in $dom. +* Fixed: Returning 409 Conflict instead of 500 when an attempt is made to create + a file as a child of something that's not a collection. +* Fixed: Issue 237: xml-encoding values in SabreDAV error responses. +* Fixed: Returning 403, instead of 501 when an unknown REPORT is requested. +* Fixed: Postfixing slash on {DAV:}owner properties. +* Fixed: Several embarrassing spelling mistakes in docblocks. + + +1.6.10 (2013-06-17) +------------------- + +* Fixed: Text was incorrectly escaped in the Href and HrefList properties, + disallowing urls with ampersands (&) in them. +* Fixed: Issue 341: Escaping xml in 423 Locked error responses. + + +1.6.9 (2013-04-11) +------------------ + +* Fixed: Assets in the browser plugins were not being served on windows + machines. + + +1.6.8 (2013-04-08) +------------------ + +* Fixed: vcardurl in database schema can now hold 255 characters instead of 80 + (which is often way to small). +* Fixed: The browser plugin potentially allowed people to open any arbitrary + file on windows servers. (CVE-2013-1939). + + +1.6.7 (2013-03-01) +------------------ + +* Change: No longer advertising support for 4.0 vcards. iOS and OS X address + book don't handle this well, and just advertising 3.0 support seems like the + most logical course of action. +* Added: ->setVerifyPeers to Sabre_DAV_Client (greatly resisting against it, + don't use this..). + + +1.6.6 (2013-01-19) +------------------ + +* Fixed: Backported a fix for broken XML serialization in error responses. + (Thanks @DeepDiver1975!) + + +1.6.5 (2012-10-04) +------------------ + +* Fixed: Workaround for line-ending bug OS X 10.8 addressbook has. +* Added: Ability to allow users to set SSL certificates for the Client class. + (Thanks schiesbn!). +* Fixed: Directory indexes with lots of nodes should be a lot faster. +* Fixed: Issue 235: E_NOTICE thrown when doing a propfind request with + Sabre_DAV_Client, and no valid properties are returned. +* Fixed: Issue with filtering on alarms in tasks. + + +1.6.4 (2012-08-02) +------------------ + +* Fixed: Issue 220: Calendar-query filters may fail when filtering on alarms, if + an overridden event has it's alarm removed. +* Fixed: Compatibility for OS/X 10.8 iCal in the IMipHandler. +* Fixed: Issue 222: beforeWriteContent shouldn't be called for lock requests. +* Fixed: Problem with POST requests to the outbox if mailto: was not lower + cased. +* Fixed: Yearly recurrence rule expansion on leap-days no behaves correctly. +* Fixed: Correctly checking if recurring, all-day events with no dtstart fall in + a timerange if the start of the time-range exceeds the start of the instance + of an event, but not the end. +* Fixed: All-day recurring events wouldn't match if an occurence ended exactly + on the start of a time-range. +* Fixed: HTTP basic auth did not correctly deal with passwords containing colons + on some servers. +* Fixed: Issue 228: DTEND is now non-inclusive for all-day events in the + calendar-query REPORT and free-busy calculations. + + +1.6.3 (2012-06-12) +------------------ + +* Added: It's now possible to specify in Sabre_DAV_Client which type of + authentication is to be used. +* Fixed: Issue 206: Sabre_DAV_Client PUT requests are fixed. +* Fixed: Issue 205: Parsing an iCalendar 0-second date interval. +* Fixed: Issue 112: Stronger validation of iCalendar objects. Now making sure + every iCalendar object only contains 1 component, and disallowing vcards, + forcing every component to have a UID. +* Fixed: Basic validation for vcards in the CardDAV plugin. +* Fixed: Issue 213: Workaround for an Evolution bug, that prevented it from + updating events. +* Fixed: Issue 211: A time-limit query on a non-relative alarm trigger in a + recurring event could result in an endless loop. +* Fixed: All uri fields are now a maximum of 200 characters. The Bynari outlook + plugin used much longer strings so this should improve compatibility. +* Fixed: Added a workaround for a bug in KDE 4.8.2 contact syncing. See + https://bugs.kde.org/show_bug.cgi?id=300047 +* Fixed: Issue 217: Sabre_DAV_Tree_FileSystem was pretty broken. + + +1.6.2 (2012-04-16) +------------------ + +* Fixed: Sabre_VObject_Node::$parent should have been public. +* Fixed: Recurrence rules of events are now taken into consideration when doing + time-range queries on alarms. +* Fixed: Added a workaround for the fact that php's DateInterval cannot parse + weeks and days at the same time. +* Added: Sabre_DAV_Server::$exposeVersion, allowing you to hide SabreDAV's + version number from various outputs. +* Fixed: DTSTART values would be incorrect when expanding events. +* Fixed: DTSTART and DTEND would be incorrect for expansion of WEEKLY BYDAY + recurrences. +* Fixed: Issue 203: A problem with overridden events hitting the exact date and + time of a subsequent event in the recurrence set. +* Fixed: There was a problem with recurrence rules, for example the 5th tuesday + of the month, if this day did not exist. +* Added: New HTTP status codes from draft-nottingham-http-new-status-04. + + +1.6.1 (2012-03-05) +------------------ + +* Added: createFile and put() can now return an ETag. +* Added: Sending back an ETag on for operations on CardDAV backends. This should + help with OS X 10.6 Addressbook compatibility. +* Fixed: Fixed a bug where an infinite loop could occur in the recurrence + iterator if the recurrence was YEARLY, with a BYMONTH rule, and either BYDAY + or BYMONTHDAY match the first day of the month. +* Fixed: Events that are excluded using EXDATE are still counted in the COUNT= + parameter in the RRULE property. +* Added: Support for time-range filters on VALARM components. +* Fixed: Correctly filtering all-day events. +* Fixed: Sending back correct mimetypes from the browser plugin (thanks + Jürgen). +* Fixed: Issue 195: Sabre_CardDAV pear package had an incorrect dependency. +* Fixed: Calendardata would be destroyed when performing a MOVE request. + + +1.6.0 (2012-02-22) +------------------ + +* BC Break: Now requires PHP 5.3 +* BC Break: Any node that implemented Sabre_DAVACL_IACL must now also implement + the getSupportedPrivilegeSet method. See website for details. +* BC Break: Moved functions from Sabre_CalDAV_XMLUtil to + Sabre_VObject_DateTimeParser. +* BC Break: The Sabre_DAVACL_IPrincipalCollection now has two new methods: + 'searchPrincipals' and 'updatePrincipal'. +* BC Break: Sabre_DAV_ILockable is removed and all related per-node locking + functionality. +* BC Break: Sabre_DAV_Exception_FileNotFound is now deprecated in favor of + Sabre_DAV_Exception_NotFound. The former will be removed in a later version. +* BC Break: Removed Sabre_CalDAV_ICalendarUtil, use Sabre_VObject instead. +* BC Break: Sabre_CalDAV_Server is now deprecated, check out the documentation + on how to setup a caldav server with just Sabre_DAV_Server. +* BC Break: Default Principals PDO backend now needs a new field in the + 'principals' table. See the website for details. +* Added: Ability to create new calendars and addressbooks from within the + browser plugin. +* Added: Browser plugin: icons for various nodes. +* Added: Support for FREEBUSY reports! +* Added: Support for creating principals with admin-level privileges. +* Added: Possibility to let server send out invitation emails on behalf of + CalDAV client, using Sabre_CalDAV_Schedule_IMip. +* Changed: beforeCreateFile event now passes data argument by reference. +* Changed: The 'propertyMap' property from Sabre_VObject_Reader, must now be + specified in Sabre_VObject_Property::$classMap. +* Added: Ability for plugins to tell the ACL plugin which principal plugins are + searchable. +* Added: [DAVACL] Per-node overriding of supported privileges. This allows for + custom privileges where needed. +* Added: [DAVACL] Public 'principalSearch' method on the DAVACL plugin, which + allows for easy searching for principals, based on their properties. +* Added: Sabre_VObject_Component::getComponents() to return a list of only + components and not properties. +* Added: An includes.php file in every sub-package (CalDAV, CardDAV, DAV, + DAVACL, HTTP, VObject) as an alternative to the autoloader. This often works + much faster. +* Added: Support for the 'Me card', which allows Addressbook.app users specify + which vcard is their own. +* Added: Support for updating principal properties in the DAVACL principal + backends. +* Changed: Major refactoring in the calendar-query REPORT code. Should make + things more flexible and correct. +* Changed: The calendar-proxy-[read|write] principals will now only appear in + the tree, if they actually exist in the Principal backend. This should reduce + some problems people have been having with this. +* Changed: Sabre_VObject_Element_* classes are now renamed to + Sabre_VObject_Property. Old classes are retained for backwards compatibility, + but this will be removed in the future. +* Added: Sabre_VObject_FreeBusyGenerator to generate free-busy reports based on + lists of events. +* Added: Sabre_VObject_RecurrenceIterator to find all the dates and times for + recurring events. +* Fixed: Issue 97: Correctly handling RRULE for the calendar-query REPORT. +* Fixed: Issue 154: Encoding of VObject parameters with no value was incorrect. +* Added: Support for {DAV:}acl-restrictions property from RFC3744. +* Added: The contentlength for calendar objects can now be supplied by a CalDAV + backend, allowing for more optimizations. +* Fixed: Much faster implementation of Sabre_DAV_URLUtil::encodePath. +* Fixed: {DAV:}getcontentlength may now be not specified. +* Fixed: Issue 66: Using rawurldecode instead of urldecode to decode paths from + clients. This means that + will now be treated as a literal rather than a + space, and this should improve compatibility with the Windows built-in client. +* Added: Sabre_DAV_Exception_PaymentRequired exception, to emit HTTP 402 status + codes. +* Added: Some mysql unique constraints to example files. +* Fixed: Correctly formatting HTTP dates. +* Fixed: Issue 94: Sending back Last-Modified header for 304 responses. +* Added: Sabre_VObject_Component_VEvent, Sabre_VObject_Component_VJournal, + Sabre_VObject_Component_VTodo and Sabre_VObject_Component_VCalendar. +* Changed: Properties are now also automatically mapped to their appropriate + classes, if they are created using the add() or __set() methods. +* Changed: Cloning VObject objects now clones the entire tree, rather than just + the default shallow copy. +* Added: Support for recurrence expansion in the CALDAV:calendar-multiget and + CALDAV:calendar-query REPORTS. +* Changed: CalDAV PDO backend now sorts calendars based on the internal + 'calendarorder' field. +* Added: Issue 181: Carddav backends may no optionally not supply the carddata + in getCards, if etag and size are specified. This may speed up certain + requests. +* Added: More arguments to beforeWriteContent and beforeCreateFile (see + WritingPlugins wiki document). +* Added: Hook for iCalendar validation. This allows us to validate iCalendar + objects when they're uploaded. At the moment we're just validating syntax. +* Added: VObject now support Windows Timezone names correctly (thanks mrpace2). +* Added: If a timezonename could not be detected, we fall back on the default + PHP timezone. +* Added: Now a Composer package (thanks willdurand). +* Fixed: Support for \N as a newline character in the VObject reader. +* Added: afterWriteContent, afterCreateFile and afterUnbind events. +* Added: Postgresql example files. Not part of the unittests though, so use at + your own risk. +* Fixed: Issue 182: Removed backticks from sql queries, so it will work with + Postgres. + + +1.5.9 (2012-04-16) +------------------ + +* Fixed: Issue with parsing timezone identifiers that were surrounded by quotes. + (Fixes emClient compatibility). + + +1.5.8 (2012-02-22) +------------------ + +* Fixed: Issue 95: Another timezone parsing issue, this time in calendar-query. + + +1.5.7 (2012-02-19) +------------------ + +* Fixed: VObject properties are now always encoded before components. +* Fixed: Sabre_DAVACL had issues with multiple levels of privilege aggregration. +* Changed: Added 'GuessContentType' plugin to fileserver.php example. +* Fixed: The Browser plugin will now trigger the correct events when creating + files. +* Fixed: The ICSExportPlugin now considers ACL's. +* Added: Made it optional to supply carddata from an Addressbook backend when + requesting getCards. This can make some operations much faster, and could + result in much lower memory use. +* Fixed: Issue 187: Sabre_DAV_UUIDUtil was missing from includes file. +* Fixed: Issue 191: beforeUnlock was triggered twice. + + +1.5.6 (2012-01-07) +------------------ + +* Fixed: Issue 174: VObject could break UTF-8 characters. +* Fixed: pear package installation issues. + + +1.5.5 (2011-12-16) +------------------ + +* Fixed: CalDAV time-range filter workaround for recurring events. +* Fixed: Bug in Sabre_DAV_Locks_Backend_File that didn't allow multiple files to + be locked at the same time. + + +1.5.4 (2011-10-28) +------------------ + +* Fixed: GuessContentType plugin now supports mixed case file extensions. +* Fixed: DATE-TIME encoding was wrong in VObject. (we used 'DATETIME'). +* Changed: Sending back HTTP 204 after a PUT request on an existing resource + instead of HTTP 200. This should fix Evolution CardDAV client compatibility. +* Fixed: Issue 95: Parsing X-LIC-LOCATION if it's available. +* Added: All VObject elements now have a reference to their parent node. + + +1.5.3 (2011-09-28) +------------------ + +* Fixed: Sabre_DAV_Collection was missing from the includes file. +* Fixed: Issue 152. iOS 1.4.2 apparantly requires HTTP/1.1 200 OK to be in + uppercase. +* Fixed: Issue 153: Support for files with mixed newline styles in + Sabre_VObject. +* Fixed: Issue 159: Automatically converting any vcard and icalendardata to + UTF-8. +* Added: Sabre_DAV_SimpleFile class for easy static file creation. +* Added: Issue 158: Support for the CARDDAV:supported-address-data property. + + +1.5.2 (2011-09-21) +------------------ + +* Fixed: carddata and calendardata MySQL fields are now of type 'mediumblob'. + 'TEXT' was too small sometimes to hold all the data. +* Fixed: {DAV:}supported-report-set is now correctly reporting the reports for + IAddressBook. +* Added: Sabre_VObject_Property::add() to add duplicate parameters to + properties. +* Added: Issue 151: Sabre_CalDAV_ICalendar and Sabre_CalDAV_ICalendarObject + interfaces. +* Fixed: Issue 140: Not returning 201 Created if an event cancelled the creation + of a file. +* Fixed: Issue 150: Faster URLUtil::encodePath() implementation. +* Fixed: Issue 144: Browser plugin could interfere with + TemporaryFileFilterPlugin if it was loaded first. +* Added: It's not possible to specify more 'alternate uris' in principal + backends. + + +1.5.1 (2011-08-24) +------------------ + +* Fixed: Issue 137. Hiding action interface in HTML browser for non-collections. +* Fixed: addressbook-query is now correctly returned from the + {DAV:}supported-report-set property. +* Fixed: Issue 142: Bugs in groupwareserver.php example. +* Fixed: Issue 139: Rejecting PUT requests with Content-Range. + + +1.5.0 (2011-08-12) +------------------ + +* Added: CardDAV support. +* Added: An experimental WebDAV client. +* Added: MIME-Directory grouping support in the VObject library. This is very + useful for people attempting to parse vcards. +* BC Break: Adding parameters with the VObject libraries now overwrites the + previous parameter, rather than just add it. This makes more sense for 99% of + the cases. +* BC Break: lib/Sabre.autoload.php is now removed in favor of + lib/Sabre/autoload.php. +* Deprecated: Sabre_DAV_Directory is now deprecated and will be removed in a + future version. Use Sabre_DAV_Collection instead. +* Deprecated: Sabre_DAV_SimpleDirectory is now deprecated and will be removed in + a future version. Use Sabre_DAV_SimpleCollection instead. +* Fixed: Problem with overriding tablenames for the CalDAV backend. +* Added: Clark-notation parser to XML utility. +* Added: unset() support to VObject components. +* Fixed: Refactored CalDAV property fetching to be faster and simpler. +* Added: Central string-matcher for CalDAV and CardDAV plugins. +* Added: i;unicode-casemap support +* Fixed: VObject bug: wouldn't parse parameters if they weren't specified in + uppercase. +* Fixed: VObject bug: Parameters now behave more like Properties. +* Fixed: VObject bug: Parameters with no value are now correctly parsed. +* Changed: If calendars don't specify which components they allow, 'all' + components are assumed (e.g.: VEVENT, VTODO, VJOURNAL). +* Changed: Browser plugin now uses POST variable 'sabreAction' instead of + 'action' to reduce the chance of collisions. + + +1.4.4 (2011-07-07) +------------------ + +* Fixed: Issue 131: Custom CalDAV backends could break in certain cases. +* Added: The option to override the default tablename all PDO backends use. + (Issue 60). +* Fixed: Issue 124: 'File' authentication backend now takes realm into + consideration. +* Fixed: Sabre_DAV_Property_HrefList now properly deserializes. This allows + users to update the {DAV:}group-member-set property. +* Added: Helper functions for DateTime-values in Sabre_VObject package. +* Added: VObject library can now automatically map iCalendar properties to + custom classes. + + +1.4.3 (2011-04-25) +------------------ + +* Fixed: Issue 123: Added workaround for Windows 7 UNLOCK bug. +* Fixed: datatype of lastmodified field in mysql.calendars.sql. Please change + the DATETIME field to an INT to ensure this field will work correctly. +* Change: Sabre_DAV_Property_Principal is now renamed to + Sabre_DAVACL_Property_Principal. +* Added: API level support for ACL HTTP method. +* Fixed: Bug in serializing {DAV:}acl property. +* Added: deserializer for {DAV:}resourcetype property. +* Added: deserializer for {DAV:}acl property. +* Added: deserializer for {DAV:}principal property. + + +1.4.2-beta (2011-04-01) +----------------------- + +* Added: It's not possible to disable listing of nodes that are denied read + access by ACL. +* Fixed: Changed a few properties in CalDAV classes from private to protected. +* Fixed: Issue 119: Terrible things could happen when relying on guessBaseUri, + the server was running on the root of the domain and a user tried to access a + file ending in .php. This is a slight BC break. +* Fixed: Issue 118: Lock tokens in If headers without a uri should be treated as + the request uri, not 'all relevant uri's. +* Fixed: Issue 120: PDO backend was incorrectly fetching too much locks in cases + where there were similar named locked files in a directory. + + +1.4.1-beta (2011-02-26) +----------------------- + +* Fixed: Sabre_DAV_Locks_Backend_PDO returned too many locks. +* Fixed: Sabre_HTTP_Request::getHeader didn't return Content-Type when running + on apache, so a few workarounds were added. +* Change: Slightly changed CalDAV Backend API's, to allow for heavy + optimizations. This is non-bc breaking. + + +1.4.0-beta (2011-02-12) +----------------------- + +* Added: Partly RFC3744 ACL support. +* Added: Calendar-delegation (caldav-proxy) support. +* BC break: In order to fix Issue 99, a new argument had to be added to + Sabre_DAV_Locks_Backend_*::getLocks classes. Consult the classes for details. +* Deprecated: Sabre_DAV_Locks_Backend_FS is now deprecated and will be removed + in a later version. Use PDO or the new File class instead. +* Deprecated: The Sabre_CalDAV_ICalendarUtil class is now marked deprecated, and + will be removed in a future version. Please use Sabre_VObject instead. +* Removed: All principal-related functionality has been removed from the + Sabre_DAV_Auth_Plugin, and moved to the Sabre_DAVACL_Plugin. +* Added: VObject library, for easy vcard/icalendar parsing using a natural + interface. +* Added: Ability to automatically generate full .ics feeds off calendars. To + use: Add the Sabre_CalDAV_ICSExportPlugin, and add ?export to your calendar + url. +* Added: Plugins can now specify a pluginname, for easy access using + Sabre_DAV_Server::getPlugin(). +* Added: beforeGetProperties event. +* Added: updateProperties event. +* Added: Principal listings and calendar-access can now be done privately, + disallowing users from accessing or modifying other users' data. +* Added: You can now pass arrays to the Sabre_DAV_Server constructor. If it's an + array with node-objects, a Root collection will automatically be created, and + the nodes are used as top-level children. +* Added: The principal base uri is now customizable. It used to be hardcoded to + 'principals/[user]'. +* Added: getSupportedReportSet method in ServerPlugin class. This allows you to + easily specify which reports you're implementing. +* Added: A '..' link to the HTML browser. +* Fixed: Issue 99: Locks on child elements were ignored when their parent nodes + were deleted. +* Fixed: Issue 90: lockdiscovery property and LOCK response now include a + {DAV}lockroot element. +* Fixed: Issue 96: support for 'default' collation in CalDAV text-match filters. +* Fixed: Issue 102: Ensuring that copy and move with identical source and + destination uri's fails. +* Fixed: Issue 105: Supporting MKCALENDAR with no body. +* Fixed: Issue 109: Small fixes in Sabre_HTTP_Util. +* Fixed: Issue 111: Properly catching the ownername in a lock (if it's a string) +* Fixed: Sabre_DAV_ObjectTree::nodeExist always returned false for the root + node. +* Added: Global way to easily supply new resourcetypes for certain node classes. +* Fixed: Issue 59: Allowing the user to override the authentication realm in + Sabre_CalDAV_Server. +* Update: Issue 97: Looser time-range checking if there's a recurrence rule in + an event. This fixes 'missing recurring events'. + + +1.3.0 (2010-10-14) +------------------ + +* Added: childExists method to Sabre_DAV_ICollection. This is an api break, so + if you implement Sabre_DAV_ICollection directly, add the method. +* Changed: Almost all HTTP method implementations now take a uri argument, + including events. This allows for internal rerouting of certain calls. If you + have custom plugins, make sure they use this argument. If they don't, they + will likely still work, but it might get in the way of future changes. +* Changed: All getETag methods MUST now surround the etag with double-quotes. + This was a mistake made in all previous SabreDAV versions. If you don't do + this, any If-Match, If-None-Match and If: headers using Etags will work + incorrectly. (Issue 85). +* Added: Sabre_DAV_Auth_Backend_AbstractBasic class, which can be used to easily + implement basic authentication. +* Removed: Sabre_DAV_PermissionDenied class. Use Sabre_DAV_Forbidden instead. +* Removed: Sabre_DAV_IDirectory interface, use Sabre_DAV_ICollection instead. +* Added: Browser plugin now uses {DAV:}displayname if this property is + available. +* Added: Cache layer in the ObjectTree. +* Added: Tree classes now have a delete and getChildren method. +* Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if the + date is an exact match. +* Fixed: Support for multiple ETags in If-Match and If-None-Match headers. +* Fixed: Improved baseUrl handling. +* Fixed: Issue 67: Non-seekable stream support in ::put()/::get(). +* Fixed: Issue 65: Invalid dates are now ignored. +* Updated: Refactoring in Sabre_CalDAV to make everything a bit more ledgable. +* Fixed: Issue 88, Issue 89: Fixed compatibility for running SabreDAV on + Windows. +* Fixed: Issue 86: Fixed Content-Range top-boundary from 'file size' to 'file + size'-1. + + +1.2.5 (2010-08-18) +------------------ + +* Fixed: Issue 73: guessBaseUrl fails for some servers. +* Fixed: Issue 67: SabreDAV works better with non-seekable streams. +* Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if + the date is an exact match. + + +1.2.4 (2010-07-13) +------------------ + +* Fixed: Issue 62: Guessing baseUrl fails when url contains a query-string. +* Added: Apache configuration sample for CGI/FastCGI setups. +* Fixed: Issue 64: Only returning calendar-data when it was actually requested. + + +1.2.3 (2010-06-26) +------------------ + +* Fixed: Issue 57: Supporting quotes around etags in If-Match and If-None-Match + + +1.2.2 (2010-06-21) +------------------ + +* Updated: SabreDAV now attempts to guess the BaseURI if it's not set. +* Updated: Better compatibility with BitKinex +* Fixed: Issue 56: Incorrect behaviour for If-None-Match headers and GET + requests. +* Fixed: Issue with certain encoded paths in Browser Plugin. + + +1.2.1 (2010-06-07) +------------------ + +* Fixed: Issue 50, patch by Mattijs Hoitink. +* Fixed: Issue 51, Adding windows 7 lockfiles to TemporaryFileFilter. +* Fixed: Issue 38, Allowing custom filters to be added to TemporaryFileFilter. +* Fixed: Issue 53, ETags in the If: header were always failing. This behaviour + is now corrected. +* Added: Apache Authentication backend, in case authentication through .htaccess + is desired. +* Updated: Small improvements to example files. + + +1.2.0 (2010-05-24) +------------------ + +* Fixed: Browser plugin now displays international characters. +* Changed: More properties in CalDAV classes are now protected instead of + private. + + +1.2.0beta3 (2010-05-14) +----------------------- + +* Fixed: Custom properties were not properly sent back for allprops requests. +* Fixed: Issue 49, incorrect parsing of PROPPATCH, affecting Office 2007. +* Changed: Removed CalDAV items from includes.php, and added a few missing ones. + + +1.2.0beta2 (2010-05-04) +----------------------- + +* Fixed: Issue 46: Fatal error for some non-existent nodes. +* Updated: some example sql to include email address. +* Added: 208 and 508 statuscodes from RFC5842. +* Added: Apache2 configuration examples + + +1.2.0beta1 (2010-04-28) +----------------------- + +* Fixed: redundant namespace declaration in resourcetypes. +* Fixed: 2 locking bugs triggered by litmus when no Sabre_DAV_ILockable + interface is used. +* Changed: using http://sabredav.org/ns for all custom xml properties. +* Added: email address property to principals. +* Updated: CalendarObject validation. + + +1.2.0alpha4 (2010-04-24) +------------------------ + +* Added: Support for If-Range, If-Match, If-None-Match, If-Modified-Since, + If-Unmodified-Since. +* Changed: Brand new build system. Functionality is split up between Sabre, + Sabre_HTTP, Sabre_DAV and Sabre_CalDAV packages. In addition to that a new + non-pear package will be created with all this functionality combined. +* Changed: Autoloader moved to Sabre/autoload.php. +* Changed: The Allow: header is now more accurate, with appropriate HTTP methods + per uri. +* Changed: Now throwing back Sabre_DAV_Exception_MethodNotAllowed on a few + places where Sabre_DAV_Exception_NotImplemented was used. + + +1.2.0alpha3 (2010-04-20) +------------------------ + +* Update: Complete rewrite of property updating. Now easier to use and atomic. +* Fixed: Issue 16, automatically adding trailing / to baseUri. +* Added: text/plain is used for .txt files in GuessContentType plugin. +* Added: support for principal-property-search and principal-search-property-set + reports. +* Added: Issue 31: Hiding exception information by default. Can be turned on + with the Sabre_DAV_Server::$debugExceptions property. + + +1.2.0alpha2 (2010-04-08) +------------------------ + +* Added: Calendars are now private and can only be read by the owner. +* Fixed: double namespace declaration in multistatus responses. +* Added: MySQL database dumps. MySQL is now also supported next to SQLite. +* Added: expand-properties REPORT from RFC 3253. +* Added: Sabre_DAV_Property_IHref interface for properties exposing urls. +* Added: Issue 25: Throwing error on broken Finder behaviour. +* Changed: Authentication backend is now aware of current user. + + +1.2.0alpha1 (2010-03-31) +------------------------ + +* Fixed: Issue 26: Workaround for broken GVFS behaviour with encoded special + characters. +* Fixed: Issue 34: Incorrect Lock-Token response header for LOCK. Fixes Office + 2010 compatibility. +* Added: Issue 35: SabreDAV version to header to OPTIONS response to ease + debugging. +* Fixed: Issue 36: Incorrect variable name, throwing error in some requests. +* Fixed: Issue 37: Incorrect smultron regex in temporary filefilter. +* Fixed: Issue 33: Converting ISO-8859-1 characters to UTF-8. +* Fixed: Issue 39 & Issue 40: Basename fails on non-utf-8 locales. +* Added: More unittests. +* Added: SabreDAV version to all error responses. +* Added: URLUtil class for decoding urls. +* Changed: Now using pear.sabredav.org pear channel. +* Changed: Sabre_DAV_Server::getCopyAndMoveInfo is now a public method. + + +1.1.2-alpha (2010-03-18) +------------------------ + +* Added: RFC5397 - current-user-principal support. +* Fixed: Issue 27: encoding entities in property responses. +* Added: naturalselection script now allows the user to specify a 'minimum + number of bytes' for deletion. This should reduce load due to less crawling +* Added: Full support for the calendar-query report. +* Added: More unittests. +* Added: Support for complex property deserialization through the static + ::unserialize() method. +* Added: Support for modifying calendar-component-set +* Fixed: Issue 29: Added TIMEOUT_INFINITE constant + + +1.1.1-alpha (2010-03-11) +------------------------ + +* Added: RFC5689 - Extended MKCOL support. +* Fixed: Evolution support for CalDAV. +* Fixed: PDO-locks backend was pretty much completely broken. This is 100% + unittested now. +* Added: support for ctags. +* Fixed: Comma's between HTTP methods in 'Allow' method. +* Changed: default argument for Sabre_DAV_Locks_Backend_FS. This means a + datadirectory must always be specified from now on. +* Changed: Moved Sabre_DAV_Server::parseProps to + Sabre_DAV_XMLUtil::parseProperties. +* Changed: Sabre_DAV_IDirectory is now Sabre_DAV_ICollection. +* Changed: Sabre_DAV_Exception_PermissionDenied is now + Sabre_DAV_Exception_Forbidden. +* Changed: Sabre_CalDAV_ICalendarCollection is removed. +* Added: Sabre_DAV_IExtendedCollection. +* Added: Many more unittests. +* Added: support for calendar-timezone property. + + +1.1.0-alpha (2010-03-01) +------------------------ + +* Note: This version is forked from version 1.0.5, so release dates may be out + of order. +* Added: CalDAV - RFC 4791 +* Removed: Sabre_PHP_Exception. PHP has a built-in ErrorException for this. +* Added: PDO authentication backend. +* Added: Example sql for auth, caldav, locks for sqlite. +* Added: Sabre_DAV_Browser_GuessContentType plugin +* Changed: Authentication plugin refactored, making it possible to implement + non-digest authentication. +* Fixed: Better error display in browser plugin. +* Added: Support for {DAV:}supported-report-set +* Added: XML utility class with helper functions for the WebDAV protocol. +* Added: Tons of unittests +* Added: PrincipalCollection and Principal classes +* Added: Sabre_DAV_Server::getProperties for easy property retrieval +* Changed: {DAV:}resourceType defaults to 0 +* Changed: Any non-null resourceType now gets a / appended to the href value. + Before this was just for {DAV:}collection's, but this is now also the case for + for example {DAV:}principal. +* Changed: The Href property class can now optionally create non-relative uri's. +* Changed: Sabre_HTTP_Response now returns false if headers are already sent and + header-methods are called. +* Fixed: Issue 19: HEAD requests on Collections +* Fixed: Issue 21: Typo in Sabre_DAV_Property_Response +* Fixed: Issue 18: Doesn't work with Evolution Contacts + + +1.0.15 (2010-05-28) +------------------- + +* Added: Issue 31: Hiding exception information by default. Can be turned on + with the Sabre_DAV_Server::$debugExceptions property. +* Added: Moved autoload from lib/ to lib/Sabre/autoload.php. This is also the + case in the upcoming 1.2.0, so it will improve future compatibility. + + +1.0.14 (2010-04-15) +------------------- + +* Fixed: double namespace declaration in multistatus responses. + + +1.0.13 (2010-03-30) +------------------- + +* Fixed: Issue 40: Last references to basename/dirname + + +1.0.12 (2010-03-30) +------------------- + +* Fixed: Issue 37: Incorrect smultron regex in temporary filefilter. +* Fixed: Issue 26: Workaround for broken GVFS behaviour with encoded special + characters. +* Fixed: Issue 33: Converting ISO-8859-1 characters to UTF-8. +* Fixed: Issue 39: Basename fails on non-utf-8 locales. +* Added: More unittests. +* Added: SabreDAV version to all error responses. +* Added: URLUtil class for decoding urls. +* Updated: Now using pear.sabredav.org pear channel. + + +1.0.11 (2010-03-23) +------------------- + +* Non-public release. This release is identical to 1.0.10, but it is used to + test releasing packages to pear.sabredav.org. + + +1.0.10 (2010-03-22) +------------------- + +* Fixed: Issue 34: Invalid Lock-Token header response. +* Added: Issue 35: Addign SabreDAV version to HTTP OPTIONS responses. + + +1.0.9 (2010-03-19) +------------------ + +* Fixed: Issue 27: Entities not being encoded in PROPFIND responses. +* Fixed: Issue 29: Added missing TIMEOUT_INFINITE constant. + + +1.0.8 (2010-03-03) +------------------ + +* Fixed: Issue 21: typos causing errors +* Fixed: Issue 23: Comma's between methods in Allow header. +* Added: Sabre_DAV_ICollection interface, to aid in future compatibility. +* Added: Sabre_DAV_Exception_Forbidden exception. This will replace + Sabre_DAV_Exception_PermissionDenied in the future, and can already be used to + ensure future compatibility. + + +1.0.7 (2010-02-24) +------------------ + +* Fixed: Issue 19 regression for MS Office + + +1.0.6 (2010-02-23) +------------------ + +* Fixed: Issue 19: HEAD requests on Collections + + +1.0.5 (2010-01-22) +------------------ + +* Fixed: Fatal error when a malformed url was used for unlocking, in conjuction + with Sabre.autoload.php due to a incorrect filename. +* Fixed: Improved unittests and build system + + +1.0.4 (2010-01-11) +------------------ + +* Fixed: needed 2 different releases. One for googlecode and one for pearfarm. + This is to retain the old method to install SabreDAV until pearfarm becomes + the standard installation method. + + +1.0.3 (2010-01-11) +------------------ + +* Added: RFC4709 support (davmount) +* Added: 6 unittests +* Added: naturalselection. A tool to keep cache directories below a specified + theshold. +* Changed: Now using pearfarm.org channel server. + + +1.0.1 (2009-12-22) +------------------ + +* Fixed: Issue 15: typos in examples +* Fixed: Minor pear installation issues + + +1.0.0 (2009-11-02) +------------------ + +* Added: SimpleDirectory class. This class allows creating static directory + structures with ease. +* Changed: Custom complex properties and exceptions now get an instance of + Sabre_DAV_Server as their first argument in serialize() +* Changed: Href complex property now prepends server's baseUri +* Changed: delete before an overwriting copy/move is now handles by server class + instead of tree classes +* Changed: events must now explicitly return false to stop execution. Before, + execution would be stopped by anything loosely evaluating to false. +* Changed: the getPropertiesForPath method now takes a different set of + arguments, and returns a different response. This allows plugin developers to + return statuses for properties other than 200 and 404. The hrefs are now also + always calculated relative to the baseUri, and not the uri of the request. +* Changed: generatePropFindResponse is renamed to generateMultiStatus, and now + takes a list of properties similar to the response of getPropertiesForPath. + This was also needed to improve flexibility for plugin development. +* Changed: Auth plugins are no longer included. They were not yet stable + quality, so they will probably be reintroduced in a later version. +* Changed: PROPPATCH also used generateMultiStatus now. +* Removed: unknownProperties event. This is replaced by the afterGetProperties + event, which should provide more flexibility. +* Fixed: Only calling getSize() on IFile instances in httpHead() +* Added: beforeBind event. This is invoked upon file or directory creation +* Added: beforeWriteContent event, this is invoked by PUT and LOCK on an + existing resource. +* Added: beforeUnbind event. This is invoked right before deletion of any + resource. +* Added: afterGetProperties event. This event can be used to make modifications + to property responses. +* Added: beforeLock and beforeUnlock events. +* Added: afterBind event. +* Fixed: Copy and Move could fail in the root directory. This is now fixed. +* Added: Plugins can now be retrieved by their classname. This is useful for + inter-plugin communication. +* Added: The Auth backend can now return usernames and user-id's. +* Added: The Auth backend got a getUsers method +* Added: Sabre_DAV_FSExt_Directory now returns quota info + + +0.12.1-beta (2009-09-11) +------------------------ + +* Fixed: UNLOCK bug. Unlock didn't work at all + + +0.12-beta (2009-09-10) +---------------------- + +* Updated: Browser plugin now shows multiple {DAV:}resourcetype values if + available. +* Added: Experimental PDO backend for Locks Manager +* Fixed: Sending Content-Length: 0 for every empty response. This improves NGinx + compatibility. +* Fixed: Last modification time is reported in UTC timezone. This improves + Finder compatibility. + + +0.11-beta (2009-08-11) +---------------------- + +* Updated: Now in Beta +* Updated: Pear package no longer includes docs/ directory. These just contained + rfc's, which are publicly available. This reduces the package from ~800k to + ~60k +* Added: generatePropfindResponse now takes a baseUri argument +* Added: ResourceType property can now contain multiple resourcetypes. +* Fixed: Issue 13. + + +0.10-alpha (2009-08-03) +----------------------- + +* Added: Plugin to automatically map GET requests to non-files to PROPFIND + (Sabre_DAV_Browser_MapGetToPropFind). This should allow easier debugging of + complicated WebDAV setups. +* Added: Sabre_DAV_Property_Href class. For future use. +* Added: Ability to choose to use auth-int, auth or both for HTTP Digest + authentication. (Issue 11) +* Changed: Made more methods in Sabre_DAV_Server public. +* Fixed: TemporaryFileFilter plugin now intercepts HTTP LOCK requests to + non-existent files. (Issue 12) +* Added: Central list of defined xml namespace prefixes. This can reduce + Bandwidth and legibility for xml bodies with user-defined namespaces. +* Added: now a PEAR-compatible package again, thanks to Michael Gauthier +* Changed: moved default copy and move logic from ObjectTree to Tree class + +0.9a-alpha (2009-07-21) +---------------------- + +* Fixed: Broken release + +0.9-alpha (2009-07-21) +---------------------- + +* Changed: Major refactoring, removed most of the logic from the Tree objects. + The Server class now directly works with the INode, IFile and IDirectory + objects. If you created your own Tree objects, this will most likely break in + this release. +* Changed: Moved all the Locking logic from the Tree and Server classes into a + separate plugin. +* Changed: TemporaryFileFilter is now a plugin. +* Added: Comes with an autoloader script. This can be used instead of the + includer script, and is preferred by some people. +* Added: AWS Authentication class. +* Added: simpleserversetup.py script. This will quickly get a fileserver up and + running. +* Added: When subscribing to events, it is now possible to supply a priority. + This is for example needed to ensure that the Authentication Plugin is used + before any other Plugin. +* Added: 22 new tests. +* Added: Users-manager plugin for .htdigest files. Experimental and subject to + change. +* Added: RFC 2324 HTTP 418 status code +* Fixed: Exclusive locks could in some cases be picked up as shared locks +* Fixed: Digest auth for non-apache servers had a bug (still not actually tested + this well). + + +0.8-alpha (2009-05-30) +---------------------- + +* Changed: Renamed all exceptions! This is a compatibility break. Every + Exception now follows Sabre_DAV_Exception_FileNotFound convention instead of + Sabre_DAV_FileNotFoundException. +* Added: Browser plugin now allows uploading and creating directories straight + from the browser. +* Added: 12 more unittests +* Fixed: Locking bug, which became prevalent on Windows Vista. +* Fixed: Netdrive support +* Fixed: TemporaryFileFilter filtered out too many files. Fixed some of the + regexes. +* Fixed: Added README and ChangeLog to package + + +0.7-alpha (2009-03-29) +---------------------- + +* Added: System to return complex properties from PROPFIND. +* Added: support for {DAV:}supportedlock. +* Added: support for {DAV:}lockdiscovery. +* Added: 6 new tests. +* Added: New plugin system. +* Added: Simple HTML directory plugin, for browser access. +* Added: Server class now sends back standard pre-condition error xml bodies. + This was new since RFC4918. +* Added: Sabre_DAV_Tree_Aggregrate, which can 'host' multiple Tree objects into + one. +* Added: simple basis for HTTP REPORT method. This method is not used yet, but + can be used by plugins to add reports. +* Changed: ->getSize is only called for files, no longer for collections. r303 +* Changed: Sabre_DAV_FilterTree is now Sabre_DAV_Tree_Filter +* Changed: Sabre_DAV_TemporaryFileFilter is now called + Sabre_DAV_Tree_TemporaryFileFilter. +* Changed: removed functions (get(/set)HTTPRequest(/Response)) from Server + class, and using a public property instead. +* Fixed: bug related to parsing proppatch and propfind requests. Didn't show up + in most clients, but it needed fixing regardless. (r255) +* Fixed: auth-int is now properly supported within HTTP Digest. +* Fixed: Using application/xml for a mimetype vs. text/xml as per RFC4918 sec + 8.2. +* Fixed: TemporaryFileFilter now lets through GET's if they actually exist on + the backend. (r274) +* FIxed: Some methods didn't get passed through in the FilterTree (r283). +* Fixed: LockManager is now slightly more complex, Tree classes slightly less. + (r287) + + +0.6-alpha (2009-02-16) +---------------------- + +* Added: Now uses streams for files, instead of strings. This means it won't + require to hold entire files in memory, which can be an issue if you're + dealing with big files. Note that this breaks compatibility for put() and + createFile methods. +* Added: HTTP Digest Authentication helper class. +* Added: Support for HTTP Range header +* Added: Support for ETags within If: headers +* Added: The API can now return ETags and override the default Content-Type +* Added: starting with basic framework for unittesting, using PHPUnit. +* Added: 49 unittests. +* Added: Abstraction for the HTTP request. +* Updated: Using Clark Notation for tags in properties. This means tags are + serialized as {namespace}tagName instead of namespace#tagName +* Fixed: HTTP_BasicAuth class now works as expected. +* Fixed: DAV_Server uses / for a default baseUrl. +* Fixed: Last modification date is no longer ignored in PROPFIND. +* Fixed: PROPFIND now sends back information about the requestUri even when + "Depth: 1" is specified. + + +0.5-alpha (2009-01-14) +---------------------- + +* Added: Added a very simple example for implementing a mapping to PHP file + streams. This should allow easy implementation of for example a WebDAV to FTP + proxy. +* Added: HTTP Basic Authentication helper class. +* Added: Sabre_HTTP_Response class. This centralizes HTTP operations and will be + a start towards the creating of a testing framework. +* Updated: Backwards compatibility break: all require_once() statements are + removed from all the files. It is now recommended to use autoloading of + classes, or just including lib/Sabre.includes.php. This fix was made to allow + easier integration into applications not using this standard inclusion model. +* Updated: Better in-file documentation. +* Updated: Sabre_DAV_Tree can now work with Sabre_DAV_LockManager. +* Updated: Fixes a shared-lock bug. +* Updated: Removed ?> from the bottom of each php file. +* Updated: Split up some operations from Sabre_DAV_Server to + Sabre_HTTP_Response. +* Fixed: examples are now actually included in the pear package. + + +0.4-alpha (2008-11-05) +---------------------- + +* Passes all litmus tests! +* Added: more examples +* Added: Custom property support +* Added: Shared lock support +* Added: Depth support to locks +* Added: Locking on unmapped urls (non-existent nodes) +* Fixed: Advertising as WebDAV class 3 support + + +0.3-alpha (2008-06-29) +---------------------- + +* Fully working in MS Windows clients. +* Added: temporary file filter: support for smultron files. +* Added: Phing build scripts +* Added: PEAR package +* Fixed: MOVE bug identified using finder. +* Fixed: Using gzuncompress instead of gzdecode in the temporary file filter. + This seems more common. + + +0.2-alpha (2008-05-27) +---------------------- + +* Somewhat working in Windows clients +* Added: Working PROPPATCH method (doesn't support custom properties yet) +* Added: Temporary filename handling system +* Added: Sabre_DAV_IQuota to return quota information +* Added: PROPFIND now reads the request body and only supplies the requested + properties + + +0.1-alpha (2008-04-04) +---------------------- + +* First release! +* Passes litmus: basic, http and copymove test. +* Fully working in Finder and DavFS2. + +Project started: 2007-12-13 + +[vobj]: http://sabre.io/vobject/ +[evnt]: http://sabre.io/event/ +[http]: http://sabre.io/http/ +[uri]: http://sabre.io/uri/ +[xml]: http://sabre.io/xml/ +[mi20]: http://sabre.io/dav/upgrade/1.8-to-2.0/ +[rfc6638]: http://tools.ietf.org/html/rfc6638 "CalDAV Scheduling" +[rfc7240]: http://tools.ietf.org/html/rfc7240 +[calendar-availability]: https://tools.ietf.org/html/draft-daboo-calendar-availability-05 diff --git a/vendor/LICENSE b/vendor/LICENSE new file mode 100644 index 000000000..fd3539e33 --- /dev/null +++ b/vendor/LICENSE @@ -0,0 +1,27 @@ +Copyright (C) 2007-2016 fruux GmbH (https://fruux.com/). + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of SabreDAV nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/README.md b/vendor/README.md new file mode 100644 index 000000000..8edcd4073 --- /dev/null +++ b/vendor/README.md @@ -0,0 +1,36 @@ +![sabre's logo](http://sabre.io/img/logo.png) sabre/dav +======================================================= + +Introduction +------------ + +sabre/dav is the most popular WebDAV framework for PHP. Use it to create WebDAV, CalDAV and CardDAV servers. + +Full documentation can be found on the website: + +http://sabre.io/ + +Build status +------------ + +| branch | status | minimum PHP version | +| ------------ | ------ | ------------------- | +| master | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=master)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 | +| 3.1 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=3.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 | +| 3.0 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=3.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | +| 2.1 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=2.1)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | +| 2.0 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=2.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | +| 1.8 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.8)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | +| 1.7 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.7)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | +| 1.6 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.6)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | + +Documentation +------------- + +* [Introduction](http://sabre.io/dav/). +* [Installation](http://sabre.io/dav/install/). + +Made at fruux +------------- + +SabreDAV is being developed by [fruux](https://fruux.com/). Drop us a line for commercial services or enterprise support. diff --git a/vendor/examples/addressbookserver.php b/vendor/examples/addressbookserver.php new file mode 100644 index 000000000..6d1c9b26c --- /dev/null +++ b/vendor/examples/addressbookserver.php @@ -0,0 +1,57 @@ +<?php + +/* + +Addressbook/CardDAV server example + +This server features CardDAV support + +*/ + +// settings +date_default_timezone_set('Canada/Eastern'); + +// Make sure this setting is turned on and reflect the root url for your WebDAV server. +// This can be for example the root / or a complete path to your server script +$baseUri = '/'; + +/* Database */ +$pdo = new PDO('sqlite:data/db.sqlite'); +$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +//Mapping PHP errors to exceptions +function exception_error_handler($errno, $errstr, $errfile, $errline) { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); +} +set_error_handler("exception_error_handler"); + +// Autoloader +require_once 'vendor/autoload.php'; + +// Backends +$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo); +$principalBackend = new Sabre\DAVACL\PrincipalBackend\PDO($pdo); +$carddavBackend = new Sabre\CardDAV\Backend\PDO($pdo); +//$caldavBackend = new Sabre\CalDAV\Backend\PDO($pdo); + +// Setting up the directory tree // +$nodes = [ + new Sabre\DAVACL\PrincipalCollection($principalBackend), +// 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)); +$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(); diff --git a/vendor/examples/calendarserver.php b/vendor/examples/calendarserver.php new file mode 100644 index 000000000..e5f9f3387 --- /dev/null +++ b/vendor/examples/calendarserver.php @@ -0,0 +1,76 @@ +<?php + +/* + +CalendarServer example + +This server features CalDAV support + +*/ + +// settings +date_default_timezone_set('Canada/Eastern'); + +// If you want to run the SabreDAV server in a custom location (using mod_rewrite for instance) +// You can override the baseUri here. +// $baseUri = '/'; + +/* Database */ +$pdo = new PDO('sqlite:data/db.sqlite'); +$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +//Mapping PHP errors to exceptions +function exception_error_handler($errno, $errstr, $errfile, $errline) { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); +} +set_error_handler("exception_error_handler"); + +// Files we need +require_once 'vendor/autoload.php'; + +// Backends +$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo); +$calendarBackend = new Sabre\CalDAV\Backend\PDO($pdo); +$principalBackend = new Sabre\DAVACL\PrincipalBackend\PDO($pdo); + +// Directory structure +$tree = [ + new Sabre\CalDAV\Principal\Collection($principalBackend), + new Sabre\CalDAV\CalendarRoot($principalBackend, $calendarBackend), +]; + +$server = new Sabre\DAV\Server($tree); + +if (isset($baseUri)) + $server->setBaseUri($baseUri); + +/* Server Plugins */ +$authPlugin = new Sabre\DAV\Auth\Plugin($authBackend); +$server->addPlugin($authPlugin); + +$aclPlugin = new Sabre\DAVACL\Plugin(); +$server->addPlugin($aclPlugin); + +/* CalDAV support */ +$caldavPlugin = new Sabre\CalDAV\Plugin(); +$server->addPlugin($caldavPlugin); + +/* Calendar subscription support */ +$server->addPlugin( + new Sabre\CalDAV\Subscriptions\Plugin() +); + +/* Calendar scheduling support */ +$server->addPlugin( + new Sabre\CalDAV\Schedule\Plugin() +); + +/* WebDAV-Sync plugin */ +$server->addPlugin(new Sabre\DAV\Sync\Plugin()); + +// Support for html frontend +$browser = new Sabre\DAV\Browser\Plugin(); +$server->addPlugin($browser); + +// And off we go! +$server->exec(); diff --git a/vendor/examples/fileserver.php b/vendor/examples/fileserver.php new file mode 100644 index 000000000..59a453f63 --- /dev/null +++ b/vendor/examples/fileserver.php @@ -0,0 +1,56 @@ +<?php + +/* + +This is the best starting point if you're just interested in setting up a fileserver. + +Make sure that the 'public' and 'tmpdata' exists, with write permissions +for your server. + +*/ + +// settings +date_default_timezone_set('Canada/Eastern'); +$publicDir = 'public'; +$tmpDir = 'tmpdata'; + +// If you want to run the SabreDAV server in a custom location (using mod_rewrite for instance) +// You can override the baseUri here. +// $baseUri = '/'; + + +// Files we need +require_once 'vendor/autoload.php'; + +// Create the root node +$root = new \Sabre\DAV\FS\Directory($publicDir); + +// The rootnode needs in turn to be passed to the server class +$server = new \Sabre\DAV\Server($root); + +if (isset($baseUri)) + $server->setBaseUri($baseUri); + +// Support for LOCK and UNLOCK +$lockBackend = new \Sabre\DAV\Locks\Backend\File($tmpDir . '/locksdb'); +$lockPlugin = new \Sabre\DAV\Locks\Plugin($lockBackend); +$server->addPlugin($lockPlugin); + +// Support for html frontend +$browser = new \Sabre\DAV\Browser\Plugin(); +$server->addPlugin($browser); + +// Automatically guess (some) contenttypes, based on extesion +$server->addPlugin(new \Sabre\DAV\Browser\GuessContentType()); + +// Authentication backend +$authBackend = new \Sabre\DAV\Auth\Backend\File('.htdigest'); +$auth = new \Sabre\DAV\Auth\Plugin($authBackend); +$server->addPlugin($auth); + +// Temporary file filter +$tempFF = new \Sabre\DAV\TemporaryFileFilterPlugin($tmpDir); +$server->addPlugin($tempFF); + +// And off we go! +$server->exec(); diff --git a/vendor/examples/groupwareserver.php b/vendor/examples/groupwareserver.php new file mode 100644 index 000000000..40c1844da --- /dev/null +++ b/vendor/examples/groupwareserver.php @@ -0,0 +1,101 @@ +<?php + +/** + * This server combines both CardDAV and CalDAV functionality into a single + * server. It is assumed that the server runs at the root of a HTTP domain (be + * that a domainname-based vhost or a specific TCP port. + * + * This example also assumes that you're using SQLite and the database has + * already been setup (along with the database tables). + * + * You may choose to use MySQL instead, just change the PDO connection + * statement. + */ + +/** + * UTC or GMT is easy to work with, and usually recommended for any + * application. + */ +date_default_timezone_set('UTC'); + +/** + * Make sure this setting is turned on and reflect the root url for your WebDAV + * server. + * + * This can be for example the root / or a complete path to your server script. + */ +// $baseUri = '/'; + +/** + * Database + * + * Feel free to switch this to MySQL, it will definitely be better for higher + * concurrency. + */ +$pdo = new \PDO('sqlite:data/db.sqlite'); +$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +/** + * Mapping PHP errors to exceptions. + * + * While this is not strictly needed, it makes a lot of sense to do so. If an + * E_NOTICE or anything appears in your code, this allows SabreDAV to intercept + * the issue and send a proper response back to the client (HTTP/1.1 500). + */ +function exception_error_handler($errno, $errstr, $errfile, $errline) { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); +} +set_error_handler("exception_error_handler"); + +// Autoloader +require_once 'vendor/autoload.php'; + +/** + * The backends. Yes we do really need all of them. + * + * This allows any developer to subclass just any of them and hook into their + * own backend systems. + */ +$authBackend = new \Sabre\DAV\Auth\Backend\PDO($pdo); +$principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo); +$carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo); +$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo); + +/** + * The directory tree + * + * Basically this is an array which contains the 'top-level' directories in the + * WebDAV server. + */ +$nodes = [ + // /principals + new \Sabre\CalDAV\Principal\Collection($principalBackend), + // /calendars + new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend), + // /addressbook + 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); +if (isset($baseUri)) $server->setBaseUri($baseUri); + +// Plugins +$server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend)); +$server->addPlugin(new \Sabre\DAV\Browser\Plugin()); +$server->addPlugin(new \Sabre\DAV\Sync\Plugin()); +$server->addPlugin(new \Sabre\DAV\Sharing\Plugin()); +$server->addPlugin(new \Sabre\DAVACL\Plugin()); + +// CalDAV plugins +$server->addPlugin(new \Sabre\CalDAV\Plugin()); +$server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); +$server->addPlugin(new \Sabre\CalDAV\SharingPlugin()); +$server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); + +// CardDAV plugins +$server->addPlugin(new \Sabre\CardDAV\Plugin()); +$server->addPlugin(new \Sabre\CardDAV\VCFExportPlugin()); + +// And off we go! +$server->exec(); diff --git a/vendor/examples/minimal.php b/vendor/examples/minimal.php new file mode 100644 index 000000000..4ac256064 --- /dev/null +++ b/vendor/examples/minimal.php @@ -0,0 +1,20 @@ +<?php + +/** + * This example shows the smallest possible sabre/dav server. + */ +include 'vendor/autoload.php'; + +$server = new Sabre\DAV\Server([ + new Sabre\DAV\FS\Directory(__DIR__) +]); + +/** + * Ok. Perhaps not the smallest possible. The browser plugin is 100% optional, + * but it really helps understanding the server. + */ +$server->addPlugin( + new Sabre\DAV\Browser\Plugin() +); + +$server->exec(); diff --git a/vendor/examples/sql/mysql.addressbooks.sql b/vendor/examples/sql/mysql.addressbooks.sql new file mode 100644 index 000000000..9ec88babe --- /dev/null +++ b/vendor/examples/sql/mysql.addressbooks.sql @@ -0,0 +1,28 @@ +CREATE TABLE addressbooks ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + principaluri VARBINARY(255), + displayname VARCHAR(255), + uri VARBINARY(200), + description TEXT, + 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 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; diff --git a/vendor/examples/sql/mysql.calendars.sql b/vendor/examples/sql/mysql.calendars.sql new file mode 100644 index 000000000..21c5bcb44 --- /dev/null +++ b/vendor/examples/sql/mysql.calendars.sql @@ -0,0 +1,76 @@ +CREATE TABLE calendarobjects ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + calendardata MEDIUMBLOB, + uri VARBINARY(200), + calendarid INTEGER UNSIGNED NOT NULL, + lastmodified INT(11) UNSIGNED, + etag VARBINARY(32), + size INT(11) UNSIGNED NOT NULL, + componenttype VARBINARY(8), + firstoccurence INT(11) UNSIGNED, + lastoccurence INT(11) UNSIGNED, + uid VARBINARY(200), + UNIQUE(calendarid, uri), + INDEX calendarid_time (calendarid, firstoccurence) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE calendars ( + id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1', + components VARBINARY(21) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE calendarinstances ( + id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + calendarid INTEGER UNSIGNED NOT NULL, + principaluri VARBINARY(100), + access TINYINT(1) NOT NULL DEFAULT '1' COMMENT '1 = owner, 2 = read, 3 = readwrite', + displayname VARCHAR(100), + uri VARBINARY(200), + description TEXT, + calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', + calendarcolor VARBINARY(10), + timezone TEXT, + transparent TINYINT(1) NOT NULL DEFAULT '0', + share_href VARBINARY(100), + share_displayname VARCHAR(100), + share_invitestatus TINYINT(1) NOT NULL DEFAULT '2' COMMENT '1 = noresponse, 2 = accepted, 3 = declined, 4 = invalid', + UNIQUE(principaluri, uri), + UNIQUE(calendarid, principaluri), + UNIQUE(calendarid, share_href) +) 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; diff --git a/vendor/examples/sql/mysql.locks.sql b/vendor/examples/sql/mysql.locks.sql new file mode 100644 index 000000000..96a3a88d9 --- /dev/null +++ b/vendor/examples/sql/mysql.locks.sql @@ -0,0 +1,12 @@ +CREATE TABLE locks ( + id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + owner VARCHAR(100), + timeout INTEGER UNSIGNED, + created INTEGER, + token VARBINARY(100), + scope TINYINT, + depth TINYINT, + uri VARBINARY(1000), + INDEX(token), + INDEX(uri(100)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/vendor/examples/sql/mysql.principals.sql b/vendor/examples/sql/mysql.principals.sql new file mode 100644 index 000000000..ea0d16a27 --- /dev/null +++ b/vendor/examples/sql/mysql.principals.sql @@ -0,0 +1,20 @@ +CREATE TABLE principals ( + id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + uri VARBINARY(200) NOT NULL, + email VARBINARY(80), + displayname VARCHAR(80), + 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'), +('principals/admin/calendar-proxy-read', null, null), +('principals/admin/calendar-proxy-write', null, null); + diff --git a/vendor/examples/sql/mysql.propertystorage.sql b/vendor/examples/sql/mysql.propertystorage.sql new file mode 100644 index 000000000..1b5ca5ac6 --- /dev/null +++ b/vendor/examples/sql/mysql.propertystorage.sql @@ -0,0 +1,9 @@ +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 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE UNIQUE INDEX path_property ON propertystorage (path(600), name(100)); diff --git a/vendor/examples/sql/mysql.users.sql b/vendor/examples/sql/mysql.users.sql new file mode 100644 index 000000000..22ac312d5 --- /dev/null +++ b/vendor/examples/sql/mysql.users.sql @@ -0,0 +1,9 @@ +CREATE TABLE users ( + id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + username VARBINARY(50), + digesta1 VARBINARY(32), + UNIQUE(username) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +INSERT INTO users (username,digesta1) VALUES +('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/examples/sql/pgsql.addressbooks.sql b/vendor/examples/sql/pgsql.addressbooks.sql new file mode 100644 index 000000000..98f414f42 --- /dev/null +++ b/vendor/examples/sql/pgsql.addressbooks.sql @@ -0,0 +1,44 @@ +CREATE TABLE addressbooks ( + id SERIAL NOT NULL, + principaluri VARCHAR(255), + displayname VARCHAR(255), + uri VARCHAR(200), + description TEXT, + synctoken INTEGER NOT NULL DEFAULT 1 +); + +ALTER TABLE ONLY addressbooks + ADD CONSTRAINT addressbooks_pkey PRIMARY KEY (id); + +CREATE UNIQUE INDEX addressbooks_ukey + ON addressbooks USING btree (principaluri, uri); + +CREATE TABLE cards ( + id SERIAL NOT NULL, + addressbookid INTEGER NOT NULL, + carddata BYTEA, + uri VARCHAR(200), + lastmodified INTEGER, + etag VARCHAR(32), + size INTEGER NOT NULL +); + +ALTER TABLE ONLY cards + ADD CONSTRAINT cards_pkey PRIMARY KEY (id); + +CREATE UNIQUE INDEX cards_ukey + ON cards USING btree (addressbookid, uri); + +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); diff --git a/vendor/examples/sql/pgsql.calendars.sql b/vendor/examples/sql/pgsql.calendars.sql new file mode 100644 index 000000000..67dc41a5a --- /dev/null +++ b/vendor/examples/sql/pgsql.calendars.sql @@ -0,0 +1,105 @@ +CREATE TABLE calendarobjects ( + id SERIAL NOT NULL, + calendardata BYTEA, + uri VARCHAR(200), + calendarid INTEGER NOT NULL, + lastmodified INTEGER, + etag VARCHAR(32), + size INTEGER NOT NULL, + componenttype VARCHAR(8), + firstoccurence INTEGER, + lastoccurence INTEGER, + uid VARCHAR(200) +); + +ALTER TABLE ONLY calendarobjects + ADD CONSTRAINT calendarobjects_pkey PRIMARY KEY (id); + +CREATE UNIQUE INDEX calendarobjects_ukey + ON calendarobjects USING btree (calendarid, uri); + + +CREATE TABLE calendars ( + id SERIAL NOT NULL, + synctoken INTEGER NOT NULL DEFAULT 1, + components VARCHAR(21) +); + +ALTER TABLE ONLY calendars + ADD CONSTRAINT calendars_pkey PRIMARY KEY (id); + + +CREATE TABLE calendarinstances ( + id SERIAL NOT NULL, + calendarid INTEGER NOT NULL, + principaluri VARCHAR(100), + access SMALLINT NOT NULL DEFAULT '1', -- '1 = owner, 2 = read, 3 = readwrite' + displayname VARCHAR(100), + uri VARCHAR(200), + description TEXT, + calendarorder INTEGER NOT NULL DEFAULT 0, + calendarcolor VARCHAR(10), + timezone TEXT, + transparent SMALLINT NOT NULL DEFAULT '0', + share_href VARCHAR(100), + share_displayname VARCHAR(100), + share_invitestatus SMALLINT NOT NULL DEFAULT '2' -- '1 = noresponse, 2 = accepted, 3 = declined, 4 = invalid' +); + +ALTER TABLE ONLY calendarinstances + ADD CONSTRAINT calendarinstances_pkey PRIMARY KEY (id); + +CREATE UNIQUE INDEX calendarinstances_principaluri_uri + ON calendarinstances USING btree (principaluri, uri); + + +CREATE UNIQUE INDEX calendarinstances_principaluri_calendarid + ON calendarinstances USING btree (principaluri, calendarid); + +CREATE UNIQUE INDEX calendarinstances_principaluri_share_href + ON calendarinstances USING btree (principaluri, share_href); + +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); + +CREATE TABLE schedulingobjects ( + id SERIAL NOT NULL, + principaluri VARCHAR(255), + calendardata BYTEA, + uri VARCHAR(200), + lastmodified INTEGER, + etag VARCHAR(32), + size INTEGER NOT NULL +); diff --git a/vendor/examples/sql/pgsql.locks.sql b/vendor/examples/sql/pgsql.locks.sql new file mode 100644 index 000000000..0290528ce --- /dev/null +++ b/vendor/examples/sql/pgsql.locks.sql @@ -0,0 +1,19 @@ +CREATE TABLE locks ( + id SERIAL NOT NULL, + owner VARCHAR(100), + timeout INTEGER, + created INTEGER, + token VARCHAR(100), + 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); diff --git a/vendor/examples/sql/pgsql.principals.sql b/vendor/examples/sql/pgsql.principals.sql new file mode 100644 index 000000000..5a65260a2 --- /dev/null +++ b/vendor/examples/sql/pgsql.principals.sql @@ -0,0 +1,30 @@ +CREATE TABLE principals ( + id SERIAL NOT NULL, + uri VARCHAR(200) NOT NULL, + email VARCHAR(80), + displayname VARCHAR(80) +); + +ALTER TABLE ONLY principals + ADD CONSTRAINT principals_pkey PRIMARY KEY (id); + +CREATE UNIQUE INDEX principals_ukey + ON principals USING btree (uri); + +CREATE TABLE groupmembers ( + id SERIAL NOT NULL, + principal_id INTEGER NOT NULL, + member_id INTEGER NOT NULL +); + +ALTER TABLE ONLY groupmembers + ADD CONSTRAINT groupmembers_pkey PRIMARY KEY (id); + +CREATE UNIQUE INDEX groupmembers_ukey + ON groupmembers USING btree (principal_id, member_id); + +INSERT INTO principals (uri,email,displayname) VALUES +('principals/admin', 'admin@example.org','Administrator'), +('principals/admin/calendar-proxy-read', null, null), +('principals/admin/calendar-proxy-write', null, null); + diff --git a/vendor/examples/sql/pgsql.propertystorage.sql b/vendor/examples/sql/pgsql.propertystorage.sql new file mode 100644 index 000000000..d1463faae --- /dev/null +++ b/vendor/examples/sql/pgsql.propertystorage.sql @@ -0,0 +1,13 @@ +CREATE TABLE propertystorage ( + id SERIAL NOT NULL, + path VARCHAR(1024) NOT NULL, + name VARCHAR(100) NOT NULL, + valuetype INT, + value BYTEA +); + +ALTER TABLE ONLY propertystorage + ADD CONSTRAINT propertystorage_pkey PRIMARY KEY (id); + +CREATE UNIQUE INDEX propertystorage_ukey + ON propertystorage (path, name); diff --git a/vendor/examples/sql/pgsql.users.sql b/vendor/examples/sql/pgsql.users.sql new file mode 100644 index 000000000..9d6047b8c --- /dev/null +++ b/vendor/examples/sql/pgsql.users.sql @@ -0,0 +1,14 @@ +CREATE TABLE users ( + id SERIAL NOT NULL, + username VARCHAR(50), + digesta1 VARCHAR(32) +); + +ALTER TABLE ONLY users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); + +CREATE UNIQUE INDEX users_ukey + ON users USING btree (username); + +INSERT INTO users (username,digesta1) VALUES +('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/examples/sql/sqlite.addressbooks.sql b/vendor/examples/sql/sqlite.addressbooks.sql new file mode 100644 index 000000000..0baed8bfb --- /dev/null +++ b/vendor/examples/sql/sqlite.addressbooks.sql @@ -0,0 +1,28 @@ +CREATE TABLE addressbooks ( + id integer primary key asc NOT NULL, + principaluri text NOT NULL, + displayname text, + uri text NOT NULL, + description text, + synctoken integer DEFAULT 1 NOT NULL +); + +CREATE TABLE cards ( + id integer primary key asc NOT NULL, + addressbookid integer NOT NULL, + carddata blob, + 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); diff --git a/vendor/examples/sql/sqlite.calendars.sql b/vendor/examples/sql/sqlite.calendars.sql new file mode 100644 index 000000000..1c8070496 --- /dev/null +++ b/vendor/examples/sql/sqlite.calendars.sql @@ -0,0 +1,76 @@ +CREATE TABLE calendarobjects ( + 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, + uid text +); + +CREATE TABLE calendars ( + id integer primary key asc NOT NULL, + synctoken integer DEFAULT 1 NOT NULL, + components text NOT NULL +); + +CREATE TABLE calendarinstances ( + id integer primary key asc NOT NULL, + calendarid integer NOT NULL, + principaluri text NULL, + access integer COMMENT '1 = owner, 2 = read, 3 = readwrite' NOT NULL DEFAULT '1', + displayname text, + uri text NOT NULL, + description text, + calendarorder integer, + calendarcolor text, + timezone text, + transparent bool, + share_href text, + share_displayname text, + share_invitestatus integer DEFAULT '2', + UNIQUE (principaluri, uri), + UNIQUE (calendarid, principaluri), + UNIQUE (calendarid, share_href) +); + +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); diff --git a/vendor/examples/sql/sqlite.locks.sql b/vendor/examples/sql/sqlite.locks.sql new file mode 100644 index 000000000..622baea42 --- /dev/null +++ b/vendor/examples/sql/sqlite.locks.sql @@ -0,0 +1,12 @@ +BEGIN TRANSACTION; +CREATE TABLE locks ( + id integer primary key asc NOT NULL, + owner text, + timeout integer, + created integer, + token text, + scope integer, + depth integer, + uri text +); +COMMIT; diff --git a/vendor/examples/sql/sqlite.principals.sql b/vendor/examples/sql/sqlite.principals.sql new file mode 100644 index 000000000..4105156f8 --- /dev/null +++ b/vendor/examples/sql/sqlite.principals.sql @@ -0,0 +1,20 @@ +CREATE TABLE principals ( + id INTEGER PRIMARY KEY ASC NOT NULL, + uri TEXT NOT NULL, + email TEXT, + displayname TEXT, + UNIQUE(uri) +); + +CREATE TABLE groupmembers ( + id INTEGER PRIMARY KEY ASC NOT NULL, + principal_id INTEGER NOT NULL, + member_id INTEGER NOT NULL, + UNIQUE(principal_id, member_id) +); + + +INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin', 'admin@example.org','Administrator'); +INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-read', null, null); +INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-write', null, null); + diff --git a/vendor/examples/sql/sqlite.propertystorage.sql b/vendor/examples/sql/sqlite.propertystorage.sql new file mode 100644 index 000000000..72e860ce3 --- /dev/null +++ b/vendor/examples/sql/sqlite.propertystorage.sql @@ -0,0 +1,10 @@ +CREATE TABLE propertystorage ( + id integer primary key asc NOT NULL, + path text NOT NULL, + name text NOT NULL, + valuetype integer NOT NULL, + value string +); + + +CREATE UNIQUE INDEX path_property ON propertystorage (path, name); diff --git a/vendor/examples/sql/sqlite.users.sql b/vendor/examples/sql/sqlite.users.sql new file mode 100644 index 000000000..5597b058a --- /dev/null +++ b/vendor/examples/sql/sqlite.users.sql @@ -0,0 +1,9 @@ +CREATE TABLE users ( + id integer primary key asc NOT NULL, + username TEXT NOT NULL, + digesta1 TEXT NOT NULL, + UNIQUE(username) +); + +INSERT INTO users (username,digesta1) VALUES +('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/examples/webserver/apache2_htaccess.conf b/vendor/examples/webserver/apache2_htaccess.conf new file mode 100644 index 000000000..c5f29ba80 --- /dev/null +++ b/vendor/examples/webserver/apache2_htaccess.conf @@ -0,0 +1,16 @@ +RewriteEngine On +# This makes every request go to server.php +RewriteRule (.*) server.php [L] + +# Output buffering needs to be off, to prevent high memory usage +php_flag output_buffering off + +# 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 diff --git a/vendor/examples/webserver/apache2_vhost.conf b/vendor/examples/webserver/apache2_vhost.conf new file mode 100644 index 000000000..74289641e --- /dev/null +++ b/vendor/examples/webserver/apache2_vhost.conf @@ -0,0 +1,29 @@ +# This is a sample configuration to setup a dedicated Apache vhost for WebDAV. +# +# The main thing that should be configured is the servername, and the path to +# your SabreDAV installation (DocumentRoot). +# +# This configuration assumed mod_php5 is used, as it sets a few default php +# settings as well. +<VirtualHost *:*> + + # Don't forget to change the server name + # ServerName dav.example.org + + # The DocumentRoot is also required + # DocumentRoot /home/sabredav/ + + RewriteEngine On + # This makes every request go to server.php + RewriteRule ^/(.*)$ /server.php [L] + + # Output buffering needs to be off, to prevent high memory usage + php_flag output_buffering off + + # This is also to prevent high memory usage + php_flag always_populate_raw_post_data off + + # SabreDAV is not compatible with mbstring function overloading + php_flag mbstring.func_overload off + +</VirtualHost *:*> diff --git a/vendor/examples/webserver/apache2_vhost_cgi.conf b/vendor/examples/webserver/apache2_vhost_cgi.conf new file mode 100644 index 000000000..607254c6e --- /dev/null +++ b/vendor/examples/webserver/apache2_vhost_cgi.conf @@ -0,0 +1,21 @@ +# This is a sample configuration to setup a dedicated Apache vhost for WebDAV. +# +# The main thing that should be configured is the servername, and the path to +# your SabreDAV installation (DocumentRoot). +# +# This configuration assumes CGI or FastCGI is used. +<VirtualHost *:*> + + # Don't forget to change the server name + # ServerName dav.example.org + + # The DocumentRoot is also required + # DocumentRoot /home/sabredav/ + + # This makes every request go to server.php. This also makes sure + # the Authentication information is available. If your server script is + # not called server.php, be sure to change it. + RewriteEngine On + RewriteRule ^/(.*)$ /server.php [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + +</VirtualHost *:*> diff --git a/vendor/sabre/dav/bin/migrateto17.php b/vendor/sabre/dav/bin/migrateto17.php deleted file mode 100755 index 3ccf0a380..000000000 --- a/vendor/sabre/dav/bin/migrateto17.php +++ /dev/null @@ -1,284 +0,0 @@ -#!/usr/bin/env php -<?php - -echo "SabreDAV migrate script for version 1.7\n"; - -if ($argc<2) { - - echo <<<HELLO - -This script help you migrate from a pre-1.7 database to 1.7 and later\n -Both the 'calendarobjects' and 'calendars' tables will be upgraded. - -If you do not have this table, or don't use the default PDO CalDAV backend -it's pointless to run this script. - -Keep in mind that some processing will be done on every single record of this -table and in addition, ALTER TABLE commands will be executed. -If you have a large calendarobjects table, this may mean that this process -takes a while. - -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 = array( - __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); - -echo "Validating existing table layout\n"; - -// The only cross-db way to do this, is to just fetch a single record. -$row = $pdo->query("SELECT * FROM calendarobjects LIMIT 1")->fetch(); - -if (!$row) { - echo "Error: This database did not have any records in the calendarobjects table, you should just recreate the table.\n"; - exit(-1); -} - -$requiredFields = array( - 'id', - 'calendardata', - 'uri', - 'calendarid', - 'lastmodified', -); - -foreach($requiredFields as $requiredField) { - if (!array_key_exists($requiredField,$row)) { - echo "Error: The current 'calendarobjects' table was missing a field we expected to exist.\n"; - echo "For safety reasons, this process is stopped.\n"; - exit(-1); - } -} - -$fields17 = array( - 'etag', - 'size', - 'componenttype', - 'firstoccurence', - 'lastoccurence', -); - -$found = 0; -foreach($fields17 as $field) { - if (array_key_exists($field, $row)) { - $found++; - } -} - -if ($found === 0) { - echo "The database had the 1.6 schema. Table will now be altered.\n"; - echo "This may take some time for large tables\n"; - - switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) { - - case 'mysql' : - - $pdo->exec(<<<SQL -ALTER TABLE calendarobjects -ADD etag VARCHAR(32), -ADD size INT(11) UNSIGNED, -ADD componenttype VARCHAR(8), -ADD firstoccurence INT(11) UNSIGNED, -ADD lastoccurence INT(11) UNSIGNED -SQL - ); - break; - case 'sqlite' : - $pdo->exec('ALTER TABLE calendarobjects ADD etag text'); - $pdo->exec('ALTER TABLE calendarobjects ADD size integer'); - $pdo->exec('ALTER TABLE calendarobjects ADD componenttype TEXT'); - $pdo->exec('ALTER TABLE calendarobjects ADD firstoccurence integer'); - $pdo->exec('ALTER TABLE calendarobjects ADD lastoccurence integer'); - break; - - default : - die('This upgrade script does not support this driver (' . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . ")\n"); - - } - echo "Database schema upgraded.\n"; - -} elseif ($found === 5) { - - echo "Database already had the 1.7 schema\n"; - -} else { - - echo "The database had $found out of 5 from the changes for 1.7. This is scary and unusual, so we have to abort.\n"; - echo "You can manually try to upgrade the schema, and then run this script again.\n"; - exit(-1); - -} - -echo "Now, we need to parse every record and pull out some information.\n"; - -$result = $pdo->query('SELECT id, calendardata FROM calendarobjects'); -$stmt = $pdo->prepare('UPDATE calendarobjects SET etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ? WHERE id = ?'); - -echo "Total records found: " . $result->rowCount() . "\n"; -$done = 0; -$total = $result->rowCount(); -while($row = $result->fetch()) { - - try { - $newData = getDenormalizedData($row['calendardata']); - } catch (Exception $e) { - echo "===\nException caught will trying to parser calendarobject.\n"; - echo "Error message: " . $e->getMessage() . "\n"; - echo "Record id: " . $row['id'] . "\n"; - echo "This record is ignored, you should inspect it to see if there's anything wrong.\n===\n"; - continue; - } - $stmt->execute(array( - $newData['etag'], - $newData['size'], - $newData['componentType'], - $newData['firstOccurence'], - $newData['lastOccurence'], - $row['id'], - )); - $done++; - - if ($done % 500 === 0) { - echo "Completed: $done / $total\n"; - } -} -echo "Completed: $done / $total\n"; - -echo "Checking the calendars table needs changes.\n"; -$row = $pdo->query("SELECT * FROM calendars LIMIT 1")->fetch(); - -if (array_key_exists('transparent', $row)) { - - echo "The calendars table is already up to date\n"; - -} else { - - echo "Adding the 'transparent' field to the calendars table\n"; - - switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) { - - case 'mysql' : - $pdo->exec("ALTER TABLE calendars ADD transparent TINYINT(1) NOT NULL DEFAULT '0'"); - break; - case 'sqlite' : - $pdo->exec("ALTER TABLE calendars ADD transparent bool"); - break; - - default : - die('This upgrade script does not support this driver (' . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . ")\n"); - - } - -} - -echo "Process completed!\n"; - -/** - * Parses some information from calendar objects, used for optimized - * calendar-queries. - * - * Blantently copied from Sabre\CalDAV\Backend\PDO - * - * Returns an array with the following keys: - * * etag - * * size - * * componentType - * * firstOccurence - * * lastOccurence - * - * @param string $calendarData - * @return array - */ -function getDenormalizedData($calendarData) { - - $vObject = \Sabre\VObject\Reader::read($calendarData); - $componentType = null; - $component = null; - $firstOccurence = null; - $lastOccurence = null; - foreach($vObject->getComponents() as $component) { - if ($component->name!=='VTIMEZONE') { - $componentType = $component->name; - break; - } - } - if (!$componentType) { - throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component'); - } - if ($componentType === 'VEVENT') { - $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp(); - // Finding the last occurence is a bit harder - if (!isset($component->RRULE)) { - if (isset($component->DTEND)) { - $lastOccurence = $component->DTEND->getDateTime()->getTimeStamp(); - } elseif (isset($component->DURATION)) { - $endDate = clone $component->DTSTART->getDateTime(); - $endDate->add(\Sabre\VObject\DateTimeParser::parse($component->DURATION->value)); - $lastOccurence = $endDate->getTimeStamp(); - } elseif (!$component->DTSTART->hasTime()) { - $endDate = clone $component->DTSTART->getDateTime(); - $endDate->modify('+1 day'); - $lastOccurence = $endDate->getTimeStamp(); - } else { - $lastOccurence = $firstOccurence; - } - } else { - $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(); - } else { - $end = $it->getDtEnd(); - while($it->valid() && $end < $maxDate) { - $end = $it->getDtEnd(); - $it->next(); - - } - $lastOccurence = $end->getTimeStamp(); - } - - } - } - - return array( - 'etag' => md5($calendarData), - 'size' => strlen($calendarData), - 'componentType' => $componentType, - 'firstOccurence' => $firstOccurence, - 'lastOccurence' => $lastOccurence, - ); - -} diff --git a/vendor/sabre/dav/examples/addressbookserver.php b/vendor/sabre/dav/examples/addressbookserver.php deleted file mode 100644 index 6d1c9b26c..000000000 --- a/vendor/sabre/dav/examples/addressbookserver.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - -Addressbook/CardDAV server example - -This server features CardDAV support - -*/ - -// settings -date_default_timezone_set('Canada/Eastern'); - -// Make sure this setting is turned on and reflect the root url for your WebDAV server. -// This can be for example the root / or a complete path to your server script -$baseUri = '/'; - -/* Database */ -$pdo = new PDO('sqlite:data/db.sqlite'); -$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - -//Mapping PHP errors to exceptions -function exception_error_handler($errno, $errstr, $errfile, $errline) { - throw new ErrorException($errstr, 0, $errno, $errfile, $errline); -} -set_error_handler("exception_error_handler"); - -// Autoloader -require_once 'vendor/autoload.php'; - -// Backends -$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo); -$principalBackend = new Sabre\DAVACL\PrincipalBackend\PDO($pdo); -$carddavBackend = new Sabre\CardDAV\Backend\PDO($pdo); -//$caldavBackend = new Sabre\CalDAV\Backend\PDO($pdo); - -// Setting up the directory tree // -$nodes = [ - new Sabre\DAVACL\PrincipalCollection($principalBackend), -// 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)); -$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(); diff --git a/vendor/sabre/dav/examples/sql/mysql.addressbook.sql b/vendor/sabre/dav/examples/sql/mysql.addressbook.sql deleted file mode 100644 index 5ec8428a7..000000000 --- a/vendor/sabre/dav/examples/sql/mysql.addressbook.sql +++ /dev/null @@ -1,28 +0,0 @@ -CREATE TABLE addressbooks ( - id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - principaluri VARBINARY(255), - displayname VARCHAR(255), - uri VARBINARY(200), - description TEXT, - synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1', - UNIQUE(principaluri(100), uri(100)) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - -CREATE TABLE cards ( - id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - addressbookid INT(11) UNSIGNED NOT NULL, - carddata MEDIUMBLOB, - uri VARBINARY(200), - lastmodified INT(11) UNSIGNED, - etag VARBINARY(32), - size INT(11) UNSIGNED NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - -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=utf8 COLLATE=utf8_unicode_ci; diff --git a/vendor/sabre/dav/examples/sql/mysql.calendars.sql b/vendor/sabre/dav/examples/sql/mysql.calendars.sql deleted file mode 100644 index 21c5bcb44..000000000 --- a/vendor/sabre/dav/examples/sql/mysql.calendars.sql +++ /dev/null @@ -1,76 +0,0 @@ -CREATE TABLE calendarobjects ( - id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - calendardata MEDIUMBLOB, - uri VARBINARY(200), - calendarid INTEGER UNSIGNED NOT NULL, - lastmodified INT(11) UNSIGNED, - etag VARBINARY(32), - size INT(11) UNSIGNED NOT NULL, - componenttype VARBINARY(8), - firstoccurence INT(11) UNSIGNED, - lastoccurence INT(11) UNSIGNED, - uid VARBINARY(200), - UNIQUE(calendarid, uri), - INDEX calendarid_time (calendarid, firstoccurence) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE calendars ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1', - components VARBINARY(21) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE calendarinstances ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - calendarid INTEGER UNSIGNED NOT NULL, - principaluri VARBINARY(100), - access TINYINT(1) NOT NULL DEFAULT '1' COMMENT '1 = owner, 2 = read, 3 = readwrite', - displayname VARCHAR(100), - uri VARBINARY(200), - description TEXT, - calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', - calendarcolor VARBINARY(10), - timezone TEXT, - transparent TINYINT(1) NOT NULL DEFAULT '0', - share_href VARBINARY(100), - share_displayname VARCHAR(100), - share_invitestatus TINYINT(1) NOT NULL DEFAULT '2' COMMENT '1 = noresponse, 2 = accepted, 3 = declined, 4 = invalid', - UNIQUE(principaluri, uri), - UNIQUE(calendarid, principaluri), - UNIQUE(calendarid, share_href) -) 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; diff --git a/vendor/sabre/dav/examples/sql/mysql.locks.sql b/vendor/sabre/dav/examples/sql/mysql.locks.sql deleted file mode 100644 index 96a3a88d9..000000000 --- a/vendor/sabre/dav/examples/sql/mysql.locks.sql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE TABLE locks ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - owner VARCHAR(100), - timeout INTEGER UNSIGNED, - created INTEGER, - token VARBINARY(100), - scope TINYINT, - depth TINYINT, - uri VARBINARY(1000), - INDEX(token), - INDEX(uri(100)) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/vendor/sabre/dav/examples/sql/mysql.principals.sql b/vendor/sabre/dav/examples/sql/mysql.principals.sql deleted file mode 100644 index ea0d16a27..000000000 --- a/vendor/sabre/dav/examples/sql/mysql.principals.sql +++ /dev/null @@ -1,20 +0,0 @@ -CREATE TABLE principals ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - uri VARBINARY(200) NOT NULL, - email VARBINARY(80), - displayname VARCHAR(80), - 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'), -('principals/admin/calendar-proxy-read', null, null), -('principals/admin/calendar-proxy-write', null, null); - diff --git a/vendor/sabre/dav/examples/sql/mysql.users.sql b/vendor/sabre/dav/examples/sql/mysql.users.sql deleted file mode 100644 index 22ac312d5..000000000 --- a/vendor/sabre/dav/examples/sql/mysql.users.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE users ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - username VARBINARY(50), - digesta1 VARBINARY(32), - UNIQUE(username) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -INSERT INTO users (username,digesta1) VALUES -('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/sabre/dav/examples/sql/pgsql.addressbook.sql b/vendor/sabre/dav/examples/sql/pgsql.addressbook.sql deleted file mode 100644 index ef2cc5b9a..000000000 --- a/vendor/sabre/dav/examples/sql/pgsql.addressbook.sql +++ /dev/null @@ -1,52 +0,0 @@ -CREATE TABLE addressbooks ( - id SERIAL NOT NULL, - principaluri VARCHAR(255), - displayname VARCHAR(255), - uri VARCHAR(200), - description TEXT, - synctoken INTEGER NOT NULL DEFAULT 1 -); - -ALTER TABLE ONLY addressbooks - ADD CONSTRAINT addressbooks_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX addressbooks_ukey - ON addressbooks USING btree (principaluri, uri); - -CREATE TABLE cards ( - id SERIAL NOT NULL, - addressbookid INTEGER NOT NULL, - carddata TEXT, - uri VARCHAR(200), - lastmodified INTEGER, - etag VARCHAR(32), - size INTEGER NOT NULL -); - -ALTER TABLE ONLY cards - ADD CONSTRAINT cards_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX cards_ukey - ON cards USING btree (addressbookid, uri); - -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; diff --git a/vendor/sabre/dav/examples/sql/pgsql.calendars.sql b/vendor/sabre/dav/examples/sql/pgsql.calendars.sql deleted file mode 100644 index 67dc41a5a..000000000 --- a/vendor/sabre/dav/examples/sql/pgsql.calendars.sql +++ /dev/null @@ -1,105 +0,0 @@ -CREATE TABLE calendarobjects ( - id SERIAL NOT NULL, - calendardata BYTEA, - uri VARCHAR(200), - calendarid INTEGER NOT NULL, - lastmodified INTEGER, - etag VARCHAR(32), - size INTEGER NOT NULL, - componenttype VARCHAR(8), - firstoccurence INTEGER, - lastoccurence INTEGER, - uid VARCHAR(200) -); - -ALTER TABLE ONLY calendarobjects - ADD CONSTRAINT calendarobjects_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX calendarobjects_ukey - ON calendarobjects USING btree (calendarid, uri); - - -CREATE TABLE calendars ( - id SERIAL NOT NULL, - synctoken INTEGER NOT NULL DEFAULT 1, - components VARCHAR(21) -); - -ALTER TABLE ONLY calendars - ADD CONSTRAINT calendars_pkey PRIMARY KEY (id); - - -CREATE TABLE calendarinstances ( - id SERIAL NOT NULL, - calendarid INTEGER NOT NULL, - principaluri VARCHAR(100), - access SMALLINT NOT NULL DEFAULT '1', -- '1 = owner, 2 = read, 3 = readwrite' - displayname VARCHAR(100), - uri VARCHAR(200), - description TEXT, - calendarorder INTEGER NOT NULL DEFAULT 0, - calendarcolor VARCHAR(10), - timezone TEXT, - transparent SMALLINT NOT NULL DEFAULT '0', - share_href VARCHAR(100), - share_displayname VARCHAR(100), - share_invitestatus SMALLINT NOT NULL DEFAULT '2' -- '1 = noresponse, 2 = accepted, 3 = declined, 4 = invalid' -); - -ALTER TABLE ONLY calendarinstances - ADD CONSTRAINT calendarinstances_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX calendarinstances_principaluri_uri - ON calendarinstances USING btree (principaluri, uri); - - -CREATE UNIQUE INDEX calendarinstances_principaluri_calendarid - ON calendarinstances USING btree (principaluri, calendarid); - -CREATE UNIQUE INDEX calendarinstances_principaluri_share_href - ON calendarinstances USING btree (principaluri, share_href); - -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); - -CREATE TABLE schedulingobjects ( - id SERIAL NOT NULL, - principaluri VARCHAR(255), - calendardata BYTEA, - uri VARCHAR(200), - lastmodified INTEGER, - etag VARCHAR(32), - size INTEGER NOT NULL -); diff --git a/vendor/sabre/dav/examples/sql/pgsql.locks.sql b/vendor/sabre/dav/examples/sql/pgsql.locks.sql deleted file mode 100644 index 0290528ce..000000000 --- a/vendor/sabre/dav/examples/sql/pgsql.locks.sql +++ /dev/null @@ -1,19 +0,0 @@ -CREATE TABLE locks ( - id SERIAL NOT NULL, - owner VARCHAR(100), - timeout INTEGER, - created INTEGER, - token VARCHAR(100), - 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); diff --git a/vendor/sabre/dav/examples/sql/pgsql.principals.sql b/vendor/sabre/dav/examples/sql/pgsql.principals.sql deleted file mode 100644 index 5a65260a2..000000000 --- a/vendor/sabre/dav/examples/sql/pgsql.principals.sql +++ /dev/null @@ -1,30 +0,0 @@ -CREATE TABLE principals ( - id SERIAL NOT NULL, - uri VARCHAR(200) NOT NULL, - email VARCHAR(80), - displayname VARCHAR(80) -); - -ALTER TABLE ONLY principals - ADD CONSTRAINT principals_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX principals_ukey - ON principals USING btree (uri); - -CREATE TABLE groupmembers ( - id SERIAL NOT NULL, - principal_id INTEGER NOT NULL, - member_id INTEGER NOT NULL -); - -ALTER TABLE ONLY groupmembers - ADD CONSTRAINT groupmembers_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX groupmembers_ukey - ON groupmembers USING btree (principal_id, member_id); - -INSERT INTO principals (uri,email,displayname) VALUES -('principals/admin', 'admin@example.org','Administrator'), -('principals/admin/calendar-proxy-read', null, null), -('principals/admin/calendar-proxy-write', null, null); - diff --git a/vendor/sabre/dav/examples/sql/pgsql.users.sql b/vendor/sabre/dav/examples/sql/pgsql.users.sql deleted file mode 100644 index 9d6047b8c..000000000 --- a/vendor/sabre/dav/examples/sql/pgsql.users.sql +++ /dev/null @@ -1,14 +0,0 @@ -CREATE TABLE users ( - id SERIAL NOT NULL, - username VARCHAR(50), - digesta1 VARCHAR(32) -); - -ALTER TABLE ONLY users - ADD CONSTRAINT users_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX users_ukey - ON users USING btree (username); - -INSERT INTO users (username,digesta1) VALUES -('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/sabre/dav/examples/sql/sqlite.addressbooks.sql b/vendor/sabre/dav/examples/sql/sqlite.addressbooks.sql deleted file mode 100644 index 0baed8bfb..000000000 --- a/vendor/sabre/dav/examples/sql/sqlite.addressbooks.sql +++ /dev/null @@ -1,28 +0,0 @@ -CREATE TABLE addressbooks ( - id integer primary key asc NOT NULL, - principaluri text NOT NULL, - displayname text, - uri text NOT NULL, - description text, - synctoken integer DEFAULT 1 NOT NULL -); - -CREATE TABLE cards ( - id integer primary key asc NOT NULL, - addressbookid integer NOT NULL, - carddata blob, - 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); diff --git a/vendor/sabre/dav/examples/sql/sqlite.calendars.sql b/vendor/sabre/dav/examples/sql/sqlite.calendars.sql deleted file mode 100644 index 1c8070496..000000000 --- a/vendor/sabre/dav/examples/sql/sqlite.calendars.sql +++ /dev/null @@ -1,76 +0,0 @@ -CREATE TABLE calendarobjects ( - 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, - uid text -); - -CREATE TABLE calendars ( - id integer primary key asc NOT NULL, - synctoken integer DEFAULT 1 NOT NULL, - components text NOT NULL -); - -CREATE TABLE calendarinstances ( - id integer primary key asc NOT NULL, - calendarid integer NOT NULL, - principaluri text NULL, - access integer COMMENT '1 = owner, 2 = read, 3 = readwrite' NOT NULL DEFAULT '1', - displayname text, - uri text NOT NULL, - description text, - calendarorder integer, - calendarcolor text, - timezone text, - transparent bool, - share_href text, - share_displayname text, - share_invitestatus integer DEFAULT '2', - UNIQUE (principaluri, uri), - UNIQUE (calendarid, principaluri), - UNIQUE (calendarid, share_href) -); - -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); diff --git a/vendor/sabre/dav/examples/sql/sqlite.locks.sql b/vendor/sabre/dav/examples/sql/sqlite.locks.sql deleted file mode 100644 index 622baea42..000000000 --- a/vendor/sabre/dav/examples/sql/sqlite.locks.sql +++ /dev/null @@ -1,12 +0,0 @@ -BEGIN TRANSACTION; -CREATE TABLE locks ( - id integer primary key asc NOT NULL, - owner text, - timeout integer, - created integer, - token text, - scope integer, - depth integer, - uri text -); -COMMIT; diff --git a/vendor/sabre/dav/examples/sql/sqlite.principals.sql b/vendor/sabre/dav/examples/sql/sqlite.principals.sql deleted file mode 100644 index 4105156f8..000000000 --- a/vendor/sabre/dav/examples/sql/sqlite.principals.sql +++ /dev/null @@ -1,20 +0,0 @@ -CREATE TABLE principals ( - id INTEGER PRIMARY KEY ASC NOT NULL, - uri TEXT NOT NULL, - email TEXT, - displayname TEXT, - UNIQUE(uri) -); - -CREATE TABLE groupmembers ( - id INTEGER PRIMARY KEY ASC NOT NULL, - principal_id INTEGER NOT NULL, - member_id INTEGER NOT NULL, - UNIQUE(principal_id, member_id) -); - - -INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin', 'admin@example.org','Administrator'); -INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-read', null, null); -INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-write', null, null); - diff --git a/vendor/sabre/dav/examples/sql/sqlite.users.sql b/vendor/sabre/dav/examples/sql/sqlite.users.sql deleted file mode 100644 index 5597b058a..000000000 --- a/vendor/sabre/dav/examples/sql/sqlite.users.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE users ( - id integer primary key asc NOT NULL, - username TEXT NOT NULL, - digesta1 TEXT NOT NULL, - UNIQUE(username) -); - -INSERT INTO users (username,digesta1) VALUES -('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/sabre/dav/examples/webserver/apache2_htaccess.conf b/vendor/sabre/dav/examples/webserver/apache2_htaccess.conf deleted file mode 100644 index c5f29ba80..000000000 --- a/vendor/sabre/dav/examples/webserver/apache2_htaccess.conf +++ /dev/null @@ -1,16 +0,0 @@ -RewriteEngine On -# This makes every request go to server.php -RewriteRule (.*) server.php [L] - -# Output buffering needs to be off, to prevent high memory usage -php_flag output_buffering off - -# 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 diff --git a/vendor/sabre/dav/examples/webserver/apache2_vhost.conf b/vendor/sabre/dav/examples/webserver/apache2_vhost.conf deleted file mode 100644 index 74289641e..000000000 --- a/vendor/sabre/dav/examples/webserver/apache2_vhost.conf +++ /dev/null @@ -1,29 +0,0 @@ -# This is a sample configuration to setup a dedicated Apache vhost for WebDAV. -# -# The main thing that should be configured is the servername, and the path to -# your SabreDAV installation (DocumentRoot). -# -# This configuration assumed mod_php5 is used, as it sets a few default php -# settings as well. -<VirtualHost *:*> - - # Don't forget to change the server name - # ServerName dav.example.org - - # The DocumentRoot is also required - # DocumentRoot /home/sabredav/ - - RewriteEngine On - # This makes every request go to server.php - RewriteRule ^/(.*)$ /server.php [L] - - # Output buffering needs to be off, to prevent high memory usage - php_flag output_buffering off - - # This is also to prevent high memory usage - php_flag always_populate_raw_post_data off - - # SabreDAV is not compatible with mbstring function overloading - php_flag mbstring.func_overload off - -</VirtualHost *:*> diff --git a/vendor/sabre/dav/examples/webserver/apache2_vhost_cgi.conf b/vendor/sabre/dav/examples/webserver/apache2_vhost_cgi.conf deleted file mode 100644 index 607254c6e..000000000 --- a/vendor/sabre/dav/examples/webserver/apache2_vhost_cgi.conf +++ /dev/null @@ -1,21 +0,0 @@ -# This is a sample configuration to setup a dedicated Apache vhost for WebDAV. -# -# The main thing that should be configured is the servername, and the path to -# your SabreDAV installation (DocumentRoot). -# -# This configuration assumes CGI or FastCGI is used. -<VirtualHost *:*> - - # Don't forget to change the server name - # ServerName dav.example.org - - # The DocumentRoot is also required - # DocumentRoot /home/sabredav/ - - # This makes every request go to server.php. This also makes sure - # the Authentication information is available. If your server script is - # not called server.php, be sure to change it. - RewriteEngine On - RewriteRule ^/(.*)$ /server.php [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] - -</VirtualHost *:*> diff --git a/vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php b/vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php deleted file mode 100644 index 7420d94f7..000000000 --- a/vendor/sabre/dav/lib/CalDAV/IShareableCalendar.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -namespace Sabre\CalDAV; - -/** - * This interface represents a Calendar that can be shared with other users. - * - * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). - * @author Evert Pot (http://evertpot.com/) - * @license http://sabre.io/license/ Modified BSD License - */ -interface IShareableCalendar extends ICalendar { - - /** - * Updates the list of shares. - * - * The first array is a list of people that are to be added to the - * calendar. - * - * Every element in the add array has the following properties: - * * href - A url. Usually a mailto: address - * * commonName - Usually a first and last name, or false - * * summary - A description of the share, can also be false - * * readOnly - A boolean value - * - * Every element in the remove array is just the address string. - * - * @param array $add - * @param array $remove - * @return void - */ - function updateShares(array $add, array $remove); - - /** - * Returns the list of people whom this calendar is shared with. - * - * Every element in this array should have the following properties: - * * href - Often a mailto: address - * * commonName - Optional, for example a first + last name - * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. - * * readOnly - boolean - * * summary - Optional, a description for the share - * - * @return array - */ - function getShares(); - -} diff --git a/vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php b/vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php deleted file mode 100644 index c81c96300..000000000 --- a/vendor/sabre/dav/lib/CalDAV/ShareableCalendar.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -namespace Sabre\CalDAV; - -/** - * This object represents a CalDAV calendar that can be shared with other - * users. - * - * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). - * @author Evert Pot (http://evertpot.com/) - * @license http://sabre.io/license/ Modified BSD License - */ -class ShareableCalendar extends Calendar implements IShareableCalendar { - - /** - * Updates the list of shares. - * - * The first array is a list of people that are to be added to the - * calendar. - * - * Every element in the add array has the following properties: - * * href - A url. Usually a mailto: address - * * commonName - Usually a first and last name, or false - * * summary - A description of the share, can also be false - * * readOnly - A boolean value - * - * Every element in the remove array is just the address string. - * - * @param array $add - * @param array $remove - * @return void - */ - function updateShares(array $add, array $remove) { - - $this->caldavBackend->updateShares($this->calendarInfo['id'], $add, $remove); - - } - - /** - * Returns the list of people whom this calendar is shared with. - * - * Every element in this array should have the following properties: - * * href - Often a mailto: address - * * commonName - Optional, for example a first + last name - * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. - * * readOnly - boolean - * * summary - Optional, a description for the share - * - * @return array - */ - function getShares() { - - return $this->caldavBackend->getShares($this->calendarInfo['id']); - - } - - /** - * Marks this calendar as published. - * - * Publishing a calendar should automatically create a read-only, public, - * subscribable calendar. - * - * @param bool $value - * @return void - */ - function setPublishStatus($value) { - - $this->caldavBackend->setPublishStatus($this->calendarInfo['id'], $value); - - } - -} diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/ShareableCalendarTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/ShareableCalendarTest.php deleted file mode 100644 index 15b869d50..000000000 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/ShareableCalendarTest.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -namespace Sabre\CalDAV; - -use Sabre\DAVACL; - -class ShareableCalendarTest extends \PHPUnit_Framework_TestCase { - - protected $backend; - protected $instance; - - function setUp() { - - $props = array( - 'id' => 1, - ); - - $this->backend = new Backend\MockSharing( - array($props) - ); - $this->backend->updateShares(1, array( - array( - 'href' => 'mailto:removeme@example.org', - 'commonName' => 'To be removed', - 'readOnly' => true, - ), - ), array()); - - $this->instance = new ShareableCalendar($this->backend, $props); - - } - - function testUpdateShares() { - - $this->instance->updateShares(array( - array( - 'href' => 'mailto:test@example.org', - 'commonName' => 'Foo Bar', - 'summary' => 'Booh', - 'readOnly' => false, - ), - ), array('mailto:removeme@example.org')); - - $this->assertEquals(array(array( - 'href' => 'mailto:test@example.org', - 'commonName' => 'Foo Bar', - 'summary' => 'Booh', - 'readOnly' => false, - 'status' => SharingPlugin::STATUS_NORESPONSE, - )), $this->instance->getShares()); - - } - - function testPublish() { - - $this->assertNull($this->instance->setPublishStatus(true)); - $this->assertNull($this->instance->setPublishStatus(false)); - - } -} diff --git a/vendor/sabre/dav/tests/phpunit.xml b/vendor/sabre/dav/tests/phpunit.xml deleted file mode 100644 index e16ec38b5..000000000 --- a/vendor/sabre/dav/tests/phpunit.xml +++ /dev/null @@ -1,40 +0,0 @@ -<phpunit - colors="true" - bootstrap="bootstrap.php" - convertErrorsToExceptions="true" - convertNoticesToExceptions="true" - convertWarningsToExceptions="true" - strict="true" - > - <testsuite name="sabre-vobject"> - <directory>../vendor/sabre/vobject/tests/VObject</directory> - </testsuite> - <testsuite name="sabre-event"> - <directory>../vendor/sabre/event/tests/</directory> - </testsuite> - <testsuite name="sabre-http"> - <directory>../vendor/sabre/http/tests/HTTP</directory> - </testsuite> - <testsuite name="sabre-dav"> - <directory>Sabre/DAV</directory> - </testsuite> - <testsuite name="sabre-davacl"> - <directory>Sabre/DAVACL</directory> - </testsuite> - <testsuite name="sabre-caldav"> - <directory>Sabre/CalDAV</directory> - </testsuite> - <testsuite name="sabre-carddav"> - <directory>Sabre/CardDAV</directory> - </testsuite> - - <filter> - <whitelist addUncoveredFilesFromWhitelist="true"> - <directory suffix=".php">../lib/</directory> - <exclude> - <file>../lib/Sabre/autoload.php</file> - <file>../lib/Sabre/VObject/includes.php</file> - </exclude> - </whitelist> - </filter> -</phpunit> diff --git a/vendor/sabre/vobject/ChangeLog.md b/vendor/sabre/vobject/ChangeLog.md deleted file mode 100644 index 60501f930..000000000 --- a/vendor/sabre/vobject/ChangeLog.md +++ /dev/null @@ -1,563 +0,0 @@ -ChangeLog -========= - -3.4.5 (2015-06-02) ------------------- - -* #229: Converting vcards from 3.0 to 4.0 that contained a `LANG` property - would throw an error. - - -3.4.4 (2015-05-27) ------------------- - -* #228: Fixed a 'party crasher' bug in the iTip broker. This would break - scheduling in some cases. - - -3.4.3 (2015-05-19) ------------------- - -* #219: Corrected validation of `EXDATE` properties with more than one value. -* #212: `BYSETPOS` with values below `-1` was broken and could cause infinite - loops. -* #211: Fix `BYDAY=-5TH` in recurrence iterator. (@lindquist) -* #216: `ENCODING` parameter is now validated for all document types. -* #217: Initializing vCard `DATE` objects with a PHP DateTime object will now - work correctly. (@thomascube) - - -3.4.2 (2015-02-25) ------------------- - -* #210: iTip: Replying to an event without a master event was broken. - - -3.4.1 (2015-02-24) ------------------- - -* A minor change to ensure that unittests work correctly in the sabre/dav - test-suite. - - -3.4.0 (2015-02-23) ------------------- - -* #196: Made parsing recurrence rules a lot faster on big calendars. -* Updated windows timezone mappings to latest unicode version. -* #202: Support for parsing and validating `VAVAILABILITY` components. (@Hywan) -* #195: PHP 5.3 compatibility in 'generatevcards' script. (@rickdenhaan) -* #205: Improving handling of multiple `EXDATE` when processing iTip changes. - (@armin-hackmann) -* #187: Fixed validator rules for `LAST-MODIFIED` properties. -* #188: Retain floating times when generating instances using - `Recur\EventIterator`. -* #203: Skip tests for timezones that are not supported on older PHP versions, - instead of a hard fail. -* #204: Dealing a bit better with vCard date-time values that contained - milliseconds. (which is normally invalid). (@armin-hackmann) - - -3.3.5 (2015-01-09) ------------------- - -* #168: Expanding calendars now removes objects with recurrence rules that - don't have a valid recurrence instance. -* #177: SCHEDULE-STATUS should not contain a reason phrase, only a status - code. -* #175: Parser can now read and skip the UTF-8 BOM. -* #179: Added `isFloating` to `DATE-TIME` properties. -* #179: Fixed jCal serialization of floating `DATE-TIME` properties. -* #173: vCard converter failed for `X-ABDATE` properties that had no - `X-ABLABEL`. -* #180: Added `PROFILE_CALDAV` and `PROFILE_CARDDAV` to enable validation rules - specific for CalDAV/CardDAV servers. -* #176: A missing `UID` is no longer an error, but a warning for the vCard - validator, unless `PROFILE_CARDDAV` is specified. - - -3.3.4 (2014-11-19) ------------------- - -* #154: Converting `ANNIVERSARY` to `X-ANNIVERSARY` and `X-ABDATE` and - vice-versa when converting to/from vCard 4. -* #154: It's now possible to easily select all vCard properties belonging to - a single group with `$vcard->{'ITEM1.'}` syntax. (@armin-hackmann) -* #156: Simpler way to check if a string is UTF-8. (@Hywan) -* Unittest improvements. -* #159: The recurrence iterator, freebusy generator and iCalendar DATE and - DATE-TIME properties can now all accept a reference timezone when working - floating times or all-day events. -* #159: Master events will no longer get a `RECURRENCE-ID` when expanding. -* #159: `RECURRENCE-ID` for all-day events will now be correct when expanding. -* #163: Added a `getTimeZone()` method to `VTIMEZONE` components. - - -3.3.3 (2014-10-09) ------------------- - -* #142: `CANCEL` and `REPLY` messages now include the `DTSTART` from the - original event. -* #143: `SCHEDULE-AGENT` on the `ORGANIZER` property is respected. -* #144: `PARTSTAT=NEEDS-ACTION` is now set for new invites, if no `PARTSTAT` is - set to support the inbox feature of iOS. -* #147: Bugs related to scheduling all-day events. -* #148: Ignore events that have attendees but no organizer. -* #149: Avoiding logging errors during timezone detection. This is a workaround - for a PHP bug. -* Support for "Line Islands Standard Time" windows timezone. -* #154: Correctly work around vCard parameters that have a value but no name. - - -3.3.2 (2014-09-19) ------------------- - -* Changed: iTip broker now sets RSVP status to false when replies are received. -* #118: iTip Message now has a `getScheduleStatus()` method. -* #119: Support for detecting 'significant changes'. -* #120: Support for `SCHEDULE-FORCE-SEND`. -* #121: iCal demands parameters containing the + sign to be quoted. -* #122: Don't generate REPLY messages for events that have been cancelled. -* #123: Added `SUMMARY` to iTip messages. -* #130: Incorrect validation rules for `RELATED` (should be `RELATED-TO`). -* #128: `ATTACH` in iCalendar is `URI` by default, not `BINARY`. -* #131: RRULE that doesn't provide a single valid instance now throws an - exception. -* #136: Validator rejects *all* control characters. We were missing a few. -* #133: Splitter objects will throw exceptions when receiving incompatible - objects. -* #127: Attendees who delete recurring event instances events they had already - declined earlier will no longer generate another reply. -* #125: Send CANCEL messages when ORGANIZER property gets deleted. - - -3.3.1 (2014-08-18) ------------------- - -* Changed: It's now possible to pass DateTime objects when using the magic - setters on properties. (`$event->DTSTART = new DateTime('now')`). -* #111: iTip Broker does not process attendee adding events to EXDATE. -* #112: EventIterator now sets TZID on RECURRENCE-ID. -* #113: Timezone support during creation of iTip REPLY messages. -* #114: VTIMEZONE is retained when generating new REQUEST objects. -* #114: Support for 'MAILTO:' style email addresses (in uppercase) in the iTip - broker. This improves evolution support. -* #115: Using REQUEST-STATUS from REPLY messages and now propegating that into - SCHEDULE-STATUS. - - -3.3.0 (2014-08-07) ------------------- - -* We now use PSR-4 for the directory structure. This means that everything - that was used to be in the `lib/Sabre/VObject` directory is now moved to - `lib/`. If you use composer to load this library, you shouldn't have to do - anything about that though. -* VEVENT now get populated with a DTSTAMP and UID property by default. -* BC Break: Removed the 'includes.php' file. Use composer instead. -* #103: Added support for processing [iTip][iTip] messages. This allows a user - to parse incoming iTip messages and apply the result on existing calendars, - or automatically generate invites/replies/cancellations based on changes that - a user made on objects. -* #75, #58, #18: Fixes related to overriding the first event in recurrences. -* Added: VCalendar::getBaseComponent to find the 'master' component in a - calendar. -* #51: Support for iterating RDATE properties. -* Fixed: Issue #101: RecurrenceIterator::nextMonthly() shows events that are - excluded events with wrong time - - -3.2.4 (2014-07-14) ------------------- - -* Added: Issue #98. The VCardConverter now takes `X-APPLE-OMIT-YEAR` into - consideration when converting between vCard 3 and 4. -* Fixed: Issue #96. Some support for Yahoo's broken vcards. -* Fixed: PHP 5.3 support was broken in the cli tool. - - -3.2.3 (2014-06-12) ------------------- - -* Validator now checks if DUE and DTSTART are of the same type in VTODO, and - ensures that DUE is always after DTSTART. -* Removed documentation from source repository, to http://sabre.io/vobject/ -* Expanded the vobject cli tool validation output to make it easier to find - issues. -* Fixed: vobject repair. It was not working for iCalendar objects. - - -3.2.2 (2014-05-07) ------------------- - -* Minor tweak in unittests to make it run on PHP 5.5.12. Json-prettifying - slightly changed which caused the test to fail. - - -3.2.1 (2014-05-03) ------------------- - -* Minor tweak to make the unittests run with the latest hhvm on travis. -* Updated timezone definitions. -* Updated copyright links to point to http://sabre.io/ - - -3.2.0 (2014-04-02) ------------------- - -* Now hhvm compatible! -* The validator can now detect a _lot_ more problems. Many rules for both - iCalendar and vCard were added. -* Added: bin/generate_vcards, a utility to generate random vcards for testing - purposes. Patches are welcome to add more data. -* Updated: Windows timezone mapping to latest version from unicode.org -* Changed: The timezone maps are now loaded in from external files, in - lib/Sabre/VObject/timezonedata. -* Added: Fixing badly encoded URL's from google contacts vcards. -* Fixed: Issue #68. Couldn't decode properties ending in a colon. -* Fixed: Issue #72. RecurrenceIterator should respect timezone in the UNTIL - clause. -* Fixed: Issue #67. BYMONTH limit on DAILY recurrences. -* Fixed: Issue #26. Return a more descriptive error when coming across broken - BYDAY rules. -* Fixed: Issue #28. Incorrect timezone detection for some timezones. -* Fixed: Issue #70. Casting a parameter with a null value to string would fail. -* Added: Support for rfc6715 and rfc6474. -* Added: Support for DateTime objects in the VCard DATE-AND-OR-TIME property. -* Added: UUIDUtil, for easily creating unique identifiers. -* Fixed: Issue #83. Creating new VALUE=DATE objects using php's DateTime. -* Fixed: Issue #86. Don't go into an infinite loop when php errors are - disabled and an invalid file is read. - - -3.1.4 (2014-03-30) ------------------- - -* Fixed: Issue #87: Several compatibility fixes related to timezone handling - changes in PHP 5.5.10. - - -3.1.3 (2013-10-02) ------------------- - -* Fixed: Support from properties from draft-daboo-valarm-extensions-04. Issue - #56. -* Fixed: Issue #54. Parsing a stream of multiple vcards separated by more than - one newline. Thanks @Vedmak for the patch. -* Fixed: Serializing vcard 2.1 parameters with no name caused a literal '1' to - be inserted. -* Added: VCardConverter removed properties that are no longer supported in vCard - 4.0. -* Added: vCards with a minimum number of values (such as N), but don't have that - many, are now automatically padded with empty components. -* Added: The vCard validator now also checks for a minimum number of components, - and has the ability to repair these. -* Added: Some support for vCard 2.1 in the VCard converter, to upgrade to vCard - 3.0 or 4.0. -* Fixed: Issue 60 Use Document::$componentMap when instantiating the top-level - VCalendar and VCard components. -* Fixed: Issue 62: Parsing iCalendar parameters with no value. -* Added: --forgiving option to vobject utility. -* Fixed: Compound properties such as ADR were not correctly split up in vCard - 2.1 quoted printable-encoded properties. -* Fixed: Issue 64: Encoding of binary properties of converted vCards. Thanks - @DominikTo for the patch. - - -3.1.2 (2013-08-13) ------------------- - -* Fixed: Setting correct property group on VCard conversion - - -3.1.1 (2013-08-02) ------------------- - -* Fixed: Issue #53. A regression in RecurrenceIterator. - - -3.1.0 (2013-07-27) ------------------- - -* Added: bad-ass new cli debugging utility (in bin/vobject). -* Added: jCal and jCard parser. -* Fixed: URI properties should not escape ; and ,. -* Fixed: VCard 4 documents now correctly use URI as a default value-type for - PHOTO and others. BINARY no longer exists in vCard 4. -* Added: Utility to convert between 2.1, 3.0 and 4.0 vCards. -* Added: You can now add() multiple parameters to a property in one call. -* Added: Parameter::has() for easily checking if a parameter value exists. -* Added: VCard::preferred() to find a preferred email, phone number, etc for a - contact. -* Changed: All $duration properties are now public. -* Added: A few validators for iCalendar documents. -* Fixed: Issue #50. RecurrenceIterator gives incorrect result when exception - events are out of order in the iCalendar file. -* Fixed: Issue #48. Overridden events in the recurrence iterator that were past - the UNTIL date were ignored. -* Added: getDuration for DURATION values such as TRIGGER. Thanks to - @SimonSimCity. -* Fixed: Issue #52. vCard 2.1 parameters with no name may lose values if there's - more than 1. Thanks to @Vedmak. - - -3.0.0 (2013-06-21) ------------------- - -* Fixed: includes.php file was still broken. Our tool to generate it had some - bugs. - - -3.0.0-beta4 (2013-06-21) ------------------------- - -* Fixed: includes.php was no longer up to date. - - -3.0.0-beta3 (2013-06-17) ------------------------- - -* Added: OPTION_FORGIVING now also allows slashes in property names. -* Fixed: DateTimeParser no longer fails on dates with years < 1000 & > 4999 -* Fixed: Issue 36: Workaround for the recurrenceiterator and caldav events with - a missing base event. -* Fixed: jCard encoding of TIME properties. -* Fixed: jCal encoding of REQUEST-STATUS, GEO and PERIOD values. - - -3.0.0-beta2 (2013-06-10) ------------------------- - -* Fixed: Corrected includes.php file. -* Fixed: vCard date-time parser supported extended-format dates as well. -* Changed: Properties have been moved to an ICalendar or VCard directory. -* Fixed: Couldn't parse vCard 3 extended format dates and times. -* Fixed: Couldn't export jCard DATE values correctly. -* Fixed: Recursive loop in ICalendar\DateTime property. - - -3.0.0-beta1 (2013-06-07) ------------------------- - -* Added: jsonSerialize() for creating jCal and jCard documents. -* Added: helper method to parse vCard dates and times. -* Added: Specialized classes for FLOAT, LANGUAGE-TAG, TIME, TIMESTAMP, - DATE-AND-OR-TIME, CAL-ADDRESS, UNKNOWN and UTC-OFFSET properties. -* Removed: CommaSeparatedText property. Now included into Text. -* Fixed: Multiple parameters with the same name are now correctly encoded. -* Fixed: Parameter values containing a comma are now enclosed in double-quotes. -* Fixed: Iterating parameter values should now fully work as expected. -* Fixed: Support for vCard 2.1 nameless parameters. -* Changed: $valueMap, $componentMap and $propertyMap now all use fully-qualified - class names, so they are actually overridable. -* Fixed: Updating DATE-TIME to DATE values now behaves like expected. - - -3.0.0-alpha4 (2013-05-31) -------------------------- - -* Added: It's now possible to send parser options to the splitter classes. -* Added: A few tweaks to improve component and property creation. - - -3.0.0-alpha3 (2013-05-13) -------------------------- - -* Changed: propertyMap, valueMap and componentMap are now static properties. -* Changed: Component::remove() will throw an exception when trying to a node - that's not a child of said component. -* Added: Splitter objects are now faster, line numbers are accurately reported - and use less memory. -* Added: MimeDir parser can now continue parsing with the same stream buffer. -* Fixed: vobjectvalidate.php is operational again. -* Fixed: \r is properly stripped in text values. -* Fixed: QUOTED-PRINTABLE is now correctly encoded as well as encoded, for - vCards 2.1. -* Fixed: Parser assumes vCard 2.1, if no version was supplied. - - -3.0.0-alpha2 (2013-05-22) -------------------------- - -* Fixed: vCard URL properties were referencing a non-existant class. - - -3.0.0-alpha1 (2013-05-21) -------------------------- - -* Fixed: Now correctly dealing with escaping of properties. This solves the - problem with double-backslashes where they don't belong. -* Added: Easy support for properties with more than one value, using setParts - and getParts. -* Added: Support for broken 2.1 vCards produced by microsoft. -* Added: Automatically decoding quoted-printable values. -* Added: Automatically decoding base64 values. -* Added: Decoding RFC6868 parameter values (uses ^ as an escape character). -* Added: Fancy new MimeDir parser that can also parse streams. -* Added: Automatically mapping many, many properties to a property-class with - specialized API's. -* Added: remove() method for easily removing properties and sub-components - components. -* Changed: Components, Properties and Parameters can no longer be created with - Component::create, Property::create and Parameter::create. They must instead - be created through the root component. (A VCalendar or VCard object). -* Changed: API for DateTime properties has slightly changed. -* Changed: the ->value property is now protected everywhere. Use getParts() and - getValue() instead. -* BC Break: No support for mac newlines (\r). Never came across these anyway. -* Added: add() method to the Property class. -* Added: It's now possible to easy set multi-value properties as arrays. -* Added: When setting date-time properties you can just pass PHP's DateTime - object. -* Added: New components automatically get a bunch of default properties, such as - VERSION and CALSCALE. -* Added: You can add new sub-components much quicker with the magic setters, and - add() method. - - -2.1.7 (2015-01-21) ------------------- - -* Fixed: Issue #94, a workaround for bad escaping of ; and , in compound - properties. It's not a full solution, but it's an improvement for those - stuck in the 2.1 versions. - - -2.1.6 (2014-12-10) ------------------- - -* Fixed: Minor change to make sure that unittests succeed on every PHP version. - - -2.1.5 (2014-06-03) ------------------- - -* Fixed: #94: Better parameter escaping. -* Changed: Documentation cleanups. - - -2.1.4 (2014-03-30) ------------------- - -* Fixed: Issue #87: Several compatibility fixes related to timezone handling - changes in PHP 5.5.10. - - -2.1.3 (2013-10-02) ------------------- - -* Fixed: Issue #55. \r must be stripped from property values. -* Fixed: Issue #65. Putting quotes around parameter values that contain a colon. - - -2.1.2 (2013-08-02) ------------------- - -* Fixed: Issue #53. A regression in RecurrenceIterator. - - -2.1.1 (2013-07-27) ------------------- - -* Fixed: Issue #50. RecurrenceIterator gives incorrect result when exception - events are out of order in the iCalendar file. -* Fixed: Issue #48. Overridden events in the recurrence iterator that were past - the UNTIL date were ignored. - - -2.1.0 (2013-06-17) ------------------- - -* This version is fully backwards compatible with 2.0.\*. However, it contains a - few new API's that mimic the VObject 3 API. This allows it to be used a - 'bridge' version. Specifically, this new version exists so SabreDAV 1.7 and - 1.8 can run with both the 2 and 3 versions of this library. -* Added: Property\DateTime::hasTime(). -* Added: Property\MultiDateTime::hasTime(). -* Added: Property::getValue(). -* Added: Document class. -* Added: Document::createComponent and Document::createProperty. -* Added: Parameter::getValue(). - - -2.0.7 (2013-03-05) ------------------- - -* Fixed: Microsoft re-uses their magic numbers for different timezones, - specifically id 2 for both Sarajevo and Lisbon). A workaround was added to - deal with this. - - -2.0.6 (2013-02-17) ------------------- - -* Fixed: The reader now properly parses parameters without a value. - - -2.0.5 (2012-11-05) ------------------- - -* Fixed: The FreeBusyGenerator is now properly using the factory methods for - creation of components and properties. - - -2.0.4 (2012-11-02) ------------------- - -* Added: Known Lotus Notes / Domino timezone id's. - - -2.0.3 (2012-10-29) ------------------- - -* Added: Support for 'GMT+????' format in TZID's. -* Added: Support for formats like SystemV/EST5EDT in TZID's. -* Fixed: RecurrenceIterator now repairs recurrence rules where UNTIL < DTSTART. -* Added: Support for BYHOUR in FREQ=DAILY (@hollodk). -* Added: Support for BYHOUR and BYDAY in FREQ=WEEKLY. - - -2.0.2 (2012-10-06) ------------------- - -* Added: includes.php file, to load the entire library in one go. -* Fixed: A problem with determining alarm triggers for TODO's. - - -2.0.1 (2012-09-22) ------------------- - -* Removed: Element class. It wasn't used. -* Added: Basic validation and repair methods for broken input data. -* Fixed: RecurrenceIterator could infinitely loop when an INTERVAL of 0 was - specified. -* Added: A cli script that can validate and automatically repair vcards and - iCalendar objects. -* Added: A new 'Compound' property, that can automatically split up parts for - properties such as N, ADR, ORG and CATEGORIES. -* Added: Splitter classes, that can split up large objects (such as exports) - into individual objects (thanks @DominikTO and @armin-hackmann). -* Added: VFREEBUSY component, which allows easily checking wether timeslots are - available. -* Added: The Reader class now has a 'FORGIVING' option, which allows it to parse - properties with incorrect characters in the name (at this time, it just allows - underscores). -* Added: Also added the 'IGNORE_INVALID_LINES' option, to completely disregard - any invalid lines. -* Fixed: A bug in Windows timezone-id mappings for times created in Greenlands - timezone (sorry Greenlanders! I do care!). -* Fixed: DTEND was not generated correctly for VFREEBUSY reports. -* Fixed: Parser is at least 25% faster with real-world data. - - -2.0.0 (2012-08-08) ------------------- - -* VObject is now a separate project from SabreDAV. See the SabreDAV changelog - for version information before 2.0. -* New: VObject library now uses PHP 5.3 namespaces. -* New: It's possible to specify lists of parameters when constructing - properties. -* New: made it easier to construct the FreeBusyGenerator. - -[iTip]: http://tools.ietf.org/html/rfc5546 diff --git a/vendor/sabre/vobject/lib/Property/Float.php b/vendor/sabre/vobject/lib/Property/Float.php deleted file mode 100644 index 25bcd3db2..000000000 --- a/vendor/sabre/vobject/lib/Property/Float.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -namespace Sabre\VObject\Property; - -use - Sabre\VObject\Property; - -/** - * Float property - * - * This object represents FLOAT values. These can be 1 or more floating-point - * numbers. - * - * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). - * @author Evert Pot (http://evertpot.com/) - * @license http://sabre.io/license/ Modified BSD License - */ -class Float extends Property { - - /** - * In case this is a multi-value property. This string will be used as a - * delimiter. - * - * @var string|null - */ - public $delimiter = ';'; - - /** - * Sets a raw value coming from a mimedir (iCalendar/vCard) file. - * - * This has been 'unfolded', so only 1 line will be passed. Unescaping is - * not yet done, but parameters are not included. - * - * @param string $val - * @return void - */ - public function setRawMimeDirValue($val) { - - $val = explode($this->delimiter, $val); - foreach($val as &$item) { - $item = (float)$item; - } - $this->setParts($val); - - } - - /** - * Returns a raw mime-dir representation of the value. - * - * @return string - */ - public function getRawMimeDirValue() { - - return implode( - $this->delimiter, - $this->getParts() - ); - - } - - /** - * Returns the type of value. - * - * This corresponds to the VALUE= parameter. Every property also has a - * 'default' valueType. - * - * @return string - */ - public function getValueType() { - - return "FLOAT"; - - } - - /** - * Returns the value, in the format it should be encoded for json. - * - * This method must always return an array. - * - * @return array - */ - public function getJsonValue() { - - $val = array_map( - function($item) { - - return (float)$item; - - }, - $this->getParts() - ); - - // Special-casing the GEO property. - // - // See: - // http://tools.ietf.org/html/draft-ietf-jcardcal-jcal-04#section-3.4.1.2 - if ($this->name==='GEO') { - return array($val); - } else { - return $val; - } - - } -} diff --git a/vendor/sabre/vobject/lib/Property/Integer.php b/vendor/sabre/vobject/lib/Property/Integer.php deleted file mode 100644 index db000156f..000000000 --- a/vendor/sabre/vobject/lib/Property/Integer.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -namespace Sabre\VObject\Property; - -use - Sabre\VObject\Property; - -/** - * Integer property - * - * This object represents INTEGER values. These are always a single integer. - * They may be preceeded by either + or -. - * - * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). - * @author Evert Pot (http://evertpot.com/) - * @license http://sabre.io/license/ Modified BSD License - */ -class Integer extends Property { - - /** - * Sets a raw value coming from a mimedir (iCalendar/vCard) file. - * - * This has been 'unfolded', so only 1 line will be passed. Unescaping is - * not yet done, but parameters are not included. - * - * @param string $val - * @return void - */ - public function setRawMimeDirValue($val) { - - $this->setValue((int)$val); - - } - - /** - * Returns a raw mime-dir representation of the value. - * - * @return string - */ - public function getRawMimeDirValue() { - - return $this->value; - - } - - /** - * Returns the type of value. - * - * This corresponds to the VALUE= parameter. Every property also has a - * 'default' valueType. - * - * @return string - */ - public function getValueType() { - - return "INTEGER"; - - } - - /** - * Returns the value, in the format it should be encoded for json. - * - * This method must always return an array. - * - * @return array - */ - public function getJsonValue() { - - return array((int)$this->getValue()); - - } -} diff --git a/vendor/sabre/vobject/lib/RecurrenceIterator.php b/vendor/sabre/vobject/lib/RecurrenceIterator.php deleted file mode 100644 index 92ea03ffe..000000000 --- a/vendor/sabre/vobject/lib/RecurrenceIterator.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -namespace Sabre\VObject; - -use Sabre\VObject\Recur\EventIterator; - -/** - * RecurrenceIterator - * - * This class is deprecated. Use Sabre\VObject\Recur\EventIterator instead. - * This class will be removed from a future version. - * - * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). - * @author Evert Pot (http://evertpot.com/) - * @deprecated - * @license http://sabre.io/license Modified BSD License - */ -class RecurrenceIterator extends EventIterator { - - -} -- cgit v1.2.3 From cac6cef4952e6535788c1c6db8ef1e58e88536a0 Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Sun, 29 May 2016 10:58:11 +0200 Subject: use composer to install sabre32 --- vendor/CHANGELOG.md | 2311 -------------------- vendor/LICENSE | 27 - vendor/README.md | 36 - vendor/autoload.php | 2 +- vendor/bin/generate_vcards | 242 +- vendor/bin/naturalselection | 141 +- vendor/bin/sabredav | 3 +- vendor/bin/vobject | 28 +- vendor/composer/autoload_real.php | 45 +- vendor/composer/autoload_static.php | 92 + vendor/examples/addressbookserver.php | 57 - vendor/examples/calendarserver.php | 76 - vendor/examples/fileserver.php | 56 - vendor/examples/groupwareserver.php | 101 - vendor/examples/minimal.php | 20 - vendor/examples/sql/mysql.addressbooks.sql | 28 - vendor/examples/sql/mysql.calendars.sql | 76 - vendor/examples/sql/mysql.locks.sql | 12 - vendor/examples/sql/mysql.principals.sql | 20 - vendor/examples/sql/mysql.propertystorage.sql | 9 - vendor/examples/sql/mysql.users.sql | 9 - vendor/examples/sql/pgsql.addressbooks.sql | 44 - vendor/examples/sql/pgsql.calendars.sql | 105 - vendor/examples/sql/pgsql.locks.sql | 19 - vendor/examples/sql/pgsql.principals.sql | 30 - vendor/examples/sql/pgsql.propertystorage.sql | 13 - vendor/examples/sql/pgsql.users.sql | 14 - vendor/examples/sql/sqlite.addressbooks.sql | 28 - vendor/examples/sql/sqlite.calendars.sql | 76 - vendor/examples/sql/sqlite.locks.sql | 12 - vendor/examples/sql/sqlite.principals.sql | 20 - vendor/examples/sql/sqlite.propertystorage.sql | 10 - vendor/examples/sql/sqlite.users.sql | 9 - vendor/examples/webserver/apache2_htaccess.conf | 16 - vendor/examples/webserver/apache2_vhost.conf | 29 - vendor/examples/webserver/apache2_vhost_cgi.conf | 21 - vendor/sabre/dav/CHANGELOG.md | 2311 ++++++++++++++++++++ vendor/sabre/dav/LICENSE | 27 + vendor/sabre/dav/README.md | 36 + vendor/sabre/dav/bin/build.php | 0 vendor/sabre/dav/bin/googlecode_upload.py | 0 vendor/sabre/dav/bin/migrateto20.php | 0 vendor/sabre/dav/bin/migrateto21.php | 0 vendor/sabre/dav/bin/migrateto30.php | 0 vendor/sabre/dav/bin/migrateto32.php | 0 vendor/sabre/dav/bin/sabredav.php | 0 vendor/sabre/vobject/bin/bench.php | 0 vendor/sabre/vobject/bin/fetch_windows_zones.php | 0 vendor/sabre/vobject/bin/generateicalendardata.php | 0 vendor/sabre/vobject/bin/mergeduplicates.php | 0 50 files changed, 2499 insertions(+), 3712 deletions(-) delete mode 100644 vendor/CHANGELOG.md delete mode 100644 vendor/LICENSE delete mode 100644 vendor/README.md mode change 100755 => 120000 vendor/bin/generate_vcards mode change 100755 => 120000 vendor/bin/naturalselection mode change 100755 => 120000 vendor/bin/sabredav mode change 100755 => 120000 vendor/bin/vobject create mode 100644 vendor/composer/autoload_static.php delete mode 100644 vendor/examples/addressbookserver.php delete mode 100644 vendor/examples/calendarserver.php delete mode 100644 vendor/examples/fileserver.php delete mode 100644 vendor/examples/groupwareserver.php delete mode 100644 vendor/examples/minimal.php delete mode 100644 vendor/examples/sql/mysql.addressbooks.sql delete mode 100644 vendor/examples/sql/mysql.calendars.sql delete mode 100644 vendor/examples/sql/mysql.locks.sql delete mode 100644 vendor/examples/sql/mysql.principals.sql delete mode 100644 vendor/examples/sql/mysql.propertystorage.sql delete mode 100644 vendor/examples/sql/mysql.users.sql delete mode 100644 vendor/examples/sql/pgsql.addressbooks.sql delete mode 100644 vendor/examples/sql/pgsql.calendars.sql delete mode 100644 vendor/examples/sql/pgsql.locks.sql delete mode 100644 vendor/examples/sql/pgsql.principals.sql delete mode 100644 vendor/examples/sql/pgsql.propertystorage.sql delete mode 100644 vendor/examples/sql/pgsql.users.sql delete mode 100644 vendor/examples/sql/sqlite.addressbooks.sql delete mode 100644 vendor/examples/sql/sqlite.calendars.sql delete mode 100644 vendor/examples/sql/sqlite.locks.sql delete mode 100644 vendor/examples/sql/sqlite.principals.sql delete mode 100644 vendor/examples/sql/sqlite.propertystorage.sql delete mode 100644 vendor/examples/sql/sqlite.users.sql delete mode 100644 vendor/examples/webserver/apache2_htaccess.conf delete mode 100644 vendor/examples/webserver/apache2_vhost.conf delete mode 100644 vendor/examples/webserver/apache2_vhost_cgi.conf create mode 100644 vendor/sabre/dav/CHANGELOG.md create mode 100644 vendor/sabre/dav/LICENSE create mode 100644 vendor/sabre/dav/README.md mode change 100755 => 100644 vendor/sabre/dav/bin/build.php mode change 100755 => 100644 vendor/sabre/dav/bin/googlecode_upload.py mode change 100755 => 100644 vendor/sabre/dav/bin/migrateto20.php mode change 100755 => 100644 vendor/sabre/dav/bin/migrateto21.php mode change 100755 => 100644 vendor/sabre/dav/bin/migrateto30.php mode change 100755 => 100644 vendor/sabre/dav/bin/migrateto32.php mode change 100755 => 100644 vendor/sabre/dav/bin/sabredav.php mode change 100755 => 100644 vendor/sabre/vobject/bin/bench.php mode change 100755 => 100644 vendor/sabre/vobject/bin/fetch_windows_zones.php mode change 100755 => 100644 vendor/sabre/vobject/bin/generateicalendardata.php mode change 100755 => 100644 vendor/sabre/vobject/bin/mergeduplicates.php diff --git a/vendor/CHANGELOG.md b/vendor/CHANGELOG.md deleted file mode 100644 index 079650965..000000000 --- a/vendor/CHANGELOG.md +++ /dev/null @@ -1,2311 +0,0 @@ -ChangeLog -========= - -3.2.0-beta1 (2016-05-20) ------------------------- - -* #833: Calendars throw exceptions when the sharing plugin is not enabled. -* #834: Return vCards exactly as they were stored if we don't need to convert - in between versions. - - -3.2.0-alpha1 (2016-05-09) -------------------------- - -* Database changes for CalDAV. If you are using the CalDAV PDO backends, you - must migrate. Run `./bin/migrateto32.php` for more info. -* Support for WebDAV Resource Sharing, an upcoming standard. -* Added support for sharing in the CalDAV PDO backend! Users can now invite - others to their calendar and give them read/read-write access! -* #397: Support for PSR-3. You can now log exceptions with your favourite - psr3-compatible logging tool. -* #825: Actual proper, tested support for PostgreSQL. We require version 9.5. -* Removed database migration script for sabre/dav 1.7. To update from that - version you now first need to update to sabre/dav 3.1. -* Removed deprecated function: `Sabre\DAV\Auth\Plugin::getCurrentUser()`. -* #774: Fixes for getting free disk space on Windows. -* #803: Major changes in the sharing API. If you were using an old sabre/dav - sharing api, head to the website for more detailed migration notes. -* #657: Support for optional auth using `{DAV:}unauthorized` and `{DAV:}all` - privileges. This allows you to assign a privilege to a resource, allowing - non-authenticated users to access it. For instance, this could allow you - to create a public read-only collection. -* #812 #814: ICS/VCF exporter now includes a more useful filename in its - `Content-Disposition` header. (@Xenopathic). -* #801: BC break: If you were using the `Href` object before, it's behavior - now changed a bit, and `LocalHref` was added to replace the old, default - behavior of `Href`. See the migration doc for more info. -* Removed `Sabre\DAVACL\Plugin::$allowAccessToNodesWithoutACL` setting. - Instead, you can provide a set of default ACL rules with - `Sabre\DAVACL\Plugin::setDefaultAcl()`. -* Introduced `Sabre\DAVACL\ACLTrait` which contains a default implementation - of `Sabre\DAV\IACL` with some sane defaults. We're using this trait all over - the place now, reducing the amount of boilerplate. -* Plugins can now control the "Supported Privilege Set". -* Added Sharing, ICSExport and VCFExport plugins to `groupwareserver.php` - example. -* The `{DAV:}all` privilege is now no longer abstract, so it can be assigned - directly. We're using the `{DAV:}all` privilege now in a lot of cases where - we before assigned both `{DAV:}read` and `{DAV:}write`. -* Resources that are not collections no longer support the `{DAV:}bind` and - `{DAV:}unbind` privileges. -* Corrected the CalDAV-scheduling related privileges. -* Doing an `UNLOCK` no longer requires the `{DAV:}write-content` privilege. -* Added a new `getPrincipalByUri` plugin event. Allowing plugins to request - quickly where a principal lives on a server. -* Renamed `phpunit.xml` to `phpunit.xml.dist` to make local modifications easy. -* Functionality from `IShareableCalendar` is merged into `ISharedCalendar`. -* #751: Fixed XML responses from failing `MKCOL` requests. -* #600: Support for `principal-match` ACL `REPORT`. -* #599: Support for `acl-principal-prop-set` ACL `REPORT`. -* #798: Added an index on `firstoccurence` field in MySQL CalDAV backend. This - should speed up common calendar-query requests. -* #759: DAV\Client is now able to actually correctly resolve relative urls. -* #671: We are no longer checking the `read-free-busy` privilege on individual - calendars during freebusy operations in the scheduling plugin. Instead, we - check the `schedule-query-freebusy` privilege on the target users' inbox, - which validates access for the entire account, per the spec. -* The zip release ships with [sabre/vobject 4.1.0][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.1.3 (2016-04-06) ------------------- - -* Set minimum libxml version to 2.7.0 in `composer.json`. -* #805: It wasn't possible to create calendars that hold events, journals and - todos using MySQL, because the `components` column was 1 byte too small. -* The zip release ships with [sabre/vobject 4.1.0][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.1.2 (2016-03-12) ------------------- - -* #784: Sync logs for address books were not correctly cleaned up after - deleting them. -* #787: Cannot use non-seekable stream-wrappers with range requests. -* Faster XML parsing and generating due to sabre/xml update. -* #793: The Sqlite schema is now more strict and more similar to the MySQL - schema. This solves a problem within Baikal. -* The zip release ships with [sabre/vobject 4.0.3][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.1.1 (2016-01-25) ------------------- - -* #755: The brower plugin and some operations would break when scheduling and - delegation would both be enabled. -* #757: A bunch of unittest improvements (@jakobsack). -* The zip release ships with [sabre/vobject 4.0.2][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. - - -3.1.0 (2016-01-06) ------------------- - -* Better error message when the browser plugin is not enabled. -* Added a super minimal server example. -* #730: Switched all mysql tables to `utf8mb4` character set, allowing you to - use emoji in some tables where you couldn't before. -* #710: Provide an Auth backend that acts as a helper for people implementing - OAuth2 Bearer token. (@fkooman). -* #729: Not all calls to `Sabre\DAV\Tree::getChildren()` were properly cached. -* #727: Added another workaround to make CalDAV work for Windows 10 clients. -* #742: Fixes to make sure that vobject 4 is correctly supported. -* #726: Better error reporting in `Client::propPatch`. We're now throwing - exceptions. -* #608: When a HTTP error is triggered during `Client:propFind`, we're now - throwing `Sabre\HTTP\ClientHttpException` instead of `Sabre\DAV\Exception`. - This new exception contains a LOT more information about the problem. -* #721: Events are now handled in the correct order for `COPY` requests. - Before this subtle bugs could appear that could cause data-loss. -* #747: Now throwing exceptions and setting the HTTP status to 500 in subtle - cases where no other plugin set a correct HTTP status. -* #686: Corrected PDO principal backend's findByURI for email addresses that - don't match the exact capitalization. -* #512: The client now has it's own `User-Agent`. -* #720: Some browser improvements. -* The zip release ships with [sabre/vobject 4.0.1][vobj], - [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. - - -3.1.0-alpha2 (2015-09-05) -------------------------- - -* Massive calendars and addressbooks should see a big drop in peak memory - usage. -* Fixed a privilege bug in the availability system. -* #697: Added a "tableName" member to the PropertyStorage PDO backend. (@Frzk). -* #699: PostgreSQL fix for the Locks PDO backend. (@TCKnet) -* Removed the `simplefsserver.php` example file. It's not simple enough. -* #703: PropPatch in client is not correctly encoded. -* #709: Throw exception when running into empty - `supported-calendar-component-set`. -* #711: Don't trigger deserializers for empty elements in `{DAV:}prop`. This - fixes issues when using sabre/dav as a client. -* The zip release ships with [sabre/vobject 4.0.0-alpha2][vobj], - [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. - - -3.1.0-alpha1 (2015-07-19) -------------------------- - -* Now requires PHP 5.5 -* Upgraded to vobject 4, which is a lot faster. -* Support for PHP 7. -* #690: Support for `calendar-availability`, draft 05. - [reference][calendar-availability]. -* #691: Workaround for broken Windows Phone client. -* The zip release ships with [sabre/vobject 4.0.0-alpha1][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. - - -3.0.9 (2016-04-06) ------------------- - -* Set minimum libxml version to 2.7.0 in `composer.json`. -* #727: Added another workaround to make CalDAV work for Windows 10 clients. -* #805: It wasn't possible to create calendars that hold events, journals and - todos using MySQL, because the `components` column was 1 byte too small. -* The zip release ships with [sabre/vobject 3.5.1][vobj], - [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.0.8 (2016-03-12) ------------------- - -* #784: Sync logs for address books were not correctly cleaned up after - deleting them. -* #787: Cannot use non-seekable stream-wrappers with range requests. -* Faster XML parsing and generating due to sabre/xml update. -* The zip release ships with [sabre/vobject 3.5.0][vobj], - [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. - - -3.0.7 (2016-01-12) ------------------- - -* #752: PHP 7 support for 3.0 branch. (@DeepDiver1975) -* The zip release ships with [sabre/vobject 3.5.0][vobj], - [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. - - -3.0.6 (2016-01-04) ------------------- - -* #730: Switched all mysql tables to `utf8mb4` character set, allowing you to - use emoji in some tables where you couldn't before. -* #729: Not all calls to `Sabre\DAV\Tree::getChildren()` were properly cached. -* #734: Return `418 I'm a Teapot` when generating a multistatus response that - has resources with no returned properties. -* #740: Bugs in `migrate20.php` script. -* The zip release ships with [sabre/vobject 3.4.8][vobj], - [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. - - -3.0.5 (2015-09-15) ------------------- - -* #704: Fixed broken uri encoding in multistatus responses. This affected - at least CyberDuck, but probably also others. -* The zip release ships with [sabre/vobject 3.4.7][vobj], -* The zip release ships with [sabre/vobject 3.4.7][vobj], - [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. - - -3.0.4 (2015-09-06) ------------------- - -* #703: PropPatch in client is not correctly encoded. -* #709: Throw exception when running into empty - `supported-calendar-component-set`. -* #711: Don't trigger deserializers for empty elements in `{DAV:}prop`. This - fixes issues when using sabre/dav as a client. -* #705: A `MOVE` request that gets prevented from deleting the source resource - will still remove the target resource. Now all events are triggered before - any destructive operations. -* The zip release ships with [sabre/vobject 3.4.7][vobj], - [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. - - -3.0.3 (2015-08-06) ------------------- - -* #700: Digest Auth fails on `HEAD` requests. -* Fixed example files to no longer use now-deprecated realm argument. -* The zip release ships with [sabre/vobject 3.4.6][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. - - -3.0.2 (2015-07-21) ------------------- - -* #657: Migration script would break when coming a cross an iCalendar object - with no UID. -* #691: Workaround for broken Windows Phone client. -* Fixed a whole bunch of incorrect php docblocks. -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. - - -3.0.1 (2015-07-02) ------------------- - -* #674: Postgres sql file fixes. (@davesouthey) -* #677: Resources with the name '0' would not get retrieved when using - `Depth: infinity` in a `PROPFIND` request. -* #680: Fix 'autoprefixing' of dead `{DAV:}href` properties. -* #675: NTLM support in DAV\Client. (@k42b3) -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. - - -3.0.0 (2015-06-02) ------------------- - -* No changes since last beta. -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. - - -3.0.0-beta3 (2015-05-29) ------------------------- - -* Fixed deserializing href properties with no value. -* Fixed deserializing `{DAV:}propstat` without a `{DAV:}prop`. -* #668: More information about vcf-export-plugin in browser plugin. -* #669: Add export button to browser plugin for address books. (@mgee) -* #670: multiget report hrefs were not decoded. -* The zip release ships with [sabre/vobject 3.4.4][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. - - -3.0.0-beta2 (2015-05-27) ------------------------- - -* A node's properties should not overwrite properties that were already set. -* Some uris were not correctly encoded in notifications. -* The zip release ships with [sabre/vobject 3.4.4][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. - - -3.0.0-beta1 (2015-05-25) ------------------------- - -* `migrate22.php` is now called `migrate30.php`. -* Using php-cs-fixer for automated coding standards enforcement and fixing. -* #660: principals could break html output. -* #662: Fixed several bugs in the `share` request parser. -* #665: Fix a bug in serialization of complex properties in the proppatch - request in the client. -* #666: expand-property report did not correctly prepend the base uri when - generating uris, this caused delegation to break. -* #659: Don't throw errors when when etag-related checks are done on - collections. -* Fully supporting the updated `Prefer` header syntax, as defined in - [rfc7240][rfc7240]. -* The zip release ships with [sabre/vobject 3.4.3][vobj], - [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. - - -3.0.0-alpha1 (2015-05-19) -------------------------- - -* It's now possible to get all property information from files using the - browser plugin. -* Browser plugin will now show a 'calendar export' button when the - ics-export plugin is enabled. -* Some nodes that by default showed the current time as their last - modification time, now no longer has a last modification time. -* CardDAV namespace was missing from default namespaceMap. -* #646: Properties can now control their own HTML output in the browser plugin. -* #646: Nicer HTML output for the `{DAV:}acl` property. -* Browser plugin no longer shows a few properties that take up a lot of space, - but are likely not really interesting for most users. -* #654: Added a collection, `Sabre\DAVACL\FS\HomeCollection` for automatically - creating a private home collection per-user. -* Changed all MySQL columns from `VARCHAR` to `VARBINARY` where possible. -* Improved older migration scripts a bit to allow easier testing. -* The zip release ships with [sabre/vobject 3.4.3][vobj], - [sabre/http 4.0.0-alpha3][http], [sabre/event 2.0.2][evnt], - [sabre/uri 1.0.1][uri] and [sabre/xml 0.4.3][xml]. - - -2.2.0-alpha4 (2015-04-13) -------------------------- - -* Complete rewrite of the XML system. We now use our own [sabre/xml][xml], - which has a much smarter XML Reader and Writer. -* BC Break: It's no longer possible to instantiate the Locks plugin without - a locks backend. I'm not sure why this ever made sense. -* Simplified the Locking system and fixed a bug related to if tokens checking - locks unrelated to the current request. -* `FSExt` Directory and File no longer do custom property storage. This - functionality is already covered pretty well by the `PropertyStorage` plugin, - so please switch. -* Renamed `Sabre\CardDAV\UserAddressBooks` to `Sabre\CardDAV\AddressBookHome` - to be more consistent with `CalendarHome` as well as the CardDAV - specification. -* `Sabre\DAV\IExtendedCollection` now receives a `Sabre\DAV\MkCol` object as - its second argument, and no longer receives seperate properties and - resourcetype arguments. -* `MKCOL` now integrates better with propertystorage plugins. -* #623: Remove need of temporary files when working with Range requests. - (@dratini0) -* The zip release ships with [sabre/vobject 3.4.2][vobj], - [sabre/http 4.0.0-alpha1][http], [sabre/event 2.0.1][evnt], - [sabre/uri 1.0.0][uri] and [sabre/xml 0.4.3][xml]. - - -2.2.0-alpha3 (2015-02-25) -------------------------- - -* Contains all the changes introduced between 2.1.2 and 2.1.3. -* The zip release ships with [sabre/vobject 3.4.2][vobj], - [sabre/http 4.0.0-alpha1][http], [sabre/event 2.0.1][evnt] and - [sabre/uri 1.0.0][uri]. - - -2.2.0-alpha2 (2015-01-09) -------------------------- - -* Renamed `Sabre\DAV\Auth\Backend\BackendInterface::requireAuth` to - `challenge`, which is a more correct and better sounding name. -* The zip release ships with [sabre/vobject 3.3.5][vobj], - [sabre/http 3.0.4][http], [sabre/event 2.0.1][evnt]. - - -2.2.0-alpha1 (2014-12-10) -------------------------- - -* The browser plugin now has a new page with information about your sabredav - server, and shows information about every plugin that's loaded in the - system. -* #191: The Authentication system can now support multiple authentication - backends. -* Removed: all `$tableName` arguments from every PDO backend. This was already - deprecated, but has now been fully removed. All of these have been replaced - with public properties. -* Deleted several classes that were already deprecated much earlier: - * `Sabre\CalDAV\CalendarRootNode` - * `Sabre\CalDAV\UserCalendars` - * `Sabre\DAV\Exception\FileNotFound` - * `Sabre\DAV\Locks\Backend\FS` - * `Sabre\DAV\PartialUpdate\IFile` - * `Sabre\DAV\URLUtil` -* Removed: `Sabre\DAV\Client::addTrustedCertificates` and - `Sabre\DAV\Client::setVerifyPeer`. -* Removed: `Sabre\DAV\Plugin::getPlugin()` can now no longer return plugins - based on its class name. -* Removed: `Sabre\DAVACL\Plugin::getPrincipalByEmail()`. -* #560: GuessContentType plugin will now set content-type to - `application/octet-stream` if a better content-type could not be determined. -* #568: Added a `componentType` argument to `ICSExportPlugin`, allowing you to - specifically fetch `VEVENT`, `VTODO` or `VJOURNAL`. -* #582: Authentication backend interface changed to be stateless. If you - implemented your own authentication backend, make sure you upgrade your class - to the latest API! -* #582: `Sabre\DAV\Auth\Plugin::getCurrentUser()` is now deprecated. Use - `Sabre\DAV\Auth\Plugin::getCurrentPrincipal()` instead. -* #193: Fix `Sabre\DAV\FSExt\Directory::getQuotaInfo()` on windows. - - -2.1.11 (2016-??-??) -------------------- - -* #805: It wasn't possible to create calendars that hold events, journals and - todos using MySQL, because the `components` column was 1 byte too small. - - -2.1.10 (2016-03-10) -------------------- - -* #784: Sync logs for address books were not correctly cleaned up after - deleting them. - - -2.1.9 (2016-01-25) ------------------- - -* #674: PHP7 support (@DeepDiver1975). -* The zip release ships with [sabre/vobject 3.5.0][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.8 (2016-01-04) ------------------- - -* #729: Fixed a caching problem in the Tree object. -* #740: Bugs in `migrate20.php` script. -* The zip release ships with [sabre/vobject 3.4.8][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.7 (2015-09-05) ------------------- - -* #705: A `MOVE` request that gets prevented from deleting the source resource - will still remove the target resource. Now all events are triggered before - any destructive operations. -* The zip release ships with [sabre/vobject 3.4.7][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.6 (2015-07-21) ------------------- - -* #657: Migration script would break when coming a cross an iCalendar object - with no UID. -* #691: Workaround for broken Windows Phone client. -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.5 (2015-07-11) ------------------- - -* #677: Resources with the name '0' would not get retrieved when using - `Depth: infinity` in a `PROPFIND` request. -* The zip release ships with [sabre/vobject 3.4.5][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.4 (2015-05-25) ------------------- - -* #651: Double-encoded path in the browser plugin. Should fix a few broken - links in some setups. -* #650: Correctly cleaning up change info after deleting calendars (@ErrOrnAmE). -* #658: Updating `schedule-calendar-default-URL` does not work well, so we're - disabling it until there's a better fix. -* The zip release ships with [sabre/vobject 3.4.3][vobj], - [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. - - -2.1.3 (2015-02-25) ------------------- - -* #586: `SCHEDULE-STATUS` should not contain a reason-phrase. -* #539: Fixed a bug related to scheduling in shared calendars. -* #595: Support for calendar-timezone in iCalendar exports. -* #581: findByUri would send empty prefixes to the principal backend (@soydeedo) -* #611: Escaping a bit more HTML output in the browser plugin. (@LukasReschke) -* #610: Don't allow discovery of arbitrary files using `..` in the browser - plugin (@LukasReschke). -* Browser plugin now shows quota properties. -* #612: PropertyStorage didn't delete properties from nodes when a node's - parents get deleted. -* #581: Fixed problems related to finding attendee information during - scheduling. -* The zip release ships with [sabre/vobject 3.4.2][vobj], - [sabre/http 3.0.4][http], and [sabre/event 2.0.1][evnt]. - - -2.1.2 (2014-12-10) ------------------- - -* #566: Another issue related to the migration script, which would cause - scheduling to not work well for events that were already added before the - migration. -* #567: Doing freebusy requests on accounts that had 0 calendars would throw - a `E_NOTICE`. -* #572: `HEAD` requests trigger a PHP warning. -* #579: Browser plugin can throw exception for a few resourcetypes that didn't - have an icon defined. -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 3.0.4][http], and [sabre/event 2.0.1][evnt]. - - -2.1.1 (2014-11-22) ------------------- - -* #561: IMip Plugin didn't strip mailto: from email addresses. -* #566: Migration process had 2 problems related to adding the `uid` field - to the `calendarobjects` table. -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. - - -2.1.0 (2014-11-19) ------------------- - -* #541: CalDAV PDO backend didn't respect overridden PDO table names. -* #550: Scheduling invites are no longer delivered into shared calendars. -* #554: `calendar-multiget` `REPORT` did not work on inbox items. -* #555: The `calendar-timezone` property is now respected for floating times - and all-day events in the `calendar-query`, `calendar-multiget` and - `free-busy-query` REPORTs. -* #555: The `calendar-timezone` property is also respected for scheduling - free-busy requests. -* #547: CalDAV system too aggressively 'corrects' incoming iCalendar data, and - as a result doesn't return an etag for common cases. -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. - - -2.1.0-alpha2 (2014-10-23) -------------------------- - -* Added: calendar-user-address-set to default principal search properties - list. This should fix iOS attendee autocomplete support. -* Changed: Moved all 'notifications' functionality from `Sabre\CalDAV\Plugin` - to a new plugin: `Sabre\CalDAV\Notifications\Plugin`. If you want to use - notifications-related functionality, just add this plugin. -* Changed: Accessing the caldav inbox, outbox or notification collection no - longer triggers getCalendarsForUser() on backends. -* #533: New invites are no longer delivered to taks-only calendars. -* #538: Added `calendarObjectChange` event. -* Scheduling speedups. -* #539: added `afterResponse` event. (@joserobleda) -* Deprecated: All the "tableName" constructor arguments for all the PDO - backends are now deprecated. They still work, but will be removed in the - next major sabredav version. Every argument that is now deprecated can now - be accessed as a public property on the respective backends. -* #529: Added getCalendarObjectByUID to PDO backend, speeding up scheduling - operations on large calendars. -* The zip release ships with [sabre/vobject 3.3.3][vobj], - [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. - - -2.1.0-alpha1 (2014-09-23) -------------------------- - -* Added: Support for [rfc6638][rfc6638], also known as CalDAV Scheduling. -* Added: Automatically converting between vCard 3, 4 and jCard using the - `Accept:` header, in CardDAV reports, and automatically converting from - jCard to vCard upon `PUT`. It's important to note that your backends _may_ - now recieve both vCard 3.0 and 4.0. -* Added: #444. Collections can now opt-in to support high-speed `MOVE`. -* Changed: PropertyStorage backends now have a `move` method. -* Added: `beforeMove`, and `afterMove` events. -* Changed: A few database changes for the CalDAV PDO backend. Make sure you - run `bin/migrate21.php` to upgrade your database schema. -* Changed: CalDAV backends have a new method: `getCalendarObjectByUID`. This - method MUST be implemented by all backends, but the `AbstractBackend` has a - simple default implementation for this. -* Changed: `Sabre\CalDAV\UserCalendars` has been renamed to - `Sabre\CalDAV\CalendarHome`. -* Changed: `Sabre\CalDAV\CalendarRootNode` has been renamed to - `Sabre\CalDAV\CalendarRoot`. -* Changed: The IMipHandler has been completely removed. With CalDAV scheduling - support, it is no longer needed. It's functionality has been replaced by - `Sabre\CalDAV\Schedule\IMipPlugin`, which can now send emails for clients - other than iCal. -* Removed: `Sabre\DAV\ObjectTree` and `Sabre\DAV\Tree\FileSystem`. All this - functionality has been merged into `Sabre\DAV\Tree`. -* Changed: PrincipalBackend now has a findByUri method. -* Changed: `PrincipalBackend::searchPrincipals` has a new optional `test` - argument. -* Added: Support for the `{http://calendarserver.org/ns/}email-address-set` - property. -* #460: PropertyStorage must move properties during `MOVE` requests. -* Changed: Restructured the zip distribution to be a little bit more lean - and consistent. -* #524: Full support for the `test="anyof"` attribute in principal-search - `REPORT`. -* #472: Always returning lock tokens in the lockdiscovery property. -* Directory entries in the Browser plugin are sorted by type and name. - (@aklomp) -* #486: It's now possible to return additional properties when an 'allprop' - PROPFIND request is being done. (@aklomp) -* Changed: Now return HTTP errors when an addressbook-query REPORT is done - on a uri that's not a vcard. This should help with debugging this common - mistake. -* Changed: `PUT` requests with a `Content-Range` header now emit a 400 status - instead of 501, as per RFC7231. -* Added: Browser plugin can now display the contents of the - `{DAV:}supported-privilege-set` property. -* Added: Now reporting `CALDAV:max-resource-size`, but we're not actively - restricting it yet. -* Changed: CalDAV plugin is now responsible for reporting - `CALDAV:supported-collation-set` and `CALDAV:supported-calendar-data` - properties. -* Added: Now reporting `CARDDAV:max-resource-size`, but we're not actively - restricting it yet. -* Added: Support for `CARDDAV:supported-collation-set`. -* Changed: CardDAV plugin is now responsible for reporting - `CARDDAV:supported-address-data`. This functionality has been removed from - the CardDAV PDO backend. -* When a REPORT is not supported, we now emit HTTP error 415, instead of 403. -* #348: `HEAD` requests now work wherever `GET` also works. -* Changed: Lower priority for the iMip plugins `schedule` event listener. -* Added: #523 Custom CalDAV backends can now mark any calendar as read-only. -* The zip release ships with [sabre/vobject 3.3.3][vobj], - [sabre/http 3.0.0][http], and [sabre/event 2.0.0][evnt]. - - -2.0.9 (2015-09-04) ------------------- - -* #705: A `MOVE` request that gets prevented from deleting the source resource - will still remove the target resource. Now all events are triggered before - any destructive operations. -* The zip release ships with [sabre/vobject 3.4.6][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - - -2.0.8 (2015-07-11) ------------------- - -* #677: Resources with the name '0' would not get retrieved when using - `Depth: infinity` in a `PROPFIND` request. -* The zip release ships with [sabre/vobject 3.3.5][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.7 (2015-05-25) ------------------- - -* #650: Correctly cleaning up change info after deleting calendars (@ErrOrnAmE). -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.6 (2014-12-10) ------------------- - -* Added `Sabre\CalDAV\CalendarRoot` as an alias for - `Sabre\CalDAV\CalendarRootNode`. The latter is going to be deprecated in 2.1, - so this makes it slightly easier to write code that works in both branches. -* #497: Making sure we're initializing the sync-token field with a value after - migration. -* The zip release ships with [sabre/vobject 3.3.4][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.5 (2014-10-14) ------------------- - -* #514: CalDAV PDO backend didn't work when overriding the 'calendar changes' - database table name. -* #515: 304 status code was not being sent when checking preconditions. -* The zip release ships with [sabre/vobject 3.3.3][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.4 (2014-08-27) ------------------- - -* #483: typo in calendars creation for PostgreSQL. -* #487: Locks are now automatically removed after a node has been deleted. -* #496: Improve CalDAV and CardDAV sync when there is no webdav-sync support. -* Added: Automatically mapping internal sync-tokens to getctag. -* The zip release ships with [sabre/vobject 3.3.1][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.3 (2014-07-14) ------------------- - -* #474: Fixed PropertyStorage `pathFilter()`. -* #476: CSP policy incorrect, causing stylesheets to not load in the browser - plugin. -* #475: Href properties in the browser plugin sometimes included a backslash. -* #478: `TooMuchMatches` exception never worked. This was fixed, and we also - took this opportunity to rename it to `TooManyMatches`. -* The zip release ships with [sabre/vobject 3.2.4][vobj], - [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. - - -2.0.2 (2014-06-12) ------------------- - -* #470: Fixed compatibility with PHP < 5.4.14. -* #467: Fixed a problem in `examples/calendarserver.php`. -* #466: All the postgresql sample files have been updated. -* Fixed: An error would be thrown if a client did a propfind on a node the - user didn't have access to. -* Removed: Old and broken example code from the `examples/` directory. -* The zip release ships with [sabre/vobject 3.2.3][vobj], - [sabre/http 2.0.3][http], and [sabre/event 1.0.1][evnt]. - - -2.0.1 (2014-05-28) ------------------- - -* #459: PROPFIND requests on Files with no Depth header would return a fatal - error. -* #464: A PROPFIND allprops request should not return properties with status - 404. -* The zip release ships with [sabre/vobject 3.2.2][vobj], - [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. - - -2.0.0 (2014-05-22) ------------------- - -* The zip release ships with [sabre/vobject 3.2.2][vobj], - [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. -* Fixed: #456: Issue in sqlite migration script. -* Updated: MySQL database schema optimized by using more efficient column types. -* Cleaned up browser design. - - -2.0.0-beta1 (2014-05-15) -------------------------- - -* The zip release ships with [sabre/vobject 3.2.2][vobj], - [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. -* BC Break: Property updating and fetching got refactored. Read the [migration - document][mi20] for more information. This allows for creation of a generic - property storage, and other property-related functionality that was not - possible before. -* BC Break: Removed `propertyUpdate`, `beforeGetProperties` and - `afterGetProperties` events. -* Fixed: #413: Memory optimizations for the CardDAV PDO backend. -* Updated: Brand new browser plugin with more debugging features and a design - that is slightly less painful. -* Added: Support for the `{DAV:}supported-method-set` property server-wide. -* Making it easier for implementors to override how the CardDAV addressbook - home is located. -* Fixed: Issue #422 Preconditions were not being set on PUT on non-existant - files. Not really a chance for data-loss, but incorrect nevertheless. -* Fixed: Issue #428: Etag check with `If:` fails if the target is a collection. -* Fixed: Issues #430, #431, #433: Locks plugin didn't not properly release - filesystem based locks. -* Fixed: #443. Support for creating new calendar subscriptions for OS X 10.9.2 - and up. -* Removed: `Sabre\DAV\Server::NODE_*` constants. -* Moved all precondition checking into a central place, instead of having to - think about it on a per-method basis. -* jCal transformation for calendar-query REPORT now works again. -* Switched to PSR-4 -* Fixed: #175. Returning ETag header upon a failed `If-Match` or - `If-None-Match` check. -* Removed: `lib/Sabre/autoload.php`. Use `vendor/autoload.php` instead. -* Removed: all the rfc documentation from the sabre/dav source. This made the - package needlessly larger. -* Updated: Issue #439. Lots of updates in PATCH support. The - Sabre_DAV_PartialUpdate_IFile interface is now deprecated and will be - removed in a future version. -* Added: `Sabre\DAV\Exception\LengthRequired`. - -1.9.0-alpha2 (2014-01-14) -------------------------- - -* The zip release ships with sabre/vobject 3.1.3, sabre/http 2.0.1, and - sabre/event 1.0.0. -* Added: Browser can now inspect any node, if ?sabreaction=browser is appended. -* Fixed: Issue #178. Support for multiple items in the Timeout header. -* Fixed: Issue #382. Stricter checking if calendar-query is allowed to run. -* Added: Depth: Infinity support for PROPFIND request. Thanks Thomas Müller and - Markus Goetz. - - -1.9.0-alpha1 (2013-11-07) -------------------------- - -* The zip release ships with sabre/vobject 3.1.3, sabre/http 2.0.0alpha5, and - sabre/event 1.0.0. -* BC Break: The CardDAV and CalDAV BackendInterface each have a new method: - getMultipleCards and getMultipleCalendarObjects. The Abstract and PDO backends - have default implementations, but if you implement that interface directly, - this method is now required. -* BC Break: XML property classes now receive an extra argument in their - unserialize method ($propertyMap). This allows for recursively parsing - properties, if needed. -* BC Break: Now using sabre/event for event emitting/subscription. For plugin - authors this means Server::subscribeEvent is now Server::on, and - Server::broadcastEvent is now Server::emit. -* BC Break: Almost all core functionality moved into a CorePlugin. -* BC Break: Most events triggered by the server got an overhaul. -* Changed: Sabre\HTTP now moved into a dedicated sabre/http package. -* Added: Support for WebDAV-sync (rfc6578). -* Added: Support for caldav-subscriptions, which is an easy way for caldav - clients to manage a list of subscriptions on the server. -* Added: Support for emitting and receiving jCal instead of iCalendar for - CalDAV. -* Added: BasicCallback authenticaton backend, for creating simple authentication - systems without having to define any classes. -* Added: A $transactionType property on the server class. This can be used for - logging and performance measuring purposes. -* Fixed: If event handlers modify the request body from a PUT request, an ETag - is no longer sent back. -* Added: Sabre\DAV\IMultiGet to optimize requests that retrieve information - about lists of resources. -* Added: MultiGet support to default CalDAV and CardDAV backends, speeding up - the multiget and sync reports quite a bit! -* Added: ICSExportPlugin can now generate jCal, filter on time-ranges and expand - recurrences. -* Fixed: Read-only access to calendars still allows the sharee to modify basic - calendar properties, such as the displayname and color. -* Changed: The default supportedPrivilegeSet has changed. Most privileges are no - longer marked as abstract. -* Changed: More elegant ACL management for CalendarObject and Card nodes. -* Added: Browser plugin now marks a carddav directory as type Directory, and a - shared calendar as 'Shared'. -* Added: When debugExceptions is turned on, all previous exceptions are also - traversed. -* Removed: Got rid of the Version classes for CalDAV, CardDAV, HTTP, and DAVACL. - Now that there's no separate packages anymore, this makes a bit more sense. -* Added: Generalized the multistatus response parser a bit more, for better - re-use. -* Added: Sabre\DAV\Client now has support for complex properties for PROPPATCH. - (Issue #299). -* Added: Sabre\DAV\Client has support for gzip and deflate encoding. -* Added: Sabre\DAV\Client now has support for sending objects as streams. -* Added: Deserializer for {DAV:}current-user-privilege-set. -* Added: Addressbooks or backends can now specify custom acl rules when creating - cards. -* Added: The ability for plugins to validate custom tokens in If: headers. -* Changed: Completely refactored the Lock plugin to deal with the new If: header - system. -* Added: Checking preconditions for MOVE, COPY, DELETE and PROPPATCH methods. -* Added: has() method on DAV\Property\SupportedReportSet. -* Added: If header now gets checked (with ETag) all the time. Before the dealing - with the If-header was a responsibility of the Locking plugin. -* Fixed: Outbox access for delegates. -* Added: Issue 333: It's now possible to override the calendar-home in the - CalDAV plugin. -* Added: A negotiateContentType to HTTP\Request. A convenience method. -* Fixed: Issue 349: Denying copying or moving a resource into it's own subtree. -* Fixed: SabreDAV catches every exception again. -* Added: Issue #358, adding a component=vevent parameter to the content-types - for calendar objects, if the caldav backend provides this info. - - -1.8.12-stable (2015-01-21) --------------------------- - -* The zip release ships with sabre/vobject 2.1.7. -* #568: Support empty usernames and passwords in basic auth. - - -1.8.11 (2014-12-10) -------------------- - -* The zip release ships with sabre/vobject 2.1.6. -* Updated: MySQL database schema optimized by using more efficient column types. -* #516: The DAV client will now only redirect to HTTP and HTTPS urls. - - -1.8.10 (2014-05-15) -------------------- - -* The zip release ships with sabre/vobject 2.1.4. -* includes changes from version 1.7.12. - - -1.8.9 (2014-02-26) ------------------- - -* The zip release ships with sabre/vobject 2.1.3. -* includes changes from version 1.7.11. - - -1.8.8 (2014-02-09) ------------------- - -* includes changes from version 1.7.10. -* The zip release ships with sabre/vobject 2.1.3. - -1.8.7 (2013-10-02) ------------------- - -* the zip release ships with sabre/vobject 2.1.3. -* includes changes from version 1.7.9. - - -1.8.6 (2013-06-18) ------------------- - -* The zip release ships with sabre/vobject 2.1.0. -* Includes changes from version 1.7.8. - - -1.8.5 (2013-04-11) ------------------- - -* The zip release ships with sabre/vobject 2.0.7. -* Includes changes from version 1.7.7. - - -1.8.4 (2013-04-08) ------------------- - -* The zip release ships with sabre/vobject 2.0.7. -* Includes changes from version 1.7.6. - - -1.8.3 (2013-03-01) ------------------- - -* The zip release ships with sabre/vobject 2.0.6. -* Includes changes from version 1.7.5. -* Fixed: organizer email-address for shared calendars is now prefixed with - mailto:, as it should. - - -1.8.2 (2013-01-19) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Includes changes from version 1.7.4. - - -1.8.1 (2012-12-01) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Includes changes from version 1.7.3. -* Fixed: Typo in 1.7 migration script caused it to fail. - - -1.8.0 (2012-11-08) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* BC Break: Moved the entire codebase to PHP namespaces. -* BC Break: Every backend package (CalDAV, CardDAV, Auth, Locks, Principals) now - has consistent naming conventions. There's a BackendInterface, and an - AbstractBackend class. -* BC Break: Changed a bunch of constructor signatures in the CalDAV package, to - reduce dependencies on the ACL package. -* BC Break: Sabre_CalDAV_ISharedCalendar now also has a getShares method, so - sharees can figure out who is also on a shared calendar. -* Added: Sabre_DAVACL_IPrincipalCollection interface, to advertise support for - principal-property-search on any node. -* Added: Simple console script to fire up a fileserver in the current directory - using PHP 5.4's built-in webserver. -* Added: Sharee's can now also read out the list of invites for a shared - calendar. -* Added: The Proxy principal classes now both implement an interface, for - greater flexiblity. - - -1.7.13 (2014-07-28) -------------------- - -* The zip release ships with sabre/vobject 2.1.4. -* Changed: Removed phing and went with a custom build script for now. - - -1.7.12 (2014-05-15) -------------------- - -* The zip release ships with sabre/vobject 2.1.4. -* Updated: Issue #439. Lots of updates in PATCH support. The - Sabre_DAV_PartialUpdate_IFile interface is now deprecated and will be removed - in a future version. -* Fixed: Restoring old setting after changing libxml_disable_entity_loader. -* Fixed: Issue #422: Preconditions were not being set on PUT on non-existant - files. Not really a chance for data-loss, but incorrect nevertheless. -* Fixed: Issue #427: Now checking preconditions on DELETE requests. -* Fixed: Issue #428: Etag check with If: fails if the target is a collection. -* Fixed: Issue #393: PATCH request with missing end-range was handled - incorrectly. -* Added: Sabre_DAV_Exception_LengthRequired to omit 411 errors. - - -1.7.11 (2014-02-26) -------------------- - -* The zip release ships with sabre/vobject 2.1.3. -* Fixed: Issue #407: large downloads failed. -* Fixed: Issue #414: XXE security problem on older PHP versions. - - -1.7.10 (2014-02-09) -------------------- - -* Fixed: Issue #374: Don't urlescape colon (:) when it's not required. -* Fixed: Potential security vulnerability in the http client. - - -1.7.9 (2013-10-02) ------------------- - -* The zip release ships with sabre/vobject 2.1.3. -* Fixed: Issue #365. Incorrect output when principal urls have spaces in them. -* Added: Issue #367: Automatically adding a UID to vcards that don't have them. - - -1.7.8 (2013-06-17) ------------------- - -* The zip release ships with sabre/vobject 2.1.0. -* Changed: Sabre\DAV\Client::verifyPeer is now a protected property (instead of - private). -* Fixed: Text was incorrectly escaped in the Href and HrefList properties, - disallowing urls with ampersands (&) in them. -* Added: deserializer for Sabre\DAVACL\Property\CurrentUserPrivilegeSet. -* Fixed: Issue 335: Client only deserializes properties with status 200. -* Fixed: Issue 341: Escaping xml in 423 Locked error responses. -* Added: Issue 339: beforeGetPropertiesForPath event. - - -1.7.7 (2013-04-11) ------------------- - -* The zip release ships with sabre/vobject 2.0.7. -* Fixed: Assets in the browser plugins were not being served on windows - machines. - - -1.7.6 (2013-04-08) ------------------- - -* The zip release ships with sabre/vobject 2.0.7. -* Fixed: vcardurl in database schema can now hold 255 characters instead of 80 - (which is often way to small). -* Fixed: The browser plugin potentially allowed people to open any arbitrary - file on windows servers (CVE-2013-1939). - - -1.7.5 (2013-03-01) ------------------- - -* The zip release ships with sabre/vobject 2.0.6. -* Change: No longer advertising support for 4.0 vcards. iOS and OS X address - book don't handle this well, and just advertising 3.0 support seems like the - most logical course of action. -* Added: ->setVerifyPeers to Sabre_DAV_Client (greatly resisting against it, - don't use this..). - - -1.7.4 (2013-01-19) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Changed: To be compatibile with MS Office 2011 for Mac, a workaround was - removed that was added to support old versions of Windows XP (pre-SP3). - Indeed! We needed a crazy workaround to work with one MS product in the past, - and we can't keep that workaround to be compatible with another MS product. -* Fixed: expand-properties REPORT had incorrect values for the href element. -* Fixed: Range requests now work for non-seekable streams. (Thanks Alfred - Klomp). -* Fixed: Changed serialization of {DAV:}getlastmodified and {DAV:}supportedlock - to improve compatiblity with MS Office 2011 for Mac. -* Changed: reverted the automatic translation of 'DAV:' xml namespaces to - 'urn:DAV' when parsing files. Issues were reported with libxml 2.6.32, on a - relatively recent debian release, so we'll wait till 2015 to take this one out - again. -* Added: Sabre_DAV_Exception_ServiceUnavailable, for emitting 503's. - - -1.7.3 (2012-12-01) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Fixed: Removing double slashes from getPropertiesForPath. -* Change: Marked a few more properties in the CardDAV as protected, instead of - private. -* Fixed: SharingPlugin now plays nicer with other plugins with similar - functionality. -* Fixed: Issue 174. Sending back HTTP/1.0 for requests with this version. - - -1.7.2 (2012-11-08) ------------------- - -* The zip release ships with sabre/vobject 2.0.5. -* Added: ACL plugin advertises support for 'calendarserver-principal- - property-search'. -* Fixed: [#153] Allowing for relative http principals in iMip requests. -* Added: Support for cs:first-name and cs:last-name properties in sharing - invites. -* Fixed: Made a bunch of properties protected, where they were private before. -* Added: Some non-standard properties for sharing to improve compatibility. -* Fixed: some bugfixes in postgres sql script. -* Fixed: When requesting some properties using PROPFIND, they could show up as - both '200 Ok' and '403 Forbidden'. -* Fixed: calendar-proxy principals were not checked for deeper principal - membership than 1 level. -* Fixed: setGroupMemberSet argument now correctly receives relative principal - urls, instead of the absolute ones. -* Fixed: Server class will filter out any bonus properties if any extra were - returned. This means the implementor of the IProperty class can be a bit - lazier when implementing. Note: bug numbers after this line refer to Google - Code tickets. We're using github now. - - -1.7.1 (2012-10-07) ------------------- - -* Fixed: include path problem in the migration script. - - -1.7.0 (2012-10-06) ------------------- - -* BC Break: The calendarobjects database table has a bunch of new fields, and a - migration script is required to ensure everything will keep working. Read the - wiki for more details. -* BC Break: The ICalendar interface now has a new method: calendarQuery. -* BC Break: In this version a number of classes have been deleted, that have - been previously deprecated. Namely: - Sabre_DAV_Directory (now: - Sabre_DAV_Collection) - Sabre_DAV_SimpleDirectory (now: - Sabre_DAV_SimpleCollection) -* BC Break: Sabre_CalDAV_Schedule_IMip::sendMessage now has an extra argument. - If you extended this class, you should fix this method. It's only used for - informational purposes. -* BC Break: The DAV: namespace is no longer converted to urn:DAV. This was a - workaround for a bug in older PHP versions (pre-5.3). -* Removed: Sabre.includes.php was deprecated, and is now removed. -* Removed: Sabre_CalDAV_Server was deprecated, and is now removed. Please use - Sabre_DAV_Server and check the examples in the examples/ directory. -* Changed: The Sabre_VObject library now spawned into it's own project! The - VObject library is still included in the SabreDAV zip package. -* Added: Experimental interfaces to allow implementation of caldav-sharing. Note - that no implementation is provided yet, just the api hooks. -* Added: Free-busy reporting compliant with the caldav-scheduling standard. This - allows iCal and other clients to fetch other users' free-busy data. -* Added: Experimental NotificationSupport interface to add caldav notifications. -* Added: VCF Export plugin. If enabled, it can generate an export of an entire - addressbook. -* Added: Support for PATCH using a SabreDAV format, to live-patch files. -* Added: Support for Prefer: return-minimal and Brief: t headers for PROPFIND - and PROPPATCH requests. -* Changed: Responsibility for dealing with the calendar-query is now moved from - the CalDAV plugin to the CalDAV backends. This allows for heavy optimizations. -* Changed: The CalDAV PDO backend is now a lot faster for common calendar - queries. -* Changed: We are now using the composer autoloader. -* Changed: The CalDAV backend now all implement an interface. -* Changed: Instead of Sabre_DAV_Property, Sabre_DAV_PropertyInterface is now the - basis of every property class. -* Update: Caching results for principal lookups. This should cut down queries - and performance for a number of heavy requests. -* Update: ObjectTree caches lookups much more aggresively, which will help - especially speeding up a bunch of REPORT queries. -* Added: Support for the schedule-calendar-transp property. -* Fixed: Marking both the text/calendar and text/x-vcard as UTF-8 encoded. -* Fixed: Workaround for the SOGO connector, as it doesn't understand receiving - "text/x-vcard; charset=utf-8" for a contenttype. -* Added: Sabre_DAV_Client now throws more specific exceptions in cases where we - already has an exception class. -* Added: Sabre_DAV_PartialUpdate. This plugin allows you to use the PATCH method - to update parts of a file. -* Added: Tons of timezone name mappings for Microsoft Exchange. -* Added: Support for an 'exception' event in the server class. -* Fixed: Uploaded VCards without a UID are now rejected. (thanks Dominik!) -* Fixed: Rejecting calendar objects if they are not in the - supported-calendar-component list. (thanks Armin!) -* Fixed: Issue 219: serialize() now reorders correctly. -* Fixed: Sabre_DAV_XMLUtil no longer returns empty $dom->childNodes if there is - whitespace in $dom. -* Fixed: Returning 409 Conflict instead of 500 when an attempt is made to create - a file as a child of something that's not a collection. -* Fixed: Issue 237: xml-encoding values in SabreDAV error responses. -* Fixed: Returning 403, instead of 501 when an unknown REPORT is requested. -* Fixed: Postfixing slash on {DAV:}owner properties. -* Fixed: Several embarrassing spelling mistakes in docblocks. - - -1.6.10 (2013-06-17) -------------------- - -* Fixed: Text was incorrectly escaped in the Href and HrefList properties, - disallowing urls with ampersands (&) in them. -* Fixed: Issue 341: Escaping xml in 423 Locked error responses. - - -1.6.9 (2013-04-11) ------------------- - -* Fixed: Assets in the browser plugins were not being served on windows - machines. - - -1.6.8 (2013-04-08) ------------------- - -* Fixed: vcardurl in database schema can now hold 255 characters instead of 80 - (which is often way to small). -* Fixed: The browser plugin potentially allowed people to open any arbitrary - file on windows servers. (CVE-2013-1939). - - -1.6.7 (2013-03-01) ------------------- - -* Change: No longer advertising support for 4.0 vcards. iOS and OS X address - book don't handle this well, and just advertising 3.0 support seems like the - most logical course of action. -* Added: ->setVerifyPeers to Sabre_DAV_Client (greatly resisting against it, - don't use this..). - - -1.6.6 (2013-01-19) ------------------- - -* Fixed: Backported a fix for broken XML serialization in error responses. - (Thanks @DeepDiver1975!) - - -1.6.5 (2012-10-04) ------------------- - -* Fixed: Workaround for line-ending bug OS X 10.8 addressbook has. -* Added: Ability to allow users to set SSL certificates for the Client class. - (Thanks schiesbn!). -* Fixed: Directory indexes with lots of nodes should be a lot faster. -* Fixed: Issue 235: E_NOTICE thrown when doing a propfind request with - Sabre_DAV_Client, and no valid properties are returned. -* Fixed: Issue with filtering on alarms in tasks. - - -1.6.4 (2012-08-02) ------------------- - -* Fixed: Issue 220: Calendar-query filters may fail when filtering on alarms, if - an overridden event has it's alarm removed. -* Fixed: Compatibility for OS/X 10.8 iCal in the IMipHandler. -* Fixed: Issue 222: beforeWriteContent shouldn't be called for lock requests. -* Fixed: Problem with POST requests to the outbox if mailto: was not lower - cased. -* Fixed: Yearly recurrence rule expansion on leap-days no behaves correctly. -* Fixed: Correctly checking if recurring, all-day events with no dtstart fall in - a timerange if the start of the time-range exceeds the start of the instance - of an event, but not the end. -* Fixed: All-day recurring events wouldn't match if an occurence ended exactly - on the start of a time-range. -* Fixed: HTTP basic auth did not correctly deal with passwords containing colons - on some servers. -* Fixed: Issue 228: DTEND is now non-inclusive for all-day events in the - calendar-query REPORT and free-busy calculations. - - -1.6.3 (2012-06-12) ------------------- - -* Added: It's now possible to specify in Sabre_DAV_Client which type of - authentication is to be used. -* Fixed: Issue 206: Sabre_DAV_Client PUT requests are fixed. -* Fixed: Issue 205: Parsing an iCalendar 0-second date interval. -* Fixed: Issue 112: Stronger validation of iCalendar objects. Now making sure - every iCalendar object only contains 1 component, and disallowing vcards, - forcing every component to have a UID. -* Fixed: Basic validation for vcards in the CardDAV plugin. -* Fixed: Issue 213: Workaround for an Evolution bug, that prevented it from - updating events. -* Fixed: Issue 211: A time-limit query on a non-relative alarm trigger in a - recurring event could result in an endless loop. -* Fixed: All uri fields are now a maximum of 200 characters. The Bynari outlook - plugin used much longer strings so this should improve compatibility. -* Fixed: Added a workaround for a bug in KDE 4.8.2 contact syncing. See - https://bugs.kde.org/show_bug.cgi?id=300047 -* Fixed: Issue 217: Sabre_DAV_Tree_FileSystem was pretty broken. - - -1.6.2 (2012-04-16) ------------------- - -* Fixed: Sabre_VObject_Node::$parent should have been public. -* Fixed: Recurrence rules of events are now taken into consideration when doing - time-range queries on alarms. -* Fixed: Added a workaround for the fact that php's DateInterval cannot parse - weeks and days at the same time. -* Added: Sabre_DAV_Server::$exposeVersion, allowing you to hide SabreDAV's - version number from various outputs. -* Fixed: DTSTART values would be incorrect when expanding events. -* Fixed: DTSTART and DTEND would be incorrect for expansion of WEEKLY BYDAY - recurrences. -* Fixed: Issue 203: A problem with overridden events hitting the exact date and - time of a subsequent event in the recurrence set. -* Fixed: There was a problem with recurrence rules, for example the 5th tuesday - of the month, if this day did not exist. -* Added: New HTTP status codes from draft-nottingham-http-new-status-04. - - -1.6.1 (2012-03-05) ------------------- - -* Added: createFile and put() can now return an ETag. -* Added: Sending back an ETag on for operations on CardDAV backends. This should - help with OS X 10.6 Addressbook compatibility. -* Fixed: Fixed a bug where an infinite loop could occur in the recurrence - iterator if the recurrence was YEARLY, with a BYMONTH rule, and either BYDAY - or BYMONTHDAY match the first day of the month. -* Fixed: Events that are excluded using EXDATE are still counted in the COUNT= - parameter in the RRULE property. -* Added: Support for time-range filters on VALARM components. -* Fixed: Correctly filtering all-day events. -* Fixed: Sending back correct mimetypes from the browser plugin (thanks - Jürgen). -* Fixed: Issue 195: Sabre_CardDAV pear package had an incorrect dependency. -* Fixed: Calendardata would be destroyed when performing a MOVE request. - - -1.6.0 (2012-02-22) ------------------- - -* BC Break: Now requires PHP 5.3 -* BC Break: Any node that implemented Sabre_DAVACL_IACL must now also implement - the getSupportedPrivilegeSet method. See website for details. -* BC Break: Moved functions from Sabre_CalDAV_XMLUtil to - Sabre_VObject_DateTimeParser. -* BC Break: The Sabre_DAVACL_IPrincipalCollection now has two new methods: - 'searchPrincipals' and 'updatePrincipal'. -* BC Break: Sabre_DAV_ILockable is removed and all related per-node locking - functionality. -* BC Break: Sabre_DAV_Exception_FileNotFound is now deprecated in favor of - Sabre_DAV_Exception_NotFound. The former will be removed in a later version. -* BC Break: Removed Sabre_CalDAV_ICalendarUtil, use Sabre_VObject instead. -* BC Break: Sabre_CalDAV_Server is now deprecated, check out the documentation - on how to setup a caldav server with just Sabre_DAV_Server. -* BC Break: Default Principals PDO backend now needs a new field in the - 'principals' table. See the website for details. -* Added: Ability to create new calendars and addressbooks from within the - browser plugin. -* Added: Browser plugin: icons for various nodes. -* Added: Support for FREEBUSY reports! -* Added: Support for creating principals with admin-level privileges. -* Added: Possibility to let server send out invitation emails on behalf of - CalDAV client, using Sabre_CalDAV_Schedule_IMip. -* Changed: beforeCreateFile event now passes data argument by reference. -* Changed: The 'propertyMap' property from Sabre_VObject_Reader, must now be - specified in Sabre_VObject_Property::$classMap. -* Added: Ability for plugins to tell the ACL plugin which principal plugins are - searchable. -* Added: [DAVACL] Per-node overriding of supported privileges. This allows for - custom privileges where needed. -* Added: [DAVACL] Public 'principalSearch' method on the DAVACL plugin, which - allows for easy searching for principals, based on their properties. -* Added: Sabre_VObject_Component::getComponents() to return a list of only - components and not properties. -* Added: An includes.php file in every sub-package (CalDAV, CardDAV, DAV, - DAVACL, HTTP, VObject) as an alternative to the autoloader. This often works - much faster. -* Added: Support for the 'Me card', which allows Addressbook.app users specify - which vcard is their own. -* Added: Support for updating principal properties in the DAVACL principal - backends. -* Changed: Major refactoring in the calendar-query REPORT code. Should make - things more flexible and correct. -* Changed: The calendar-proxy-[read|write] principals will now only appear in - the tree, if they actually exist in the Principal backend. This should reduce - some problems people have been having with this. -* Changed: Sabre_VObject_Element_* classes are now renamed to - Sabre_VObject_Property. Old classes are retained for backwards compatibility, - but this will be removed in the future. -* Added: Sabre_VObject_FreeBusyGenerator to generate free-busy reports based on - lists of events. -* Added: Sabre_VObject_RecurrenceIterator to find all the dates and times for - recurring events. -* Fixed: Issue 97: Correctly handling RRULE for the calendar-query REPORT. -* Fixed: Issue 154: Encoding of VObject parameters with no value was incorrect. -* Added: Support for {DAV:}acl-restrictions property from RFC3744. -* Added: The contentlength for calendar objects can now be supplied by a CalDAV - backend, allowing for more optimizations. -* Fixed: Much faster implementation of Sabre_DAV_URLUtil::encodePath. -* Fixed: {DAV:}getcontentlength may now be not specified. -* Fixed: Issue 66: Using rawurldecode instead of urldecode to decode paths from - clients. This means that + will now be treated as a literal rather than a - space, and this should improve compatibility with the Windows built-in client. -* Added: Sabre_DAV_Exception_PaymentRequired exception, to emit HTTP 402 status - codes. -* Added: Some mysql unique constraints to example files. -* Fixed: Correctly formatting HTTP dates. -* Fixed: Issue 94: Sending back Last-Modified header for 304 responses. -* Added: Sabre_VObject_Component_VEvent, Sabre_VObject_Component_VJournal, - Sabre_VObject_Component_VTodo and Sabre_VObject_Component_VCalendar. -* Changed: Properties are now also automatically mapped to their appropriate - classes, if they are created using the add() or __set() methods. -* Changed: Cloning VObject objects now clones the entire tree, rather than just - the default shallow copy. -* Added: Support for recurrence expansion in the CALDAV:calendar-multiget and - CALDAV:calendar-query REPORTS. -* Changed: CalDAV PDO backend now sorts calendars based on the internal - 'calendarorder' field. -* Added: Issue 181: Carddav backends may no optionally not supply the carddata - in getCards, if etag and size are specified. This may speed up certain - requests. -* Added: More arguments to beforeWriteContent and beforeCreateFile (see - WritingPlugins wiki document). -* Added: Hook for iCalendar validation. This allows us to validate iCalendar - objects when they're uploaded. At the moment we're just validating syntax. -* Added: VObject now support Windows Timezone names correctly (thanks mrpace2). -* Added: If a timezonename could not be detected, we fall back on the default - PHP timezone. -* Added: Now a Composer package (thanks willdurand). -* Fixed: Support for \N as a newline character in the VObject reader. -* Added: afterWriteContent, afterCreateFile and afterUnbind events. -* Added: Postgresql example files. Not part of the unittests though, so use at - your own risk. -* Fixed: Issue 182: Removed backticks from sql queries, so it will work with - Postgres. - - -1.5.9 (2012-04-16) ------------------- - -* Fixed: Issue with parsing timezone identifiers that were surrounded by quotes. - (Fixes emClient compatibility). - - -1.5.8 (2012-02-22) ------------------- - -* Fixed: Issue 95: Another timezone parsing issue, this time in calendar-query. - - -1.5.7 (2012-02-19) ------------------- - -* Fixed: VObject properties are now always encoded before components. -* Fixed: Sabre_DAVACL had issues with multiple levels of privilege aggregration. -* Changed: Added 'GuessContentType' plugin to fileserver.php example. -* Fixed: The Browser plugin will now trigger the correct events when creating - files. -* Fixed: The ICSExportPlugin now considers ACL's. -* Added: Made it optional to supply carddata from an Addressbook backend when - requesting getCards. This can make some operations much faster, and could - result in much lower memory use. -* Fixed: Issue 187: Sabre_DAV_UUIDUtil was missing from includes file. -* Fixed: Issue 191: beforeUnlock was triggered twice. - - -1.5.6 (2012-01-07) ------------------- - -* Fixed: Issue 174: VObject could break UTF-8 characters. -* Fixed: pear package installation issues. - - -1.5.5 (2011-12-16) ------------------- - -* Fixed: CalDAV time-range filter workaround for recurring events. -* Fixed: Bug in Sabre_DAV_Locks_Backend_File that didn't allow multiple files to - be locked at the same time. - - -1.5.4 (2011-10-28) ------------------- - -* Fixed: GuessContentType plugin now supports mixed case file extensions. -* Fixed: DATE-TIME encoding was wrong in VObject. (we used 'DATETIME'). -* Changed: Sending back HTTP 204 after a PUT request on an existing resource - instead of HTTP 200. This should fix Evolution CardDAV client compatibility. -* Fixed: Issue 95: Parsing X-LIC-LOCATION if it's available. -* Added: All VObject elements now have a reference to their parent node. - - -1.5.3 (2011-09-28) ------------------- - -* Fixed: Sabre_DAV_Collection was missing from the includes file. -* Fixed: Issue 152. iOS 1.4.2 apparantly requires HTTP/1.1 200 OK to be in - uppercase. -* Fixed: Issue 153: Support for files with mixed newline styles in - Sabre_VObject. -* Fixed: Issue 159: Automatically converting any vcard and icalendardata to - UTF-8. -* Added: Sabre_DAV_SimpleFile class for easy static file creation. -* Added: Issue 158: Support for the CARDDAV:supported-address-data property. - - -1.5.2 (2011-09-21) ------------------- - -* Fixed: carddata and calendardata MySQL fields are now of type 'mediumblob'. - 'TEXT' was too small sometimes to hold all the data. -* Fixed: {DAV:}supported-report-set is now correctly reporting the reports for - IAddressBook. -* Added: Sabre_VObject_Property::add() to add duplicate parameters to - properties. -* Added: Issue 151: Sabre_CalDAV_ICalendar and Sabre_CalDAV_ICalendarObject - interfaces. -* Fixed: Issue 140: Not returning 201 Created if an event cancelled the creation - of a file. -* Fixed: Issue 150: Faster URLUtil::encodePath() implementation. -* Fixed: Issue 144: Browser plugin could interfere with - TemporaryFileFilterPlugin if it was loaded first. -* Added: It's not possible to specify more 'alternate uris' in principal - backends. - - -1.5.1 (2011-08-24) ------------------- - -* Fixed: Issue 137. Hiding action interface in HTML browser for non-collections. -* Fixed: addressbook-query is now correctly returned from the - {DAV:}supported-report-set property. -* Fixed: Issue 142: Bugs in groupwareserver.php example. -* Fixed: Issue 139: Rejecting PUT requests with Content-Range. - - -1.5.0 (2011-08-12) ------------------- - -* Added: CardDAV support. -* Added: An experimental WebDAV client. -* Added: MIME-Directory grouping support in the VObject library. This is very - useful for people attempting to parse vcards. -* BC Break: Adding parameters with the VObject libraries now overwrites the - previous parameter, rather than just add it. This makes more sense for 99% of - the cases. -* BC Break: lib/Sabre.autoload.php is now removed in favor of - lib/Sabre/autoload.php. -* Deprecated: Sabre_DAV_Directory is now deprecated and will be removed in a - future version. Use Sabre_DAV_Collection instead. -* Deprecated: Sabre_DAV_SimpleDirectory is now deprecated and will be removed in - a future version. Use Sabre_DAV_SimpleCollection instead. -* Fixed: Problem with overriding tablenames for the CalDAV backend. -* Added: Clark-notation parser to XML utility. -* Added: unset() support to VObject components. -* Fixed: Refactored CalDAV property fetching to be faster and simpler. -* Added: Central string-matcher for CalDAV and CardDAV plugins. -* Added: i;unicode-casemap support -* Fixed: VObject bug: wouldn't parse parameters if they weren't specified in - uppercase. -* Fixed: VObject bug: Parameters now behave more like Properties. -* Fixed: VObject bug: Parameters with no value are now correctly parsed. -* Changed: If calendars don't specify which components they allow, 'all' - components are assumed (e.g.: VEVENT, VTODO, VJOURNAL). -* Changed: Browser plugin now uses POST variable 'sabreAction' instead of - 'action' to reduce the chance of collisions. - - -1.4.4 (2011-07-07) ------------------- - -* Fixed: Issue 131: Custom CalDAV backends could break in certain cases. -* Added: The option to override the default tablename all PDO backends use. - (Issue 60). -* Fixed: Issue 124: 'File' authentication backend now takes realm into - consideration. -* Fixed: Sabre_DAV_Property_HrefList now properly deserializes. This allows - users to update the {DAV:}group-member-set property. -* Added: Helper functions for DateTime-values in Sabre_VObject package. -* Added: VObject library can now automatically map iCalendar properties to - custom classes. - - -1.4.3 (2011-04-25) ------------------- - -* Fixed: Issue 123: Added workaround for Windows 7 UNLOCK bug. -* Fixed: datatype of lastmodified field in mysql.calendars.sql. Please change - the DATETIME field to an INT to ensure this field will work correctly. -* Change: Sabre_DAV_Property_Principal is now renamed to - Sabre_DAVACL_Property_Principal. -* Added: API level support for ACL HTTP method. -* Fixed: Bug in serializing {DAV:}acl property. -* Added: deserializer for {DAV:}resourcetype property. -* Added: deserializer for {DAV:}acl property. -* Added: deserializer for {DAV:}principal property. - - -1.4.2-beta (2011-04-01) ------------------------ - -* Added: It's not possible to disable listing of nodes that are denied read - access by ACL. -* Fixed: Changed a few properties in CalDAV classes from private to protected. -* Fixed: Issue 119: Terrible things could happen when relying on guessBaseUri, - the server was running on the root of the domain and a user tried to access a - file ending in .php. This is a slight BC break. -* Fixed: Issue 118: Lock tokens in If headers without a uri should be treated as - the request uri, not 'all relevant uri's. -* Fixed: Issue 120: PDO backend was incorrectly fetching too much locks in cases - where there were similar named locked files in a directory. - - -1.4.1-beta (2011-02-26) ------------------------ - -* Fixed: Sabre_DAV_Locks_Backend_PDO returned too many locks. -* Fixed: Sabre_HTTP_Request::getHeader didn't return Content-Type when running - on apache, so a few workarounds were added. -* Change: Slightly changed CalDAV Backend API's, to allow for heavy - optimizations. This is non-bc breaking. - - -1.4.0-beta (2011-02-12) ------------------------ - -* Added: Partly RFC3744 ACL support. -* Added: Calendar-delegation (caldav-proxy) support. -* BC break: In order to fix Issue 99, a new argument had to be added to - Sabre_DAV_Locks_Backend_*::getLocks classes. Consult the classes for details. -* Deprecated: Sabre_DAV_Locks_Backend_FS is now deprecated and will be removed - in a later version. Use PDO or the new File class instead. -* Deprecated: The Sabre_CalDAV_ICalendarUtil class is now marked deprecated, and - will be removed in a future version. Please use Sabre_VObject instead. -* Removed: All principal-related functionality has been removed from the - Sabre_DAV_Auth_Plugin, and moved to the Sabre_DAVACL_Plugin. -* Added: VObject library, for easy vcard/icalendar parsing using a natural - interface. -* Added: Ability to automatically generate full .ics feeds off calendars. To - use: Add the Sabre_CalDAV_ICSExportPlugin, and add ?export to your calendar - url. -* Added: Plugins can now specify a pluginname, for easy access using - Sabre_DAV_Server::getPlugin(). -* Added: beforeGetProperties event. -* Added: updateProperties event. -* Added: Principal listings and calendar-access can now be done privately, - disallowing users from accessing or modifying other users' data. -* Added: You can now pass arrays to the Sabre_DAV_Server constructor. If it's an - array with node-objects, a Root collection will automatically be created, and - the nodes are used as top-level children. -* Added: The principal base uri is now customizable. It used to be hardcoded to - 'principals/[user]'. -* Added: getSupportedReportSet method in ServerPlugin class. This allows you to - easily specify which reports you're implementing. -* Added: A '..' link to the HTML browser. -* Fixed: Issue 99: Locks on child elements were ignored when their parent nodes - were deleted. -* Fixed: Issue 90: lockdiscovery property and LOCK response now include a - {DAV}lockroot element. -* Fixed: Issue 96: support for 'default' collation in CalDAV text-match filters. -* Fixed: Issue 102: Ensuring that copy and move with identical source and - destination uri's fails. -* Fixed: Issue 105: Supporting MKCALENDAR with no body. -* Fixed: Issue 109: Small fixes in Sabre_HTTP_Util. -* Fixed: Issue 111: Properly catching the ownername in a lock (if it's a string) -* Fixed: Sabre_DAV_ObjectTree::nodeExist always returned false for the root - node. -* Added: Global way to easily supply new resourcetypes for certain node classes. -* Fixed: Issue 59: Allowing the user to override the authentication realm in - Sabre_CalDAV_Server. -* Update: Issue 97: Looser time-range checking if there's a recurrence rule in - an event. This fixes 'missing recurring events'. - - -1.3.0 (2010-10-14) ------------------- - -* Added: childExists method to Sabre_DAV_ICollection. This is an api break, so - if you implement Sabre_DAV_ICollection directly, add the method. -* Changed: Almost all HTTP method implementations now take a uri argument, - including events. This allows for internal rerouting of certain calls. If you - have custom plugins, make sure they use this argument. If they don't, they - will likely still work, but it might get in the way of future changes. -* Changed: All getETag methods MUST now surround the etag with double-quotes. - This was a mistake made in all previous SabreDAV versions. If you don't do - this, any If-Match, If-None-Match and If: headers using Etags will work - incorrectly. (Issue 85). -* Added: Sabre_DAV_Auth_Backend_AbstractBasic class, which can be used to easily - implement basic authentication. -* Removed: Sabre_DAV_PermissionDenied class. Use Sabre_DAV_Forbidden instead. -* Removed: Sabre_DAV_IDirectory interface, use Sabre_DAV_ICollection instead. -* Added: Browser plugin now uses {DAV:}displayname if this property is - available. -* Added: Cache layer in the ObjectTree. -* Added: Tree classes now have a delete and getChildren method. -* Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if the - date is an exact match. -* Fixed: Support for multiple ETags in If-Match and If-None-Match headers. -* Fixed: Improved baseUrl handling. -* Fixed: Issue 67: Non-seekable stream support in ::put()/::get(). -* Fixed: Issue 65: Invalid dates are now ignored. -* Updated: Refactoring in Sabre_CalDAV to make everything a bit more ledgable. -* Fixed: Issue 88, Issue 89: Fixed compatibility for running SabreDAV on - Windows. -* Fixed: Issue 86: Fixed Content-Range top-boundary from 'file size' to 'file - size'-1. - - -1.2.5 (2010-08-18) ------------------- - -* Fixed: Issue 73: guessBaseUrl fails for some servers. -* Fixed: Issue 67: SabreDAV works better with non-seekable streams. -* Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if - the date is an exact match. - - -1.2.4 (2010-07-13) ------------------- - -* Fixed: Issue 62: Guessing baseUrl fails when url contains a query-string. -* Added: Apache configuration sample for CGI/FastCGI setups. -* Fixed: Issue 64: Only returning calendar-data when it was actually requested. - - -1.2.3 (2010-06-26) ------------------- - -* Fixed: Issue 57: Supporting quotes around etags in If-Match and If-None-Match - - -1.2.2 (2010-06-21) ------------------- - -* Updated: SabreDAV now attempts to guess the BaseURI if it's not set. -* Updated: Better compatibility with BitKinex -* Fixed: Issue 56: Incorrect behaviour for If-None-Match headers and GET - requests. -* Fixed: Issue with certain encoded paths in Browser Plugin. - - -1.2.1 (2010-06-07) ------------------- - -* Fixed: Issue 50, patch by Mattijs Hoitink. -* Fixed: Issue 51, Adding windows 7 lockfiles to TemporaryFileFilter. -* Fixed: Issue 38, Allowing custom filters to be added to TemporaryFileFilter. -* Fixed: Issue 53, ETags in the If: header were always failing. This behaviour - is now corrected. -* Added: Apache Authentication backend, in case authentication through .htaccess - is desired. -* Updated: Small improvements to example files. - - -1.2.0 (2010-05-24) ------------------- - -* Fixed: Browser plugin now displays international characters. -* Changed: More properties in CalDAV classes are now protected instead of - private. - - -1.2.0beta3 (2010-05-14) ------------------------ - -* Fixed: Custom properties were not properly sent back for allprops requests. -* Fixed: Issue 49, incorrect parsing of PROPPATCH, affecting Office 2007. -* Changed: Removed CalDAV items from includes.php, and added a few missing ones. - - -1.2.0beta2 (2010-05-04) ------------------------ - -* Fixed: Issue 46: Fatal error for some non-existent nodes. -* Updated: some example sql to include email address. -* Added: 208 and 508 statuscodes from RFC5842. -* Added: Apache2 configuration examples - - -1.2.0beta1 (2010-04-28) ------------------------ - -* Fixed: redundant namespace declaration in resourcetypes. -* Fixed: 2 locking bugs triggered by litmus when no Sabre_DAV_ILockable - interface is used. -* Changed: using http://sabredav.org/ns for all custom xml properties. -* Added: email address property to principals. -* Updated: CalendarObject validation. - - -1.2.0alpha4 (2010-04-24) ------------------------- - -* Added: Support for If-Range, If-Match, If-None-Match, If-Modified-Since, - If-Unmodified-Since. -* Changed: Brand new build system. Functionality is split up between Sabre, - Sabre_HTTP, Sabre_DAV and Sabre_CalDAV packages. In addition to that a new - non-pear package will be created with all this functionality combined. -* Changed: Autoloader moved to Sabre/autoload.php. -* Changed: The Allow: header is now more accurate, with appropriate HTTP methods - per uri. -* Changed: Now throwing back Sabre_DAV_Exception_MethodNotAllowed on a few - places where Sabre_DAV_Exception_NotImplemented was used. - - -1.2.0alpha3 (2010-04-20) ------------------------- - -* Update: Complete rewrite of property updating. Now easier to use and atomic. -* Fixed: Issue 16, automatically adding trailing / to baseUri. -* Added: text/plain is used for .txt files in GuessContentType plugin. -* Added: support for principal-property-search and principal-search-property-set - reports. -* Added: Issue 31: Hiding exception information by default. Can be turned on - with the Sabre_DAV_Server::$debugExceptions property. - - -1.2.0alpha2 (2010-04-08) ------------------------- - -* Added: Calendars are now private and can only be read by the owner. -* Fixed: double namespace declaration in multistatus responses. -* Added: MySQL database dumps. MySQL is now also supported next to SQLite. -* Added: expand-properties REPORT from RFC 3253. -* Added: Sabre_DAV_Property_IHref interface for properties exposing urls. -* Added: Issue 25: Throwing error on broken Finder behaviour. -* Changed: Authentication backend is now aware of current user. - - -1.2.0alpha1 (2010-03-31) ------------------------- - -* Fixed: Issue 26: Workaround for broken GVFS behaviour with encoded special - characters. -* Fixed: Issue 34: Incorrect Lock-Token response header for LOCK. Fixes Office - 2010 compatibility. -* Added: Issue 35: SabreDAV version to header to OPTIONS response to ease - debugging. -* Fixed: Issue 36: Incorrect variable name, throwing error in some requests. -* Fixed: Issue 37: Incorrect smultron regex in temporary filefilter. -* Fixed: Issue 33: Converting ISO-8859-1 characters to UTF-8. -* Fixed: Issue 39 & Issue 40: Basename fails on non-utf-8 locales. -* Added: More unittests. -* Added: SabreDAV version to all error responses. -* Added: URLUtil class for decoding urls. -* Changed: Now using pear.sabredav.org pear channel. -* Changed: Sabre_DAV_Server::getCopyAndMoveInfo is now a public method. - - -1.1.2-alpha (2010-03-18) ------------------------- - -* Added: RFC5397 - current-user-principal support. -* Fixed: Issue 27: encoding entities in property responses. -* Added: naturalselection script now allows the user to specify a 'minimum - number of bytes' for deletion. This should reduce load due to less crawling -* Added: Full support for the calendar-query report. -* Added: More unittests. -* Added: Support for complex property deserialization through the static - ::unserialize() method. -* Added: Support for modifying calendar-component-set -* Fixed: Issue 29: Added TIMEOUT_INFINITE constant - - -1.1.1-alpha (2010-03-11) ------------------------- - -* Added: RFC5689 - Extended MKCOL support. -* Fixed: Evolution support for CalDAV. -* Fixed: PDO-locks backend was pretty much completely broken. This is 100% - unittested now. -* Added: support for ctags. -* Fixed: Comma's between HTTP methods in 'Allow' method. -* Changed: default argument for Sabre_DAV_Locks_Backend_FS. This means a - datadirectory must always be specified from now on. -* Changed: Moved Sabre_DAV_Server::parseProps to - Sabre_DAV_XMLUtil::parseProperties. -* Changed: Sabre_DAV_IDirectory is now Sabre_DAV_ICollection. -* Changed: Sabre_DAV_Exception_PermissionDenied is now - Sabre_DAV_Exception_Forbidden. -* Changed: Sabre_CalDAV_ICalendarCollection is removed. -* Added: Sabre_DAV_IExtendedCollection. -* Added: Many more unittests. -* Added: support for calendar-timezone property. - - -1.1.0-alpha (2010-03-01) ------------------------- - -* Note: This version is forked from version 1.0.5, so release dates may be out - of order. -* Added: CalDAV - RFC 4791 -* Removed: Sabre_PHP_Exception. PHP has a built-in ErrorException for this. -* Added: PDO authentication backend. -* Added: Example sql for auth, caldav, locks for sqlite. -* Added: Sabre_DAV_Browser_GuessContentType plugin -* Changed: Authentication plugin refactored, making it possible to implement - non-digest authentication. -* Fixed: Better error display in browser plugin. -* Added: Support for {DAV:}supported-report-set -* Added: XML utility class with helper functions for the WebDAV protocol. -* Added: Tons of unittests -* Added: PrincipalCollection and Principal classes -* Added: Sabre_DAV_Server::getProperties for easy property retrieval -* Changed: {DAV:}resourceType defaults to 0 -* Changed: Any non-null resourceType now gets a / appended to the href value. - Before this was just for {DAV:}collection's, but this is now also the case for - for example {DAV:}principal. -* Changed: The Href property class can now optionally create non-relative uri's. -* Changed: Sabre_HTTP_Response now returns false if headers are already sent and - header-methods are called. -* Fixed: Issue 19: HEAD requests on Collections -* Fixed: Issue 21: Typo in Sabre_DAV_Property_Response -* Fixed: Issue 18: Doesn't work with Evolution Contacts - - -1.0.15 (2010-05-28) -------------------- - -* Added: Issue 31: Hiding exception information by default. Can be turned on - with the Sabre_DAV_Server::$debugExceptions property. -* Added: Moved autoload from lib/ to lib/Sabre/autoload.php. This is also the - case in the upcoming 1.2.0, so it will improve future compatibility. - - -1.0.14 (2010-04-15) -------------------- - -* Fixed: double namespace declaration in multistatus responses. - - -1.0.13 (2010-03-30) -------------------- - -* Fixed: Issue 40: Last references to basename/dirname - - -1.0.12 (2010-03-30) -------------------- - -* Fixed: Issue 37: Incorrect smultron regex in temporary filefilter. -* Fixed: Issue 26: Workaround for broken GVFS behaviour with encoded special - characters. -* Fixed: Issue 33: Converting ISO-8859-1 characters to UTF-8. -* Fixed: Issue 39: Basename fails on non-utf-8 locales. -* Added: More unittests. -* Added: SabreDAV version to all error responses. -* Added: URLUtil class for decoding urls. -* Updated: Now using pear.sabredav.org pear channel. - - -1.0.11 (2010-03-23) -------------------- - -* Non-public release. This release is identical to 1.0.10, but it is used to - test releasing packages to pear.sabredav.org. - - -1.0.10 (2010-03-22) -------------------- - -* Fixed: Issue 34: Invalid Lock-Token header response. -* Added: Issue 35: Addign SabreDAV version to HTTP OPTIONS responses. - - -1.0.9 (2010-03-19) ------------------- - -* Fixed: Issue 27: Entities not being encoded in PROPFIND responses. -* Fixed: Issue 29: Added missing TIMEOUT_INFINITE constant. - - -1.0.8 (2010-03-03) ------------------- - -* Fixed: Issue 21: typos causing errors -* Fixed: Issue 23: Comma's between methods in Allow header. -* Added: Sabre_DAV_ICollection interface, to aid in future compatibility. -* Added: Sabre_DAV_Exception_Forbidden exception. This will replace - Sabre_DAV_Exception_PermissionDenied in the future, and can already be used to - ensure future compatibility. - - -1.0.7 (2010-02-24) ------------------- - -* Fixed: Issue 19 regression for MS Office - - -1.0.6 (2010-02-23) ------------------- - -* Fixed: Issue 19: HEAD requests on Collections - - -1.0.5 (2010-01-22) ------------------- - -* Fixed: Fatal error when a malformed url was used for unlocking, in conjuction - with Sabre.autoload.php due to a incorrect filename. -* Fixed: Improved unittests and build system - - -1.0.4 (2010-01-11) ------------------- - -* Fixed: needed 2 different releases. One for googlecode and one for pearfarm. - This is to retain the old method to install SabreDAV until pearfarm becomes - the standard installation method. - - -1.0.3 (2010-01-11) ------------------- - -* Added: RFC4709 support (davmount) -* Added: 6 unittests -* Added: naturalselection. A tool to keep cache directories below a specified - theshold. -* Changed: Now using pearfarm.org channel server. - - -1.0.1 (2009-12-22) ------------------- - -* Fixed: Issue 15: typos in examples -* Fixed: Minor pear installation issues - - -1.0.0 (2009-11-02) ------------------- - -* Added: SimpleDirectory class. This class allows creating static directory - structures with ease. -* Changed: Custom complex properties and exceptions now get an instance of - Sabre_DAV_Server as their first argument in serialize() -* Changed: Href complex property now prepends server's baseUri -* Changed: delete before an overwriting copy/move is now handles by server class - instead of tree classes -* Changed: events must now explicitly return false to stop execution. Before, - execution would be stopped by anything loosely evaluating to false. -* Changed: the getPropertiesForPath method now takes a different set of - arguments, and returns a different response. This allows plugin developers to - return statuses for properties other than 200 and 404. The hrefs are now also - always calculated relative to the baseUri, and not the uri of the request. -* Changed: generatePropFindResponse is renamed to generateMultiStatus, and now - takes a list of properties similar to the response of getPropertiesForPath. - This was also needed to improve flexibility for plugin development. -* Changed: Auth plugins are no longer included. They were not yet stable - quality, so they will probably be reintroduced in a later version. -* Changed: PROPPATCH also used generateMultiStatus now. -* Removed: unknownProperties event. This is replaced by the afterGetProperties - event, which should provide more flexibility. -* Fixed: Only calling getSize() on IFile instances in httpHead() -* Added: beforeBind event. This is invoked upon file or directory creation -* Added: beforeWriteContent event, this is invoked by PUT and LOCK on an - existing resource. -* Added: beforeUnbind event. This is invoked right before deletion of any - resource. -* Added: afterGetProperties event. This event can be used to make modifications - to property responses. -* Added: beforeLock and beforeUnlock events. -* Added: afterBind event. -* Fixed: Copy and Move could fail in the root directory. This is now fixed. -* Added: Plugins can now be retrieved by their classname. This is useful for - inter-plugin communication. -* Added: The Auth backend can now return usernames and user-id's. -* Added: The Auth backend got a getUsers method -* Added: Sabre_DAV_FSExt_Directory now returns quota info - - -0.12.1-beta (2009-09-11) ------------------------- - -* Fixed: UNLOCK bug. Unlock didn't work at all - - -0.12-beta (2009-09-10) ----------------------- - -* Updated: Browser plugin now shows multiple {DAV:}resourcetype values if - available. -* Added: Experimental PDO backend for Locks Manager -* Fixed: Sending Content-Length: 0 for every empty response. This improves NGinx - compatibility. -* Fixed: Last modification time is reported in UTC timezone. This improves - Finder compatibility. - - -0.11-beta (2009-08-11) ----------------------- - -* Updated: Now in Beta -* Updated: Pear package no longer includes docs/ directory. These just contained - rfc's, which are publicly available. This reduces the package from ~800k to - ~60k -* Added: generatePropfindResponse now takes a baseUri argument -* Added: ResourceType property can now contain multiple resourcetypes. -* Fixed: Issue 13. - - -0.10-alpha (2009-08-03) ------------------------ - -* Added: Plugin to automatically map GET requests to non-files to PROPFIND - (Sabre_DAV_Browser_MapGetToPropFind). This should allow easier debugging of - complicated WebDAV setups. -* Added: Sabre_DAV_Property_Href class. For future use. -* Added: Ability to choose to use auth-int, auth or both for HTTP Digest - authentication. (Issue 11) -* Changed: Made more methods in Sabre_DAV_Server public. -* Fixed: TemporaryFileFilter plugin now intercepts HTTP LOCK requests to - non-existent files. (Issue 12) -* Added: Central list of defined xml namespace prefixes. This can reduce - Bandwidth and legibility for xml bodies with user-defined namespaces. -* Added: now a PEAR-compatible package again, thanks to Michael Gauthier -* Changed: moved default copy and move logic from ObjectTree to Tree class - -0.9a-alpha (2009-07-21) ----------------------- - -* Fixed: Broken release - -0.9-alpha (2009-07-21) ----------------------- - -* Changed: Major refactoring, removed most of the logic from the Tree objects. - The Server class now directly works with the INode, IFile and IDirectory - objects. If you created your own Tree objects, this will most likely break in - this release. -* Changed: Moved all the Locking logic from the Tree and Server classes into a - separate plugin. -* Changed: TemporaryFileFilter is now a plugin. -* Added: Comes with an autoloader script. This can be used instead of the - includer script, and is preferred by some people. -* Added: AWS Authentication class. -* Added: simpleserversetup.py script. This will quickly get a fileserver up and - running. -* Added: When subscribing to events, it is now possible to supply a priority. - This is for example needed to ensure that the Authentication Plugin is used - before any other Plugin. -* Added: 22 new tests. -* Added: Users-manager plugin for .htdigest files. Experimental and subject to - change. -* Added: RFC 2324 HTTP 418 status code -* Fixed: Exclusive locks could in some cases be picked up as shared locks -* Fixed: Digest auth for non-apache servers had a bug (still not actually tested - this well). - - -0.8-alpha (2009-05-30) ----------------------- - -* Changed: Renamed all exceptions! This is a compatibility break. Every - Exception now follows Sabre_DAV_Exception_FileNotFound convention instead of - Sabre_DAV_FileNotFoundException. -* Added: Browser plugin now allows uploading and creating directories straight - from the browser. -* Added: 12 more unittests -* Fixed: Locking bug, which became prevalent on Windows Vista. -* Fixed: Netdrive support -* Fixed: TemporaryFileFilter filtered out too many files. Fixed some of the - regexes. -* Fixed: Added README and ChangeLog to package - - -0.7-alpha (2009-03-29) ----------------------- - -* Added: System to return complex properties from PROPFIND. -* Added: support for {DAV:}supportedlock. -* Added: support for {DAV:}lockdiscovery. -* Added: 6 new tests. -* Added: New plugin system. -* Added: Simple HTML directory plugin, for browser access. -* Added: Server class now sends back standard pre-condition error xml bodies. - This was new since RFC4918. -* Added: Sabre_DAV_Tree_Aggregrate, which can 'host' multiple Tree objects into - one. -* Added: simple basis for HTTP REPORT method. This method is not used yet, but - can be used by plugins to add reports. -* Changed: ->getSize is only called for files, no longer for collections. r303 -* Changed: Sabre_DAV_FilterTree is now Sabre_DAV_Tree_Filter -* Changed: Sabre_DAV_TemporaryFileFilter is now called - Sabre_DAV_Tree_TemporaryFileFilter. -* Changed: removed functions (get(/set)HTTPRequest(/Response)) from Server - class, and using a public property instead. -* Fixed: bug related to parsing proppatch and propfind requests. Didn't show up - in most clients, but it needed fixing regardless. (r255) -* Fixed: auth-int is now properly supported within HTTP Digest. -* Fixed: Using application/xml for a mimetype vs. text/xml as per RFC4918 sec - 8.2. -* Fixed: TemporaryFileFilter now lets through GET's if they actually exist on - the backend. (r274) -* FIxed: Some methods didn't get passed through in the FilterTree (r283). -* Fixed: LockManager is now slightly more complex, Tree classes slightly less. - (r287) - - -0.6-alpha (2009-02-16) ----------------------- - -* Added: Now uses streams for files, instead of strings. This means it won't - require to hold entire files in memory, which can be an issue if you're - dealing with big files. Note that this breaks compatibility for put() and - createFile methods. -* Added: HTTP Digest Authentication helper class. -* Added: Support for HTTP Range header -* Added: Support for ETags within If: headers -* Added: The API can now return ETags and override the default Content-Type -* Added: starting with basic framework for unittesting, using PHPUnit. -* Added: 49 unittests. -* Added: Abstraction for the HTTP request. -* Updated: Using Clark Notation for tags in properties. This means tags are - serialized as {namespace}tagName instead of namespace#tagName -* Fixed: HTTP_BasicAuth class now works as expected. -* Fixed: DAV_Server uses / for a default baseUrl. -* Fixed: Last modification date is no longer ignored in PROPFIND. -* Fixed: PROPFIND now sends back information about the requestUri even when - "Depth: 1" is specified. - - -0.5-alpha (2009-01-14) ----------------------- - -* Added: Added a very simple example for implementing a mapping to PHP file - streams. This should allow easy implementation of for example a WebDAV to FTP - proxy. -* Added: HTTP Basic Authentication helper class. -* Added: Sabre_HTTP_Response class. This centralizes HTTP operations and will be - a start towards the creating of a testing framework. -* Updated: Backwards compatibility break: all require_once() statements are - removed from all the files. It is now recommended to use autoloading of - classes, or just including lib/Sabre.includes.php. This fix was made to allow - easier integration into applications not using this standard inclusion model. -* Updated: Better in-file documentation. -* Updated: Sabre_DAV_Tree can now work with Sabre_DAV_LockManager. -* Updated: Fixes a shared-lock bug. -* Updated: Removed ?> from the bottom of each php file. -* Updated: Split up some operations from Sabre_DAV_Server to - Sabre_HTTP_Response. -* Fixed: examples are now actually included in the pear package. - - -0.4-alpha (2008-11-05) ----------------------- - -* Passes all litmus tests! -* Added: more examples -* Added: Custom property support -* Added: Shared lock support -* Added: Depth support to locks -* Added: Locking on unmapped urls (non-existent nodes) -* Fixed: Advertising as WebDAV class 3 support - - -0.3-alpha (2008-06-29) ----------------------- - -* Fully working in MS Windows clients. -* Added: temporary file filter: support for smultron files. -* Added: Phing build scripts -* Added: PEAR package -* Fixed: MOVE bug identified using finder. -* Fixed: Using gzuncompress instead of gzdecode in the temporary file filter. - This seems more common. - - -0.2-alpha (2008-05-27) ----------------------- - -* Somewhat working in Windows clients -* Added: Working PROPPATCH method (doesn't support custom properties yet) -* Added: Temporary filename handling system -* Added: Sabre_DAV_IQuota to return quota information -* Added: PROPFIND now reads the request body and only supplies the requested - properties - - -0.1-alpha (2008-04-04) ----------------------- - -* First release! -* Passes litmus: basic, http and copymove test. -* Fully working in Finder and DavFS2. - -Project started: 2007-12-13 - -[vobj]: http://sabre.io/vobject/ -[evnt]: http://sabre.io/event/ -[http]: http://sabre.io/http/ -[uri]: http://sabre.io/uri/ -[xml]: http://sabre.io/xml/ -[mi20]: http://sabre.io/dav/upgrade/1.8-to-2.0/ -[rfc6638]: http://tools.ietf.org/html/rfc6638 "CalDAV Scheduling" -[rfc7240]: http://tools.ietf.org/html/rfc7240 -[calendar-availability]: https://tools.ietf.org/html/draft-daboo-calendar-availability-05 diff --git a/vendor/LICENSE b/vendor/LICENSE deleted file mode 100644 index fd3539e33..000000000 --- a/vendor/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (C) 2007-2016 fruux GmbH (https://fruux.com/). - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of SabreDAV nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/README.md b/vendor/README.md deleted file mode 100644 index 8edcd4073..000000000 --- a/vendor/README.md +++ /dev/null @@ -1,36 +0,0 @@ -![sabre's logo](http://sabre.io/img/logo.png) sabre/dav -======================================================= - -Introduction ------------- - -sabre/dav is the most popular WebDAV framework for PHP. Use it to create WebDAV, CalDAV and CardDAV servers. - -Full documentation can be found on the website: - -http://sabre.io/ - -Build status ------------- - -| branch | status | minimum PHP version | -| ------------ | ------ | ------------------- | -| master | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=master)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 | -| 3.1 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=3.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 | -| 3.0 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=3.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | -| 2.1 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=2.1)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | -| 2.0 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=2.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | -| 1.8 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.8)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | -| 1.7 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.7)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | -| 1.6 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.6)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | - -Documentation -------------- - -* [Introduction](http://sabre.io/dav/). -* [Installation](http://sabre.io/dav/install/). - -Made at fruux -------------- - -SabreDAV is being developed by [fruux](https://fruux.com/). Drop us a line for commercial services or enterprise support. diff --git a/vendor/autoload.php b/vendor/autoload.php index 3ba315118..bb2d0206c 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261::getLoader(); +return ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4::getLoader(); diff --git a/vendor/bin/generate_vcards b/vendor/bin/generate_vcards deleted file mode 100755 index 4663c3c16..000000000 --- a/vendor/bin/generate_vcards +++ /dev/null @@ -1,241 +0,0 @@ -#!/usr/bin/env php -<?php - -namespace Sabre\VObject; - -// This sucks.. we have to try to find the composer autoloader. But chances -// are, we can't find it this way. So we'll do our bestest -$paths = [ - __DIR__ . '/../vendor/autoload.php', // In case vobject is cloned directly - __DIR__ . '/../../../autoload.php', // In case vobject is a composer dependency. -]; - -foreach($paths as $path) { - if (file_exists($path)) { - include $path; - break; - } -} - -if (!class_exists('Sabre\\VObject\\Version')) { - fwrite(STDERR, "Composer autoloader could not be properly loaded.\n"); - die(1); -} - -if ($argc < 2) { - - $version = Version::VERSION; - - $help = <<<HI -sabre/vobject $version -Usage: - generate_vcards [count] - -Options: - count The number of random vcards to generate - -Examples: - generate_vcards 1000 > testdata.vcf - -HI; - - fwrite(STDERR, $help); - exit(2); -} - -$count = (int)$argv[1]; -if ($count < 1) { - fwrite(STDERR, "Count must be at least 1\n"); - exit(2); -} - -fwrite(STDERR, "sabre/vobject " . Version::VERSION . "\n"); -fwrite(STDERR, "Generating " . $count . " vcards in vCard 4.0 format\n"); - -/** - * The following list is just some random data we compiled from various - * sources online. - * - * Very little thought went into compiling this list, and certainly nothing - * political or ethical. - * - * We would _love_ more additions to this to add more variation to this list. - * - * Send us PR's and don't be shy adding your own first and last name for fun. - */ - -$sets = array( - "nl" => array( - "country" => "Netherlands", - "boys" => array( - "Anno", - "Bram", - "Daan", - "Evert", - "Finn", - "Jayden", - "Jens", - "Jesse", - "Levi", - "Lucas", - "Luuk", - "Milan", - "René", - "Sem", - "Sibrand", - "Willem", - ), - "girls" => array( - "Celia", - "Emma", - "Fenna", - "Geke", - "Inge", - "Julia", - "Lisa", - "Lotte", - "Mila", - "Sara", - "Sophie", - "Tess", - "Zoë", - ), - "last" => array( - "Bakker", - "Bos", - "De Boer", - "De Groot", - "De Jong", - "De Vries", - "Jansen", - "Janssen", - "Meyer", - "Mulder", - "Peters", - "Smit", - "Van Dijk", - "Van den Berg", - "Visser", - "Vos", - ), - ), - "us" => array( - "country" => "United States", - "boys" => array( - "Aiden", - "Alexander", - "Charles", - "David", - "Ethan", - "Jacob", - "James", - "Jayden", - "John", - "Joseph", - "Liam", - "Mason", - "Michael", - "Noah", - "Richard", - "Robert", - "Thomas", - "William", - ), - "girls" => array( - "Ava", - "Barbara", - "Chloe", - "Dorothy", - "Elizabeth", - "Emily", - "Emma", - "Isabella", - "Jennifer", - "Lily", - "Linda", - "Margaret", - "Maria", - "Mary", - "Mia", - "Olivia", - "Patricia", - "Roxy", - "Sophia", - "Susan", - "Zoe", - ), - "last" => array( - "Smith", - "Johnson", - "Williams", - "Jones", - "Brown", - "Davis", - "Miller", - "Wilson", - "Moore", - "Taylor", - "Anderson", - "Thomas", - "Jackson", - "White", - "Harris", - "Martin", - "Thompson", - "Garcia", - "Martinez", - "Robinson", - ), - ), -); - -$current = 0; - -$r = function($arr) { - - return $arr[mt_rand(0,count($arr)-1)]; - -}; - -$bdayStart = strtotime('-85 years'); -$bdayEnd = strtotime('-20 years'); - -while($current < $count) { - - $current++; - fwrite(STDERR, "\033[100D$current/$count"); - - $country = array_rand($sets); - $gender = mt_rand(0,1)?'girls':'boys'; - - $vcard = new Component\VCard(array( - 'VERSION' => '4.0', - 'FN' => $r($sets[$country][$gender]) . ' ' . $r($sets[$country]['last']), - 'UID' => UUIDUtil::getUUID(), - )); - - $bdayRatio = mt_rand(0,9); - - if($bdayRatio < 2) { - // 20% has a birthday property with a full date - $dt = new \DateTime('@' . mt_rand($bdayStart, $bdayEnd)); - $vcard->add('BDAY', $dt->format('Ymd')); - - } elseif ($bdayRatio < 3) { - // 10% we only know the month and date of - $dt = new \DateTime('@' . mt_rand($bdayStart, $bdayEnd)); - $vcard->add('BDAY', '--' . $dt->format('md')); - } - if ($result = $vcard->validate()) { - ob_start(); - echo "\nWe produced an invalid vcard somehow!\n"; - foreach($result as $message) { - echo " " . $message['message'] . "\n"; - } - fwrite(STDERR, ob_get_clean()); - } - echo $vcard->serialize(); - -} - -fwrite(STDERR,"\nDone.\n"); diff --git a/vendor/bin/generate_vcards b/vendor/bin/generate_vcards new file mode 120000 index 000000000..cb76da13a --- /dev/null +++ b/vendor/bin/generate_vcards @@ -0,0 +1 @@ +../sabre/vobject/bin/generate_vcards \ No newline at end of file diff --git a/vendor/bin/naturalselection b/vendor/bin/naturalselection deleted file mode 100755 index 7e20439c1..000000000 --- a/vendor/bin/naturalselection +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python - -# -# Copyright (c) 2009-2010 Evert Pot -# All rights reserved. -# http://www.rooftopsolutions.nl/ -# -# This utility is distributed along with SabreDAV -# license: http://sabre.io/license/ Modified BSD License - -import os -from optparse import OptionParser -import time - -def getfreespace(path): - stat = os.statvfs(path) - return stat.f_frsize * stat.f_bavail - -def getbytesleft(path,threshold): - return getfreespace(path)-threshold - -def run(cacheDir, threshold, sleep=5, simulate=False, min_erase = 0): - - bytes = getbytesleft(cacheDir,threshold) - if (bytes>0): - print "Bytes to go before we hit threshold:", bytes - else: - print "Threshold exceeded with:", -bytes, "bytes" - dir = os.listdir(cacheDir) - dir2 = [] - for file in dir: - path = cacheDir + '/' + file - dir2.append({ - "path" : path, - "atime": os.stat(path).st_atime, - "size" : os.stat(path).st_size - }) - - dir2.sort(lambda x,y: int(x["atime"]-y["atime"])) - - filesunlinked = 0 - gainedspace = 0 - - # Left is the amount of bytes that need to be freed up - # The default is the 'min_erase setting' - left = min_erase - - # If the min_erase setting is lower than the amount of bytes over - # the threshold, we use that number instead. - if left < -bytes : - left = -bytes - - print "Need to delete at least:", left; - - for file in dir2: - - # Only deleting files if we're not simulating - if not simulate: os.unlink(file["path"]) - left = int(left - file["size"]) - gainedspace = gainedspace + file["size"] - filesunlinked = filesunlinked + 1 - - if(left<0): - break - - print "%d files deleted (%d bytes)" % (filesunlinked, gainedspace) - - - time.sleep(sleep) - - - -def main(): - parser = OptionParser( - 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", - ) - parser.add_option( - '-s', - dest="simulate", - action="store_true", - help="Don't actually make changes, but just simulate the behaviour", - ) - parser.add_option( - '-r','--runs', - help="How many times to check before exiting. -1 is infinite, which is the default", - type="int", - dest="runs", - default=-1 - ) - parser.add_option( - '-n','--interval', - help="Sleep time in seconds (default = 5)", - type="int", - dest="sleep", - default=5 - ) - parser.add_option( - '-l','--threshold', - help="Threshold in bytes (default = 10737418240, which is 10GB)", - type="int", - dest="threshold", - default=10737418240 - ) - parser.add_option( - '-m', '--min-erase', - help="Minimum number of bytes to erase when the threshold is reached. " + - "Setting this option higher will reduce the number of times the cache directory will need to be scanned. " + - "(the default is 1073741824, which is 1GB.)", - type="int", - dest="min_erase", - default=1073741824 - ) - - options,args = parser.parse_args() - if len(args)<1: - parser.error("This utility requires at least 1 argument") - cacheDir = args[0] - - print "Natural Selection" - print "Cache directory:", cacheDir - free = getfreespace(cacheDir); - print "Current free disk space:", free - - runs = options.runs; - while runs!=0 : - run( - cacheDir, - sleep=options.sleep, - simulate=options.simulate, - threshold=options.threshold, - min_erase=options.min_erase - ) - if runs>0: - runs = runs - 1 - -if __name__ == '__main__' : - main() diff --git a/vendor/bin/naturalselection b/vendor/bin/naturalselection new file mode 120000 index 000000000..e6f1b3a2a --- /dev/null +++ b/vendor/bin/naturalselection @@ -0,0 +1 @@ +../sabre/dav/bin/naturalselection \ No newline at end of file diff --git a/vendor/bin/sabredav b/vendor/bin/sabredav deleted file mode 100755 index 032371ba8..000000000 --- a/vendor/bin/sabredav +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -php -S 0.0.0.0:8080 `dirname $0`/sabredav.php diff --git a/vendor/bin/sabredav b/vendor/bin/sabredav new file mode 120000 index 000000000..3b5e4511d --- /dev/null +++ b/vendor/bin/sabredav @@ -0,0 +1 @@ +../sabre/dav/bin/sabredav \ No newline at end of file diff --git a/vendor/bin/vobject b/vendor/bin/vobject deleted file mode 100755 index 2aca7e729..000000000 --- a/vendor/bin/vobject +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env php -<?php - -namespace Sabre\VObject; - -// This sucks.. we have to try to find the composer autoloader. But chances -// are, we can't find it this way. So we'll do our bestest -$paths = [ - __DIR__ . '/../vendor/autoload.php', // In case vobject is cloned directly - __DIR__ . '/../../../autoload.php', // In case vobject is a composer dependency. -]; - -foreach($paths as $path) { - if (file_exists($path)) { - include $path; - break; - } -} - -if (!class_exists('Sabre\\VObject\\Version')) { - fwrite(STDERR, "Composer autoloader could not be loaded.\n"); - die(1); -} - -$cli = new Cli(); -exit($cli->main($argv)); - diff --git a/vendor/bin/vobject b/vendor/bin/vobject new file mode 120000 index 000000000..f5b111eac --- /dev/null +++ b/vendor/bin/vobject @@ -0,0 +1 @@ +../sabre/vobject/bin/vobject \ No newline at end of file diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index aaf70ce6f..d0dfe0ebc 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261 +class ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4 { private static $loader; @@ -19,37 +19,48 @@ class ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4', 'loadClassLoader')); - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } + $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION'); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } + call_user_func(\Composer\Autoload\ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } } $loader->register(true); - $includeFiles = require __DIR__ . '/autoload_files.php'; + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } foreach ($includeFiles as $fileIdentifier => $file) { - composerRequiree7c34560857712ac82f3f77ff9c61261($fileIdentifier, $file); + composerRequire83c487173ca2d4f0ca8866f7816b9ab4($fileIdentifier, $file); } return $loader; } } -function composerRequiree7c34560857712ac82f3f77ff9c61261($fileIdentifier, $file) +function composerRequire83c487173ca2d4f0ca8866f7816b9ab4($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { require $file; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 000000000..afafda646 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,92 @@ +<?php + +// autoload_static.php @generated by Composer + +namespace Composer\Autoload; + +class ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4 +{ + 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 $prefixesPsr0 = array ( + 'P' => + array ( + 'Psr\\Log\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/log', + ), + ), + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::$prefixesPsr0; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/examples/addressbookserver.php b/vendor/examples/addressbookserver.php deleted file mode 100644 index 6d1c9b26c..000000000 --- a/vendor/examples/addressbookserver.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - -Addressbook/CardDAV server example - -This server features CardDAV support - -*/ - -// settings -date_default_timezone_set('Canada/Eastern'); - -// Make sure this setting is turned on and reflect the root url for your WebDAV server. -// This can be for example the root / or a complete path to your server script -$baseUri = '/'; - -/* Database */ -$pdo = new PDO('sqlite:data/db.sqlite'); -$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - -//Mapping PHP errors to exceptions -function exception_error_handler($errno, $errstr, $errfile, $errline) { - throw new ErrorException($errstr, 0, $errno, $errfile, $errline); -} -set_error_handler("exception_error_handler"); - -// Autoloader -require_once 'vendor/autoload.php'; - -// Backends -$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo); -$principalBackend = new Sabre\DAVACL\PrincipalBackend\PDO($pdo); -$carddavBackend = new Sabre\CardDAV\Backend\PDO($pdo); -//$caldavBackend = new Sabre\CalDAV\Backend\PDO($pdo); - -// Setting up the directory tree // -$nodes = [ - new Sabre\DAVACL\PrincipalCollection($principalBackend), -// 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)); -$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(); diff --git a/vendor/examples/calendarserver.php b/vendor/examples/calendarserver.php deleted file mode 100644 index e5f9f3387..000000000 --- a/vendor/examples/calendarserver.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - -CalendarServer example - -This server features CalDAV support - -*/ - -// settings -date_default_timezone_set('Canada/Eastern'); - -// If you want to run the SabreDAV server in a custom location (using mod_rewrite for instance) -// You can override the baseUri here. -// $baseUri = '/'; - -/* Database */ -$pdo = new PDO('sqlite:data/db.sqlite'); -$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - -//Mapping PHP errors to exceptions -function exception_error_handler($errno, $errstr, $errfile, $errline) { - throw new ErrorException($errstr, 0, $errno, $errfile, $errline); -} -set_error_handler("exception_error_handler"); - -// Files we need -require_once 'vendor/autoload.php'; - -// Backends -$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo); -$calendarBackend = new Sabre\CalDAV\Backend\PDO($pdo); -$principalBackend = new Sabre\DAVACL\PrincipalBackend\PDO($pdo); - -// Directory structure -$tree = [ - new Sabre\CalDAV\Principal\Collection($principalBackend), - new Sabre\CalDAV\CalendarRoot($principalBackend, $calendarBackend), -]; - -$server = new Sabre\DAV\Server($tree); - -if (isset($baseUri)) - $server->setBaseUri($baseUri); - -/* Server Plugins */ -$authPlugin = new Sabre\DAV\Auth\Plugin($authBackend); -$server->addPlugin($authPlugin); - -$aclPlugin = new Sabre\DAVACL\Plugin(); -$server->addPlugin($aclPlugin); - -/* CalDAV support */ -$caldavPlugin = new Sabre\CalDAV\Plugin(); -$server->addPlugin($caldavPlugin); - -/* Calendar subscription support */ -$server->addPlugin( - new Sabre\CalDAV\Subscriptions\Plugin() -); - -/* Calendar scheduling support */ -$server->addPlugin( - new Sabre\CalDAV\Schedule\Plugin() -); - -/* WebDAV-Sync plugin */ -$server->addPlugin(new Sabre\DAV\Sync\Plugin()); - -// Support for html frontend -$browser = new Sabre\DAV\Browser\Plugin(); -$server->addPlugin($browser); - -// And off we go! -$server->exec(); diff --git a/vendor/examples/fileserver.php b/vendor/examples/fileserver.php deleted file mode 100644 index 59a453f63..000000000 --- a/vendor/examples/fileserver.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - -This is the best starting point if you're just interested in setting up a fileserver. - -Make sure that the 'public' and 'tmpdata' exists, with write permissions -for your server. - -*/ - -// settings -date_default_timezone_set('Canada/Eastern'); -$publicDir = 'public'; -$tmpDir = 'tmpdata'; - -// If you want to run the SabreDAV server in a custom location (using mod_rewrite for instance) -// You can override the baseUri here. -// $baseUri = '/'; - - -// Files we need -require_once 'vendor/autoload.php'; - -// Create the root node -$root = new \Sabre\DAV\FS\Directory($publicDir); - -// The rootnode needs in turn to be passed to the server class -$server = new \Sabre\DAV\Server($root); - -if (isset($baseUri)) - $server->setBaseUri($baseUri); - -// Support for LOCK and UNLOCK -$lockBackend = new \Sabre\DAV\Locks\Backend\File($tmpDir . '/locksdb'); -$lockPlugin = new \Sabre\DAV\Locks\Plugin($lockBackend); -$server->addPlugin($lockPlugin); - -// Support for html frontend -$browser = new \Sabre\DAV\Browser\Plugin(); -$server->addPlugin($browser); - -// Automatically guess (some) contenttypes, based on extesion -$server->addPlugin(new \Sabre\DAV\Browser\GuessContentType()); - -// Authentication backend -$authBackend = new \Sabre\DAV\Auth\Backend\File('.htdigest'); -$auth = new \Sabre\DAV\Auth\Plugin($authBackend); -$server->addPlugin($auth); - -// Temporary file filter -$tempFF = new \Sabre\DAV\TemporaryFileFilterPlugin($tmpDir); -$server->addPlugin($tempFF); - -// And off we go! -$server->exec(); diff --git a/vendor/examples/groupwareserver.php b/vendor/examples/groupwareserver.php deleted file mode 100644 index 40c1844da..000000000 --- a/vendor/examples/groupwareserver.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -/** - * This server combines both CardDAV and CalDAV functionality into a single - * server. It is assumed that the server runs at the root of a HTTP domain (be - * that a domainname-based vhost or a specific TCP port. - * - * This example also assumes that you're using SQLite and the database has - * already been setup (along with the database tables). - * - * You may choose to use MySQL instead, just change the PDO connection - * statement. - */ - -/** - * UTC or GMT is easy to work with, and usually recommended for any - * application. - */ -date_default_timezone_set('UTC'); - -/** - * Make sure this setting is turned on and reflect the root url for your WebDAV - * server. - * - * This can be for example the root / or a complete path to your server script. - */ -// $baseUri = '/'; - -/** - * Database - * - * Feel free to switch this to MySQL, it will definitely be better for higher - * concurrency. - */ -$pdo = new \PDO('sqlite:data/db.sqlite'); -$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - -/** - * Mapping PHP errors to exceptions. - * - * While this is not strictly needed, it makes a lot of sense to do so. If an - * E_NOTICE or anything appears in your code, this allows SabreDAV to intercept - * the issue and send a proper response back to the client (HTTP/1.1 500). - */ -function exception_error_handler($errno, $errstr, $errfile, $errline) { - throw new ErrorException($errstr, 0, $errno, $errfile, $errline); -} -set_error_handler("exception_error_handler"); - -// Autoloader -require_once 'vendor/autoload.php'; - -/** - * The backends. Yes we do really need all of them. - * - * This allows any developer to subclass just any of them and hook into their - * own backend systems. - */ -$authBackend = new \Sabre\DAV\Auth\Backend\PDO($pdo); -$principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo); -$carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo); -$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo); - -/** - * The directory tree - * - * Basically this is an array which contains the 'top-level' directories in the - * WebDAV server. - */ -$nodes = [ - // /principals - new \Sabre\CalDAV\Principal\Collection($principalBackend), - // /calendars - new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend), - // /addressbook - 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); -if (isset($baseUri)) $server->setBaseUri($baseUri); - -// Plugins -$server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend)); -$server->addPlugin(new \Sabre\DAV\Browser\Plugin()); -$server->addPlugin(new \Sabre\DAV\Sync\Plugin()); -$server->addPlugin(new \Sabre\DAV\Sharing\Plugin()); -$server->addPlugin(new \Sabre\DAVACL\Plugin()); - -// CalDAV plugins -$server->addPlugin(new \Sabre\CalDAV\Plugin()); -$server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); -$server->addPlugin(new \Sabre\CalDAV\SharingPlugin()); -$server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); - -// CardDAV plugins -$server->addPlugin(new \Sabre\CardDAV\Plugin()); -$server->addPlugin(new \Sabre\CardDAV\VCFExportPlugin()); - -// And off we go! -$server->exec(); diff --git a/vendor/examples/minimal.php b/vendor/examples/minimal.php deleted file mode 100644 index 4ac256064..000000000 --- a/vendor/examples/minimal.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/** - * This example shows the smallest possible sabre/dav server. - */ -include 'vendor/autoload.php'; - -$server = new Sabre\DAV\Server([ - new Sabre\DAV\FS\Directory(__DIR__) -]); - -/** - * Ok. Perhaps not the smallest possible. The browser plugin is 100% optional, - * but it really helps understanding the server. - */ -$server->addPlugin( - new Sabre\DAV\Browser\Plugin() -); - -$server->exec(); diff --git a/vendor/examples/sql/mysql.addressbooks.sql b/vendor/examples/sql/mysql.addressbooks.sql deleted file mode 100644 index 9ec88babe..000000000 --- a/vendor/examples/sql/mysql.addressbooks.sql +++ /dev/null @@ -1,28 +0,0 @@ -CREATE TABLE addressbooks ( - id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - principaluri VARBINARY(255), - displayname VARCHAR(255), - uri VARBINARY(200), - description TEXT, - 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 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; diff --git a/vendor/examples/sql/mysql.calendars.sql b/vendor/examples/sql/mysql.calendars.sql deleted file mode 100644 index 21c5bcb44..000000000 --- a/vendor/examples/sql/mysql.calendars.sql +++ /dev/null @@ -1,76 +0,0 @@ -CREATE TABLE calendarobjects ( - id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - calendardata MEDIUMBLOB, - uri VARBINARY(200), - calendarid INTEGER UNSIGNED NOT NULL, - lastmodified INT(11) UNSIGNED, - etag VARBINARY(32), - size INT(11) UNSIGNED NOT NULL, - componenttype VARBINARY(8), - firstoccurence INT(11) UNSIGNED, - lastoccurence INT(11) UNSIGNED, - uid VARBINARY(200), - UNIQUE(calendarid, uri), - INDEX calendarid_time (calendarid, firstoccurence) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE calendars ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1', - components VARBINARY(21) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE calendarinstances ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - calendarid INTEGER UNSIGNED NOT NULL, - principaluri VARBINARY(100), - access TINYINT(1) NOT NULL DEFAULT '1' COMMENT '1 = owner, 2 = read, 3 = readwrite', - displayname VARCHAR(100), - uri VARBINARY(200), - description TEXT, - calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', - calendarcolor VARBINARY(10), - timezone TEXT, - transparent TINYINT(1) NOT NULL DEFAULT '0', - share_href VARBINARY(100), - share_displayname VARCHAR(100), - share_invitestatus TINYINT(1) NOT NULL DEFAULT '2' COMMENT '1 = noresponse, 2 = accepted, 3 = declined, 4 = invalid', - UNIQUE(principaluri, uri), - UNIQUE(calendarid, principaluri), - UNIQUE(calendarid, share_href) -) 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; diff --git a/vendor/examples/sql/mysql.locks.sql b/vendor/examples/sql/mysql.locks.sql deleted file mode 100644 index 96a3a88d9..000000000 --- a/vendor/examples/sql/mysql.locks.sql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE TABLE locks ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - owner VARCHAR(100), - timeout INTEGER UNSIGNED, - created INTEGER, - token VARBINARY(100), - scope TINYINT, - depth TINYINT, - uri VARBINARY(1000), - INDEX(token), - INDEX(uri(100)) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/vendor/examples/sql/mysql.principals.sql b/vendor/examples/sql/mysql.principals.sql deleted file mode 100644 index ea0d16a27..000000000 --- a/vendor/examples/sql/mysql.principals.sql +++ /dev/null @@ -1,20 +0,0 @@ -CREATE TABLE principals ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - uri VARBINARY(200) NOT NULL, - email VARBINARY(80), - displayname VARCHAR(80), - 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'), -('principals/admin/calendar-proxy-read', null, null), -('principals/admin/calendar-proxy-write', null, null); - diff --git a/vendor/examples/sql/mysql.propertystorage.sql b/vendor/examples/sql/mysql.propertystorage.sql deleted file mode 100644 index 1b5ca5ac6..000000000 --- a/vendor/examples/sql/mysql.propertystorage.sql +++ /dev/null @@ -1,9 +0,0 @@ -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 -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE UNIQUE INDEX path_property ON propertystorage (path(600), name(100)); diff --git a/vendor/examples/sql/mysql.users.sql b/vendor/examples/sql/mysql.users.sql deleted file mode 100644 index 22ac312d5..000000000 --- a/vendor/examples/sql/mysql.users.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE users ( - id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - username VARBINARY(50), - digesta1 VARBINARY(32), - UNIQUE(username) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -INSERT INTO users (username,digesta1) VALUES -('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/examples/sql/pgsql.addressbooks.sql b/vendor/examples/sql/pgsql.addressbooks.sql deleted file mode 100644 index 98f414f42..000000000 --- a/vendor/examples/sql/pgsql.addressbooks.sql +++ /dev/null @@ -1,44 +0,0 @@ -CREATE TABLE addressbooks ( - id SERIAL NOT NULL, - principaluri VARCHAR(255), - displayname VARCHAR(255), - uri VARCHAR(200), - description TEXT, - synctoken INTEGER NOT NULL DEFAULT 1 -); - -ALTER TABLE ONLY addressbooks - ADD CONSTRAINT addressbooks_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX addressbooks_ukey - ON addressbooks USING btree (principaluri, uri); - -CREATE TABLE cards ( - id SERIAL NOT NULL, - addressbookid INTEGER NOT NULL, - carddata BYTEA, - uri VARCHAR(200), - lastmodified INTEGER, - etag VARCHAR(32), - size INTEGER NOT NULL -); - -ALTER TABLE ONLY cards - ADD CONSTRAINT cards_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX cards_ukey - ON cards USING btree (addressbookid, uri); - -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); diff --git a/vendor/examples/sql/pgsql.calendars.sql b/vendor/examples/sql/pgsql.calendars.sql deleted file mode 100644 index 67dc41a5a..000000000 --- a/vendor/examples/sql/pgsql.calendars.sql +++ /dev/null @@ -1,105 +0,0 @@ -CREATE TABLE calendarobjects ( - id SERIAL NOT NULL, - calendardata BYTEA, - uri VARCHAR(200), - calendarid INTEGER NOT NULL, - lastmodified INTEGER, - etag VARCHAR(32), - size INTEGER NOT NULL, - componenttype VARCHAR(8), - firstoccurence INTEGER, - lastoccurence INTEGER, - uid VARCHAR(200) -); - -ALTER TABLE ONLY calendarobjects - ADD CONSTRAINT calendarobjects_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX calendarobjects_ukey - ON calendarobjects USING btree (calendarid, uri); - - -CREATE TABLE calendars ( - id SERIAL NOT NULL, - synctoken INTEGER NOT NULL DEFAULT 1, - components VARCHAR(21) -); - -ALTER TABLE ONLY calendars - ADD CONSTRAINT calendars_pkey PRIMARY KEY (id); - - -CREATE TABLE calendarinstances ( - id SERIAL NOT NULL, - calendarid INTEGER NOT NULL, - principaluri VARCHAR(100), - access SMALLINT NOT NULL DEFAULT '1', -- '1 = owner, 2 = read, 3 = readwrite' - displayname VARCHAR(100), - uri VARCHAR(200), - description TEXT, - calendarorder INTEGER NOT NULL DEFAULT 0, - calendarcolor VARCHAR(10), - timezone TEXT, - transparent SMALLINT NOT NULL DEFAULT '0', - share_href VARCHAR(100), - share_displayname VARCHAR(100), - share_invitestatus SMALLINT NOT NULL DEFAULT '2' -- '1 = noresponse, 2 = accepted, 3 = declined, 4 = invalid' -); - -ALTER TABLE ONLY calendarinstances - ADD CONSTRAINT calendarinstances_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX calendarinstances_principaluri_uri - ON calendarinstances USING btree (principaluri, uri); - - -CREATE UNIQUE INDEX calendarinstances_principaluri_calendarid - ON calendarinstances USING btree (principaluri, calendarid); - -CREATE UNIQUE INDEX calendarinstances_principaluri_share_href - ON calendarinstances USING btree (principaluri, share_href); - -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); - -CREATE TABLE schedulingobjects ( - id SERIAL NOT NULL, - principaluri VARCHAR(255), - calendardata BYTEA, - uri VARCHAR(200), - lastmodified INTEGER, - etag VARCHAR(32), - size INTEGER NOT NULL -); diff --git a/vendor/examples/sql/pgsql.locks.sql b/vendor/examples/sql/pgsql.locks.sql deleted file mode 100644 index 0290528ce..000000000 --- a/vendor/examples/sql/pgsql.locks.sql +++ /dev/null @@ -1,19 +0,0 @@ -CREATE TABLE locks ( - id SERIAL NOT NULL, - owner VARCHAR(100), - timeout INTEGER, - created INTEGER, - token VARCHAR(100), - 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); diff --git a/vendor/examples/sql/pgsql.principals.sql b/vendor/examples/sql/pgsql.principals.sql deleted file mode 100644 index 5a65260a2..000000000 --- a/vendor/examples/sql/pgsql.principals.sql +++ /dev/null @@ -1,30 +0,0 @@ -CREATE TABLE principals ( - id SERIAL NOT NULL, - uri VARCHAR(200) NOT NULL, - email VARCHAR(80), - displayname VARCHAR(80) -); - -ALTER TABLE ONLY principals - ADD CONSTRAINT principals_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX principals_ukey - ON principals USING btree (uri); - -CREATE TABLE groupmembers ( - id SERIAL NOT NULL, - principal_id INTEGER NOT NULL, - member_id INTEGER NOT NULL -); - -ALTER TABLE ONLY groupmembers - ADD CONSTRAINT groupmembers_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX groupmembers_ukey - ON groupmembers USING btree (principal_id, member_id); - -INSERT INTO principals (uri,email,displayname) VALUES -('principals/admin', 'admin@example.org','Administrator'), -('principals/admin/calendar-proxy-read', null, null), -('principals/admin/calendar-proxy-write', null, null); - diff --git a/vendor/examples/sql/pgsql.propertystorage.sql b/vendor/examples/sql/pgsql.propertystorage.sql deleted file mode 100644 index d1463faae..000000000 --- a/vendor/examples/sql/pgsql.propertystorage.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE TABLE propertystorage ( - id SERIAL NOT NULL, - path VARCHAR(1024) NOT NULL, - name VARCHAR(100) NOT NULL, - valuetype INT, - value BYTEA -); - -ALTER TABLE ONLY propertystorage - ADD CONSTRAINT propertystorage_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX propertystorage_ukey - ON propertystorage (path, name); diff --git a/vendor/examples/sql/pgsql.users.sql b/vendor/examples/sql/pgsql.users.sql deleted file mode 100644 index 9d6047b8c..000000000 --- a/vendor/examples/sql/pgsql.users.sql +++ /dev/null @@ -1,14 +0,0 @@ -CREATE TABLE users ( - id SERIAL NOT NULL, - username VARCHAR(50), - digesta1 VARCHAR(32) -); - -ALTER TABLE ONLY users - ADD CONSTRAINT users_pkey PRIMARY KEY (id); - -CREATE UNIQUE INDEX users_ukey - ON users USING btree (username); - -INSERT INTO users (username,digesta1) VALUES -('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/examples/sql/sqlite.addressbooks.sql b/vendor/examples/sql/sqlite.addressbooks.sql deleted file mode 100644 index 0baed8bfb..000000000 --- a/vendor/examples/sql/sqlite.addressbooks.sql +++ /dev/null @@ -1,28 +0,0 @@ -CREATE TABLE addressbooks ( - id integer primary key asc NOT NULL, - principaluri text NOT NULL, - displayname text, - uri text NOT NULL, - description text, - synctoken integer DEFAULT 1 NOT NULL -); - -CREATE TABLE cards ( - id integer primary key asc NOT NULL, - addressbookid integer NOT NULL, - carddata blob, - 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); diff --git a/vendor/examples/sql/sqlite.calendars.sql b/vendor/examples/sql/sqlite.calendars.sql deleted file mode 100644 index 1c8070496..000000000 --- a/vendor/examples/sql/sqlite.calendars.sql +++ /dev/null @@ -1,76 +0,0 @@ -CREATE TABLE calendarobjects ( - 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, - uid text -); - -CREATE TABLE calendars ( - id integer primary key asc NOT NULL, - synctoken integer DEFAULT 1 NOT NULL, - components text NOT NULL -); - -CREATE TABLE calendarinstances ( - id integer primary key asc NOT NULL, - calendarid integer NOT NULL, - principaluri text NULL, - access integer COMMENT '1 = owner, 2 = read, 3 = readwrite' NOT NULL DEFAULT '1', - displayname text, - uri text NOT NULL, - description text, - calendarorder integer, - calendarcolor text, - timezone text, - transparent bool, - share_href text, - share_displayname text, - share_invitestatus integer DEFAULT '2', - UNIQUE (principaluri, uri), - UNIQUE (calendarid, principaluri), - UNIQUE (calendarid, share_href) -); - -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); diff --git a/vendor/examples/sql/sqlite.locks.sql b/vendor/examples/sql/sqlite.locks.sql deleted file mode 100644 index 622baea42..000000000 --- a/vendor/examples/sql/sqlite.locks.sql +++ /dev/null @@ -1,12 +0,0 @@ -BEGIN TRANSACTION; -CREATE TABLE locks ( - id integer primary key asc NOT NULL, - owner text, - timeout integer, - created integer, - token text, - scope integer, - depth integer, - uri text -); -COMMIT; diff --git a/vendor/examples/sql/sqlite.principals.sql b/vendor/examples/sql/sqlite.principals.sql deleted file mode 100644 index 4105156f8..000000000 --- a/vendor/examples/sql/sqlite.principals.sql +++ /dev/null @@ -1,20 +0,0 @@ -CREATE TABLE principals ( - id INTEGER PRIMARY KEY ASC NOT NULL, - uri TEXT NOT NULL, - email TEXT, - displayname TEXT, - UNIQUE(uri) -); - -CREATE TABLE groupmembers ( - id INTEGER PRIMARY KEY ASC NOT NULL, - principal_id INTEGER NOT NULL, - member_id INTEGER NOT NULL, - UNIQUE(principal_id, member_id) -); - - -INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin', 'admin@example.org','Administrator'); -INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-read', null, null); -INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-write', null, null); - diff --git a/vendor/examples/sql/sqlite.propertystorage.sql b/vendor/examples/sql/sqlite.propertystorage.sql deleted file mode 100644 index 72e860ce3..000000000 --- a/vendor/examples/sql/sqlite.propertystorage.sql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE TABLE propertystorage ( - id integer primary key asc NOT NULL, - path text NOT NULL, - name text NOT NULL, - valuetype integer NOT NULL, - value string -); - - -CREATE UNIQUE INDEX path_property ON propertystorage (path, name); diff --git a/vendor/examples/sql/sqlite.users.sql b/vendor/examples/sql/sqlite.users.sql deleted file mode 100644 index 5597b058a..000000000 --- a/vendor/examples/sql/sqlite.users.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE users ( - id integer primary key asc NOT NULL, - username TEXT NOT NULL, - digesta1 TEXT NOT NULL, - UNIQUE(username) -); - -INSERT INTO users (username,digesta1) VALUES -('admin', '87fd274b7b6c01e48d7c2f965da8ddf7'); diff --git a/vendor/examples/webserver/apache2_htaccess.conf b/vendor/examples/webserver/apache2_htaccess.conf deleted file mode 100644 index c5f29ba80..000000000 --- a/vendor/examples/webserver/apache2_htaccess.conf +++ /dev/null @@ -1,16 +0,0 @@ -RewriteEngine On -# This makes every request go to server.php -RewriteRule (.*) server.php [L] - -# Output buffering needs to be off, to prevent high memory usage -php_flag output_buffering off - -# 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 diff --git a/vendor/examples/webserver/apache2_vhost.conf b/vendor/examples/webserver/apache2_vhost.conf deleted file mode 100644 index 74289641e..000000000 --- a/vendor/examples/webserver/apache2_vhost.conf +++ /dev/null @@ -1,29 +0,0 @@ -# This is a sample configuration to setup a dedicated Apache vhost for WebDAV. -# -# The main thing that should be configured is the servername, and the path to -# your SabreDAV installation (DocumentRoot). -# -# This configuration assumed mod_php5 is used, as it sets a few default php -# settings as well. -<VirtualHost *:*> - - # Don't forget to change the server name - # ServerName dav.example.org - - # The DocumentRoot is also required - # DocumentRoot /home/sabredav/ - - RewriteEngine On - # This makes every request go to server.php - RewriteRule ^/(.*)$ /server.php [L] - - # Output buffering needs to be off, to prevent high memory usage - php_flag output_buffering off - - # This is also to prevent high memory usage - php_flag always_populate_raw_post_data off - - # SabreDAV is not compatible with mbstring function overloading - php_flag mbstring.func_overload off - -</VirtualHost *:*> diff --git a/vendor/examples/webserver/apache2_vhost_cgi.conf b/vendor/examples/webserver/apache2_vhost_cgi.conf deleted file mode 100644 index 607254c6e..000000000 --- a/vendor/examples/webserver/apache2_vhost_cgi.conf +++ /dev/null @@ -1,21 +0,0 @@ -# This is a sample configuration to setup a dedicated Apache vhost for WebDAV. -# -# The main thing that should be configured is the servername, and the path to -# your SabreDAV installation (DocumentRoot). -# -# This configuration assumes CGI or FastCGI is used. -<VirtualHost *:*> - - # Don't forget to change the server name - # ServerName dav.example.org - - # The DocumentRoot is also required - # DocumentRoot /home/sabredav/ - - # This makes every request go to server.php. This also makes sure - # the Authentication information is available. If your server script is - # not called server.php, be sure to change it. - RewriteEngine On - RewriteRule ^/(.*)$ /server.php [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] - -</VirtualHost *:*> diff --git a/vendor/sabre/dav/CHANGELOG.md b/vendor/sabre/dav/CHANGELOG.md new file mode 100644 index 000000000..079650965 --- /dev/null +++ b/vendor/sabre/dav/CHANGELOG.md @@ -0,0 +1,2311 @@ +ChangeLog +========= + +3.2.0-beta1 (2016-05-20) +------------------------ + +* #833: Calendars throw exceptions when the sharing plugin is not enabled. +* #834: Return vCards exactly as they were stored if we don't need to convert + in between versions. + + +3.2.0-alpha1 (2016-05-09) +------------------------- + +* Database changes for CalDAV. If you are using the CalDAV PDO backends, you + must migrate. Run `./bin/migrateto32.php` for more info. +* Support for WebDAV Resource Sharing, an upcoming standard. +* Added support for sharing in the CalDAV PDO backend! Users can now invite + others to their calendar and give them read/read-write access! +* #397: Support for PSR-3. You can now log exceptions with your favourite + psr3-compatible logging tool. +* #825: Actual proper, tested support for PostgreSQL. We require version 9.5. +* Removed database migration script for sabre/dav 1.7. To update from that + version you now first need to update to sabre/dav 3.1. +* Removed deprecated function: `Sabre\DAV\Auth\Plugin::getCurrentUser()`. +* #774: Fixes for getting free disk space on Windows. +* #803: Major changes in the sharing API. If you were using an old sabre/dav + sharing api, head to the website for more detailed migration notes. +* #657: Support for optional auth using `{DAV:}unauthorized` and `{DAV:}all` + privileges. This allows you to assign a privilege to a resource, allowing + non-authenticated users to access it. For instance, this could allow you + to create a public read-only collection. +* #812 #814: ICS/VCF exporter now includes a more useful filename in its + `Content-Disposition` header. (@Xenopathic). +* #801: BC break: If you were using the `Href` object before, it's behavior + now changed a bit, and `LocalHref` was added to replace the old, default + behavior of `Href`. See the migration doc for more info. +* Removed `Sabre\DAVACL\Plugin::$allowAccessToNodesWithoutACL` setting. + Instead, you can provide a set of default ACL rules with + `Sabre\DAVACL\Plugin::setDefaultAcl()`. +* Introduced `Sabre\DAVACL\ACLTrait` which contains a default implementation + of `Sabre\DAV\IACL` with some sane defaults. We're using this trait all over + the place now, reducing the amount of boilerplate. +* Plugins can now control the "Supported Privilege Set". +* Added Sharing, ICSExport and VCFExport plugins to `groupwareserver.php` + example. +* The `{DAV:}all` privilege is now no longer abstract, so it can be assigned + directly. We're using the `{DAV:}all` privilege now in a lot of cases where + we before assigned both `{DAV:}read` and `{DAV:}write`. +* Resources that are not collections no longer support the `{DAV:}bind` and + `{DAV:}unbind` privileges. +* Corrected the CalDAV-scheduling related privileges. +* Doing an `UNLOCK` no longer requires the `{DAV:}write-content` privilege. +* Added a new `getPrincipalByUri` plugin event. Allowing plugins to request + quickly where a principal lives on a server. +* Renamed `phpunit.xml` to `phpunit.xml.dist` to make local modifications easy. +* Functionality from `IShareableCalendar` is merged into `ISharedCalendar`. +* #751: Fixed XML responses from failing `MKCOL` requests. +* #600: Support for `principal-match` ACL `REPORT`. +* #599: Support for `acl-principal-prop-set` ACL `REPORT`. +* #798: Added an index on `firstoccurence` field in MySQL CalDAV backend. This + should speed up common calendar-query requests. +* #759: DAV\Client is now able to actually correctly resolve relative urls. +* #671: We are no longer checking the `read-free-busy` privilege on individual + calendars during freebusy operations in the scheduling plugin. Instead, we + check the `schedule-query-freebusy` privilege on the target users' inbox, + which validates access for the entire account, per the spec. +* The zip release ships with [sabre/vobject 4.1.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.1.3 (2016-04-06) +------------------ + +* Set minimum libxml version to 2.7.0 in `composer.json`. +* #805: It wasn't possible to create calendars that hold events, journals and + todos using MySQL, because the `components` column was 1 byte too small. +* The zip release ships with [sabre/vobject 4.1.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.1.2 (2016-03-12) +------------------ + +* #784: Sync logs for address books were not correctly cleaned up after + deleting them. +* #787: Cannot use non-seekable stream-wrappers with range requests. +* Faster XML parsing and generating due to sabre/xml update. +* #793: The Sqlite schema is now more strict and more similar to the MySQL + schema. This solves a problem within Baikal. +* The zip release ships with [sabre/vobject 4.0.3][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.1.1 (2016-01-25) +------------------ + +* #755: The brower plugin and some operations would break when scheduling and + delegation would both be enabled. +* #757: A bunch of unittest improvements (@jakobsack). +* The zip release ships with [sabre/vobject 4.0.2][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. + + +3.1.0 (2016-01-06) +------------------ + +* Better error message when the browser plugin is not enabled. +* Added a super minimal server example. +* #730: Switched all mysql tables to `utf8mb4` character set, allowing you to + use emoji in some tables where you couldn't before. +* #710: Provide an Auth backend that acts as a helper for people implementing + OAuth2 Bearer token. (@fkooman). +* #729: Not all calls to `Sabre\DAV\Tree::getChildren()` were properly cached. +* #727: Added another workaround to make CalDAV work for Windows 10 clients. +* #742: Fixes to make sure that vobject 4 is correctly supported. +* #726: Better error reporting in `Client::propPatch`. We're now throwing + exceptions. +* #608: When a HTTP error is triggered during `Client:propFind`, we're now + throwing `Sabre\HTTP\ClientHttpException` instead of `Sabre\DAV\Exception`. + This new exception contains a LOT more information about the problem. +* #721: Events are now handled in the correct order for `COPY` requests. + Before this subtle bugs could appear that could cause data-loss. +* #747: Now throwing exceptions and setting the HTTP status to 500 in subtle + cases where no other plugin set a correct HTTP status. +* #686: Corrected PDO principal backend's findByURI for email addresses that + don't match the exact capitalization. +* #512: The client now has it's own `User-Agent`. +* #720: Some browser improvements. +* The zip release ships with [sabre/vobject 4.0.1][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. + + +3.1.0-alpha2 (2015-09-05) +------------------------- + +* Massive calendars and addressbooks should see a big drop in peak memory + usage. +* Fixed a privilege bug in the availability system. +* #697: Added a "tableName" member to the PropertyStorage PDO backend. (@Frzk). +* #699: PostgreSQL fix for the Locks PDO backend. (@TCKnet) +* Removed the `simplefsserver.php` example file. It's not simple enough. +* #703: PropPatch in client is not correctly encoded. +* #709: Throw exception when running into empty + `supported-calendar-component-set`. +* #711: Don't trigger deserializers for empty elements in `{DAV:}prop`. This + fixes issues when using sabre/dav as a client. +* The zip release ships with [sabre/vobject 4.0.0-alpha2][vobj], + [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. + + +3.1.0-alpha1 (2015-07-19) +------------------------- + +* Now requires PHP 5.5 +* Upgraded to vobject 4, which is a lot faster. +* Support for PHP 7. +* #690: Support for `calendar-availability`, draft 05. + [reference][calendar-availability]. +* #691: Workaround for broken Windows Phone client. +* The zip release ships with [sabre/vobject 4.0.0-alpha1][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. + + +3.0.9 (2016-04-06) +------------------ + +* Set minimum libxml version to 2.7.0 in `composer.json`. +* #727: Added another workaround to make CalDAV work for Windows 10 clients. +* #805: It wasn't possible to create calendars that hold events, journals and + todos using MySQL, because the `components` column was 1 byte too small. +* The zip release ships with [sabre/vobject 3.5.1][vobj], + [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.0.8 (2016-03-12) +------------------ + +* #784: Sync logs for address books were not correctly cleaned up after + deleting them. +* #787: Cannot use non-seekable stream-wrappers with range requests. +* Faster XML parsing and generating due to sabre/xml update. +* The zip release ships with [sabre/vobject 3.5.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. + + +3.0.7 (2016-01-12) +------------------ + +* #752: PHP 7 support for 3.0 branch. (@DeepDiver1975) +* The zip release ships with [sabre/vobject 3.5.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. + + +3.0.6 (2016-01-04) +------------------ + +* #730: Switched all mysql tables to `utf8mb4` character set, allowing you to + use emoji in some tables where you couldn't before. +* #729: Not all calls to `Sabre\DAV\Tree::getChildren()` were properly cached. +* #734: Return `418 I'm a Teapot` when generating a multistatus response that + has resources with no returned properties. +* #740: Bugs in `migrate20.php` script. +* The zip release ships with [sabre/vobject 3.4.8][vobj], + [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.3.0][xml]. + + +3.0.5 (2015-09-15) +------------------ + +* #704: Fixed broken uri encoding in multistatus responses. This affected + at least CyberDuck, but probably also others. +* The zip release ships with [sabre/vobject 3.4.7][vobj], +* The zip release ships with [sabre/vobject 3.4.7][vobj], + [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. + + +3.0.4 (2015-09-06) +------------------ + +* #703: PropPatch in client is not correctly encoded. +* #709: Throw exception when running into empty + `supported-calendar-component-set`. +* #711: Don't trigger deserializers for empty elements in `{DAV:}prop`. This + fixes issues when using sabre/dav as a client. +* #705: A `MOVE` request that gets prevented from deleting the source resource + will still remove the target resource. Now all events are triggered before + any destructive operations. +* The zip release ships with [sabre/vobject 3.4.7][vobj], + [sabre/http 4.1.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.2.0][xml]. + + +3.0.3 (2015-08-06) +------------------ + +* #700: Digest Auth fails on `HEAD` requests. +* Fixed example files to no longer use now-deprecated realm argument. +* The zip release ships with [sabre/vobject 3.4.6][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. + + +3.0.2 (2015-07-21) +------------------ + +* #657: Migration script would break when coming a cross an iCalendar object + with no UID. +* #691: Workaround for broken Windows Phone client. +* Fixed a whole bunch of incorrect php docblocks. +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. + + +3.0.1 (2015-07-02) +------------------ + +* #674: Postgres sql file fixes. (@davesouthey) +* #677: Resources with the name '0' would not get retrieved when using + `Depth: infinity` in a `PROPFIND` request. +* #680: Fix 'autoprefixing' of dead `{DAV:}href` properties. +* #675: NTLM support in DAV\Client. (@k42b3) +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.1.0][xml]. + + +3.0.0 (2015-06-02) +------------------ + +* No changes since last beta. +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. + + +3.0.0-beta3 (2015-05-29) +------------------------ + +* Fixed deserializing href properties with no value. +* Fixed deserializing `{DAV:}propstat` without a `{DAV:}prop`. +* #668: More information about vcf-export-plugin in browser plugin. +* #669: Add export button to browser plugin for address books. (@mgee) +* #670: multiget report hrefs were not decoded. +* The zip release ships with [sabre/vobject 3.4.4][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. + + +3.0.0-beta2 (2015-05-27) +------------------------ + +* A node's properties should not overwrite properties that were already set. +* Some uris were not correctly encoded in notifications. +* The zip release ships with [sabre/vobject 3.4.4][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. + + +3.0.0-beta1 (2015-05-25) +------------------------ + +* `migrate22.php` is now called `migrate30.php`. +* Using php-cs-fixer for automated coding standards enforcement and fixing. +* #660: principals could break html output. +* #662: Fixed several bugs in the `share` request parser. +* #665: Fix a bug in serialization of complex properties in the proppatch + request in the client. +* #666: expand-property report did not correctly prepend the base uri when + generating uris, this caused delegation to break. +* #659: Don't throw errors when when etag-related checks are done on + collections. +* Fully supporting the updated `Prefer` header syntax, as defined in + [rfc7240][rfc7240]. +* The zip release ships with [sabre/vobject 3.4.3][vobj], + [sabre/http 4.0.0][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 1.0.0][xml]. + + +3.0.0-alpha1 (2015-05-19) +------------------------- + +* It's now possible to get all property information from files using the + browser plugin. +* Browser plugin will now show a 'calendar export' button when the + ics-export plugin is enabled. +* Some nodes that by default showed the current time as their last + modification time, now no longer has a last modification time. +* CardDAV namespace was missing from default namespaceMap. +* #646: Properties can now control their own HTML output in the browser plugin. +* #646: Nicer HTML output for the `{DAV:}acl` property. +* Browser plugin no longer shows a few properties that take up a lot of space, + but are likely not really interesting for most users. +* #654: Added a collection, `Sabre\DAVACL\FS\HomeCollection` for automatically + creating a private home collection per-user. +* Changed all MySQL columns from `VARCHAR` to `VARBINARY` where possible. +* Improved older migration scripts a bit to allow easier testing. +* The zip release ships with [sabre/vobject 3.4.3][vobj], + [sabre/http 4.0.0-alpha3][http], [sabre/event 2.0.2][evnt], + [sabre/uri 1.0.1][uri] and [sabre/xml 0.4.3][xml]. + + +2.2.0-alpha4 (2015-04-13) +------------------------- + +* Complete rewrite of the XML system. We now use our own [sabre/xml][xml], + which has a much smarter XML Reader and Writer. +* BC Break: It's no longer possible to instantiate the Locks plugin without + a locks backend. I'm not sure why this ever made sense. +* Simplified the Locking system and fixed a bug related to if tokens checking + locks unrelated to the current request. +* `FSExt` Directory and File no longer do custom property storage. This + functionality is already covered pretty well by the `PropertyStorage` plugin, + so please switch. +* Renamed `Sabre\CardDAV\UserAddressBooks` to `Sabre\CardDAV\AddressBookHome` + to be more consistent with `CalendarHome` as well as the CardDAV + specification. +* `Sabre\DAV\IExtendedCollection` now receives a `Sabre\DAV\MkCol` object as + its second argument, and no longer receives seperate properties and + resourcetype arguments. +* `MKCOL` now integrates better with propertystorage plugins. +* #623: Remove need of temporary files when working with Range requests. + (@dratini0) +* The zip release ships with [sabre/vobject 3.4.2][vobj], + [sabre/http 4.0.0-alpha1][http], [sabre/event 2.0.1][evnt], + [sabre/uri 1.0.0][uri] and [sabre/xml 0.4.3][xml]. + + +2.2.0-alpha3 (2015-02-25) +------------------------- + +* Contains all the changes introduced between 2.1.2 and 2.1.3. +* The zip release ships with [sabre/vobject 3.4.2][vobj], + [sabre/http 4.0.0-alpha1][http], [sabre/event 2.0.1][evnt] and + [sabre/uri 1.0.0][uri]. + + +2.2.0-alpha2 (2015-01-09) +------------------------- + +* Renamed `Sabre\DAV\Auth\Backend\BackendInterface::requireAuth` to + `challenge`, which is a more correct and better sounding name. +* The zip release ships with [sabre/vobject 3.3.5][vobj], + [sabre/http 3.0.4][http], [sabre/event 2.0.1][evnt]. + + +2.2.0-alpha1 (2014-12-10) +------------------------- + +* The browser plugin now has a new page with information about your sabredav + server, and shows information about every plugin that's loaded in the + system. +* #191: The Authentication system can now support multiple authentication + backends. +* Removed: all `$tableName` arguments from every PDO backend. This was already + deprecated, but has now been fully removed. All of these have been replaced + with public properties. +* Deleted several classes that were already deprecated much earlier: + * `Sabre\CalDAV\CalendarRootNode` + * `Sabre\CalDAV\UserCalendars` + * `Sabre\DAV\Exception\FileNotFound` + * `Sabre\DAV\Locks\Backend\FS` + * `Sabre\DAV\PartialUpdate\IFile` + * `Sabre\DAV\URLUtil` +* Removed: `Sabre\DAV\Client::addTrustedCertificates` and + `Sabre\DAV\Client::setVerifyPeer`. +* Removed: `Sabre\DAV\Plugin::getPlugin()` can now no longer return plugins + based on its class name. +* Removed: `Sabre\DAVACL\Plugin::getPrincipalByEmail()`. +* #560: GuessContentType plugin will now set content-type to + `application/octet-stream` if a better content-type could not be determined. +* #568: Added a `componentType` argument to `ICSExportPlugin`, allowing you to + specifically fetch `VEVENT`, `VTODO` or `VJOURNAL`. +* #582: Authentication backend interface changed to be stateless. If you + implemented your own authentication backend, make sure you upgrade your class + to the latest API! +* #582: `Sabre\DAV\Auth\Plugin::getCurrentUser()` is now deprecated. Use + `Sabre\DAV\Auth\Plugin::getCurrentPrincipal()` instead. +* #193: Fix `Sabre\DAV\FSExt\Directory::getQuotaInfo()` on windows. + + +2.1.11 (2016-??-??) +------------------- + +* #805: It wasn't possible to create calendars that hold events, journals and + todos using MySQL, because the `components` column was 1 byte too small. + + +2.1.10 (2016-03-10) +------------------- + +* #784: Sync logs for address books were not correctly cleaned up after + deleting them. + + +2.1.9 (2016-01-25) +------------------ + +* #674: PHP7 support (@DeepDiver1975). +* The zip release ships with [sabre/vobject 3.5.0][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.8 (2016-01-04) +------------------ + +* #729: Fixed a caching problem in the Tree object. +* #740: Bugs in `migrate20.php` script. +* The zip release ships with [sabre/vobject 3.4.8][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.7 (2015-09-05) +------------------ + +* #705: A `MOVE` request that gets prevented from deleting the source resource + will still remove the target resource. Now all events are triggered before + any destructive operations. +* The zip release ships with [sabre/vobject 3.4.7][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.6 (2015-07-21) +------------------ + +* #657: Migration script would break when coming a cross an iCalendar object + with no UID. +* #691: Workaround for broken Windows Phone client. +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.5 (2015-07-11) +------------------ + +* #677: Resources with the name '0' would not get retrieved when using + `Depth: infinity` in a `PROPFIND` request. +* The zip release ships with [sabre/vobject 3.4.5][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.4 (2015-05-25) +------------------ + +* #651: Double-encoded path in the browser plugin. Should fix a few broken + links in some setups. +* #650: Correctly cleaning up change info after deleting calendars (@ErrOrnAmE). +* #658: Updating `schedule-calendar-default-URL` does not work well, so we're + disabling it until there's a better fix. +* The zip release ships with [sabre/vobject 3.4.3][vobj], + [sabre/http 3.0.5][http], and [sabre/event 2.0.2][evnt]. + + +2.1.3 (2015-02-25) +------------------ + +* #586: `SCHEDULE-STATUS` should not contain a reason-phrase. +* #539: Fixed a bug related to scheduling in shared calendars. +* #595: Support for calendar-timezone in iCalendar exports. +* #581: findByUri would send empty prefixes to the principal backend (@soydeedo) +* #611: Escaping a bit more HTML output in the browser plugin. (@LukasReschke) +* #610: Don't allow discovery of arbitrary files using `..` in the browser + plugin (@LukasReschke). +* Browser plugin now shows quota properties. +* #612: PropertyStorage didn't delete properties from nodes when a node's + parents get deleted. +* #581: Fixed problems related to finding attendee information during + scheduling. +* The zip release ships with [sabre/vobject 3.4.2][vobj], + [sabre/http 3.0.4][http], and [sabre/event 2.0.1][evnt]. + + +2.1.2 (2014-12-10) +------------------ + +* #566: Another issue related to the migration script, which would cause + scheduling to not work well for events that were already added before the + migration. +* #567: Doing freebusy requests on accounts that had 0 calendars would throw + a `E_NOTICE`. +* #572: `HEAD` requests trigger a PHP warning. +* #579: Browser plugin can throw exception for a few resourcetypes that didn't + have an icon defined. +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 3.0.4][http], and [sabre/event 2.0.1][evnt]. + + +2.1.1 (2014-11-22) +------------------ + +* #561: IMip Plugin didn't strip mailto: from email addresses. +* #566: Migration process had 2 problems related to adding the `uid` field + to the `calendarobjects` table. +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. + + +2.1.0 (2014-11-19) +------------------ + +* #541: CalDAV PDO backend didn't respect overridden PDO table names. +* #550: Scheduling invites are no longer delivered into shared calendars. +* #554: `calendar-multiget` `REPORT` did not work on inbox items. +* #555: The `calendar-timezone` property is now respected for floating times + and all-day events in the `calendar-query`, `calendar-multiget` and + `free-busy-query` REPORTs. +* #555: The `calendar-timezone` property is also respected for scheduling + free-busy requests. +* #547: CalDAV system too aggressively 'corrects' incoming iCalendar data, and + as a result doesn't return an etag for common cases. +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. + + +2.1.0-alpha2 (2014-10-23) +------------------------- + +* Added: calendar-user-address-set to default principal search properties + list. This should fix iOS attendee autocomplete support. +* Changed: Moved all 'notifications' functionality from `Sabre\CalDAV\Plugin` + to a new plugin: `Sabre\CalDAV\Notifications\Plugin`. If you want to use + notifications-related functionality, just add this plugin. +* Changed: Accessing the caldav inbox, outbox or notification collection no + longer triggers getCalendarsForUser() on backends. +* #533: New invites are no longer delivered to taks-only calendars. +* #538: Added `calendarObjectChange` event. +* Scheduling speedups. +* #539: added `afterResponse` event. (@joserobleda) +* Deprecated: All the "tableName" constructor arguments for all the PDO + backends are now deprecated. They still work, but will be removed in the + next major sabredav version. Every argument that is now deprecated can now + be accessed as a public property on the respective backends. +* #529: Added getCalendarObjectByUID to PDO backend, speeding up scheduling + operations on large calendars. +* The zip release ships with [sabre/vobject 3.3.3][vobj], + [sabre/http 3.0.2][http], and [sabre/event 2.0.1][evnt]. + + +2.1.0-alpha1 (2014-09-23) +------------------------- + +* Added: Support for [rfc6638][rfc6638], also known as CalDAV Scheduling. +* Added: Automatically converting between vCard 3, 4 and jCard using the + `Accept:` header, in CardDAV reports, and automatically converting from + jCard to vCard upon `PUT`. It's important to note that your backends _may_ + now recieve both vCard 3.0 and 4.0. +* Added: #444. Collections can now opt-in to support high-speed `MOVE`. +* Changed: PropertyStorage backends now have a `move` method. +* Added: `beforeMove`, and `afterMove` events. +* Changed: A few database changes for the CalDAV PDO backend. Make sure you + run `bin/migrate21.php` to upgrade your database schema. +* Changed: CalDAV backends have a new method: `getCalendarObjectByUID`. This + method MUST be implemented by all backends, but the `AbstractBackend` has a + simple default implementation for this. +* Changed: `Sabre\CalDAV\UserCalendars` has been renamed to + `Sabre\CalDAV\CalendarHome`. +* Changed: `Sabre\CalDAV\CalendarRootNode` has been renamed to + `Sabre\CalDAV\CalendarRoot`. +* Changed: The IMipHandler has been completely removed. With CalDAV scheduling + support, it is no longer needed. It's functionality has been replaced by + `Sabre\CalDAV\Schedule\IMipPlugin`, which can now send emails for clients + other than iCal. +* Removed: `Sabre\DAV\ObjectTree` and `Sabre\DAV\Tree\FileSystem`. All this + functionality has been merged into `Sabre\DAV\Tree`. +* Changed: PrincipalBackend now has a findByUri method. +* Changed: `PrincipalBackend::searchPrincipals` has a new optional `test` + argument. +* Added: Support for the `{http://calendarserver.org/ns/}email-address-set` + property. +* #460: PropertyStorage must move properties during `MOVE` requests. +* Changed: Restructured the zip distribution to be a little bit more lean + and consistent. +* #524: Full support for the `test="anyof"` attribute in principal-search + `REPORT`. +* #472: Always returning lock tokens in the lockdiscovery property. +* Directory entries in the Browser plugin are sorted by type and name. + (@aklomp) +* #486: It's now possible to return additional properties when an 'allprop' + PROPFIND request is being done. (@aklomp) +* Changed: Now return HTTP errors when an addressbook-query REPORT is done + on a uri that's not a vcard. This should help with debugging this common + mistake. +* Changed: `PUT` requests with a `Content-Range` header now emit a 400 status + instead of 501, as per RFC7231. +* Added: Browser plugin can now display the contents of the + `{DAV:}supported-privilege-set` property. +* Added: Now reporting `CALDAV:max-resource-size`, but we're not actively + restricting it yet. +* Changed: CalDAV plugin is now responsible for reporting + `CALDAV:supported-collation-set` and `CALDAV:supported-calendar-data` + properties. +* Added: Now reporting `CARDDAV:max-resource-size`, but we're not actively + restricting it yet. +* Added: Support for `CARDDAV:supported-collation-set`. +* Changed: CardDAV plugin is now responsible for reporting + `CARDDAV:supported-address-data`. This functionality has been removed from + the CardDAV PDO backend. +* When a REPORT is not supported, we now emit HTTP error 415, instead of 403. +* #348: `HEAD` requests now work wherever `GET` also works. +* Changed: Lower priority for the iMip plugins `schedule` event listener. +* Added: #523 Custom CalDAV backends can now mark any calendar as read-only. +* The zip release ships with [sabre/vobject 3.3.3][vobj], + [sabre/http 3.0.0][http], and [sabre/event 2.0.0][evnt]. + + +2.0.9 (2015-09-04) +------------------ + +* #705: A `MOVE` request that gets prevented from deleting the source resource + will still remove the target resource. Now all events are triggered before + any destructive operations. +* The zip release ships with [sabre/vobject 3.4.6][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + + +2.0.8 (2015-07-11) +------------------ + +* #677: Resources with the name '0' would not get retrieved when using + `Depth: infinity` in a `PROPFIND` request. +* The zip release ships with [sabre/vobject 3.3.5][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.7 (2015-05-25) +------------------ + +* #650: Correctly cleaning up change info after deleting calendars (@ErrOrnAmE). +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.6 (2014-12-10) +------------------ + +* Added `Sabre\CalDAV\CalendarRoot` as an alias for + `Sabre\CalDAV\CalendarRootNode`. The latter is going to be deprecated in 2.1, + so this makes it slightly easier to write code that works in both branches. +* #497: Making sure we're initializing the sync-token field with a value after + migration. +* The zip release ships with [sabre/vobject 3.3.4][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.5 (2014-10-14) +------------------ + +* #514: CalDAV PDO backend didn't work when overriding the 'calendar changes' + database table name. +* #515: 304 status code was not being sent when checking preconditions. +* The zip release ships with [sabre/vobject 3.3.3][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.4 (2014-08-27) +------------------ + +* #483: typo in calendars creation for PostgreSQL. +* #487: Locks are now automatically removed after a node has been deleted. +* #496: Improve CalDAV and CardDAV sync when there is no webdav-sync support. +* Added: Automatically mapping internal sync-tokens to getctag. +* The zip release ships with [sabre/vobject 3.3.1][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.3 (2014-07-14) +------------------ + +* #474: Fixed PropertyStorage `pathFilter()`. +* #476: CSP policy incorrect, causing stylesheets to not load in the browser + plugin. +* #475: Href properties in the browser plugin sometimes included a backslash. +* #478: `TooMuchMatches` exception never worked. This was fixed, and we also + took this opportunity to rename it to `TooManyMatches`. +* The zip release ships with [sabre/vobject 3.2.4][vobj], + [sabre/http 2.0.4][http], and [sabre/event 1.0.1][evnt]. + + +2.0.2 (2014-06-12) +------------------ + +* #470: Fixed compatibility with PHP < 5.4.14. +* #467: Fixed a problem in `examples/calendarserver.php`. +* #466: All the postgresql sample files have been updated. +* Fixed: An error would be thrown if a client did a propfind on a node the + user didn't have access to. +* Removed: Old and broken example code from the `examples/` directory. +* The zip release ships with [sabre/vobject 3.2.3][vobj], + [sabre/http 2.0.3][http], and [sabre/event 1.0.1][evnt]. + + +2.0.1 (2014-05-28) +------------------ + +* #459: PROPFIND requests on Files with no Depth header would return a fatal + error. +* #464: A PROPFIND allprops request should not return properties with status + 404. +* The zip release ships with [sabre/vobject 3.2.2][vobj], + [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. + + +2.0.0 (2014-05-22) +------------------ + +* The zip release ships with [sabre/vobject 3.2.2][vobj], + [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. +* Fixed: #456: Issue in sqlite migration script. +* Updated: MySQL database schema optimized by using more efficient column types. +* Cleaned up browser design. + + +2.0.0-beta1 (2014-05-15) +------------------------- + +* The zip release ships with [sabre/vobject 3.2.2][vobj], + [sabre/http 2.0.3][http], and [sabre/event 1.0.0][evnt]. +* BC Break: Property updating and fetching got refactored. Read the [migration + document][mi20] for more information. This allows for creation of a generic + property storage, and other property-related functionality that was not + possible before. +* BC Break: Removed `propertyUpdate`, `beforeGetProperties` and + `afterGetProperties` events. +* Fixed: #413: Memory optimizations for the CardDAV PDO backend. +* Updated: Brand new browser plugin with more debugging features and a design + that is slightly less painful. +* Added: Support for the `{DAV:}supported-method-set` property server-wide. +* Making it easier for implementors to override how the CardDAV addressbook + home is located. +* Fixed: Issue #422 Preconditions were not being set on PUT on non-existant + files. Not really a chance for data-loss, but incorrect nevertheless. +* Fixed: Issue #428: Etag check with `If:` fails if the target is a collection. +* Fixed: Issues #430, #431, #433: Locks plugin didn't not properly release + filesystem based locks. +* Fixed: #443. Support for creating new calendar subscriptions for OS X 10.9.2 + and up. +* Removed: `Sabre\DAV\Server::NODE_*` constants. +* Moved all precondition checking into a central place, instead of having to + think about it on a per-method basis. +* jCal transformation for calendar-query REPORT now works again. +* Switched to PSR-4 +* Fixed: #175. Returning ETag header upon a failed `If-Match` or + `If-None-Match` check. +* Removed: `lib/Sabre/autoload.php`. Use `vendor/autoload.php` instead. +* Removed: all the rfc documentation from the sabre/dav source. This made the + package needlessly larger. +* Updated: Issue #439. Lots of updates in PATCH support. The + Sabre_DAV_PartialUpdate_IFile interface is now deprecated and will be + removed in a future version. +* Added: `Sabre\DAV\Exception\LengthRequired`. + +1.9.0-alpha2 (2014-01-14) +------------------------- + +* The zip release ships with sabre/vobject 3.1.3, sabre/http 2.0.1, and + sabre/event 1.0.0. +* Added: Browser can now inspect any node, if ?sabreaction=browser is appended. +* Fixed: Issue #178. Support for multiple items in the Timeout header. +* Fixed: Issue #382. Stricter checking if calendar-query is allowed to run. +* Added: Depth: Infinity support for PROPFIND request. Thanks Thomas Müller and + Markus Goetz. + + +1.9.0-alpha1 (2013-11-07) +------------------------- + +* The zip release ships with sabre/vobject 3.1.3, sabre/http 2.0.0alpha5, and + sabre/event 1.0.0. +* BC Break: The CardDAV and CalDAV BackendInterface each have a new method: + getMultipleCards and getMultipleCalendarObjects. The Abstract and PDO backends + have default implementations, but if you implement that interface directly, + this method is now required. +* BC Break: XML property classes now receive an extra argument in their + unserialize method ($propertyMap). This allows for recursively parsing + properties, if needed. +* BC Break: Now using sabre/event for event emitting/subscription. For plugin + authors this means Server::subscribeEvent is now Server::on, and + Server::broadcastEvent is now Server::emit. +* BC Break: Almost all core functionality moved into a CorePlugin. +* BC Break: Most events triggered by the server got an overhaul. +* Changed: Sabre\HTTP now moved into a dedicated sabre/http package. +* Added: Support for WebDAV-sync (rfc6578). +* Added: Support for caldav-subscriptions, which is an easy way for caldav + clients to manage a list of subscriptions on the server. +* Added: Support for emitting and receiving jCal instead of iCalendar for + CalDAV. +* Added: BasicCallback authenticaton backend, for creating simple authentication + systems without having to define any classes. +* Added: A $transactionType property on the server class. This can be used for + logging and performance measuring purposes. +* Fixed: If event handlers modify the request body from a PUT request, an ETag + is no longer sent back. +* Added: Sabre\DAV\IMultiGet to optimize requests that retrieve information + about lists of resources. +* Added: MultiGet support to default CalDAV and CardDAV backends, speeding up + the multiget and sync reports quite a bit! +* Added: ICSExportPlugin can now generate jCal, filter on time-ranges and expand + recurrences. +* Fixed: Read-only access to calendars still allows the sharee to modify basic + calendar properties, such as the displayname and color. +* Changed: The default supportedPrivilegeSet has changed. Most privileges are no + longer marked as abstract. +* Changed: More elegant ACL management for CalendarObject and Card nodes. +* Added: Browser plugin now marks a carddav directory as type Directory, and a + shared calendar as 'Shared'. +* Added: When debugExceptions is turned on, all previous exceptions are also + traversed. +* Removed: Got rid of the Version classes for CalDAV, CardDAV, HTTP, and DAVACL. + Now that there's no separate packages anymore, this makes a bit more sense. +* Added: Generalized the multistatus response parser a bit more, for better + re-use. +* Added: Sabre\DAV\Client now has support for complex properties for PROPPATCH. + (Issue #299). +* Added: Sabre\DAV\Client has support for gzip and deflate encoding. +* Added: Sabre\DAV\Client now has support for sending objects as streams. +* Added: Deserializer for {DAV:}current-user-privilege-set. +* Added: Addressbooks or backends can now specify custom acl rules when creating + cards. +* Added: The ability for plugins to validate custom tokens in If: headers. +* Changed: Completely refactored the Lock plugin to deal with the new If: header + system. +* Added: Checking preconditions for MOVE, COPY, DELETE and PROPPATCH methods. +* Added: has() method on DAV\Property\SupportedReportSet. +* Added: If header now gets checked (with ETag) all the time. Before the dealing + with the If-header was a responsibility of the Locking plugin. +* Fixed: Outbox access for delegates. +* Added: Issue 333: It's now possible to override the calendar-home in the + CalDAV plugin. +* Added: A negotiateContentType to HTTP\Request. A convenience method. +* Fixed: Issue 349: Denying copying or moving a resource into it's own subtree. +* Fixed: SabreDAV catches every exception again. +* Added: Issue #358, adding a component=vevent parameter to the content-types + for calendar objects, if the caldav backend provides this info. + + +1.8.12-stable (2015-01-21) +-------------------------- + +* The zip release ships with sabre/vobject 2.1.7. +* #568: Support empty usernames and passwords in basic auth. + + +1.8.11 (2014-12-10) +------------------- + +* The zip release ships with sabre/vobject 2.1.6. +* Updated: MySQL database schema optimized by using more efficient column types. +* #516: The DAV client will now only redirect to HTTP and HTTPS urls. + + +1.8.10 (2014-05-15) +------------------- + +* The zip release ships with sabre/vobject 2.1.4. +* includes changes from version 1.7.12. + + +1.8.9 (2014-02-26) +------------------ + +* The zip release ships with sabre/vobject 2.1.3. +* includes changes from version 1.7.11. + + +1.8.8 (2014-02-09) +------------------ + +* includes changes from version 1.7.10. +* The zip release ships with sabre/vobject 2.1.3. + +1.8.7 (2013-10-02) +------------------ + +* the zip release ships with sabre/vobject 2.1.3. +* includes changes from version 1.7.9. + + +1.8.6 (2013-06-18) +------------------ + +* The zip release ships with sabre/vobject 2.1.0. +* Includes changes from version 1.7.8. + + +1.8.5 (2013-04-11) +------------------ + +* The zip release ships with sabre/vobject 2.0.7. +* Includes changes from version 1.7.7. + + +1.8.4 (2013-04-08) +------------------ + +* The zip release ships with sabre/vobject 2.0.7. +* Includes changes from version 1.7.6. + + +1.8.3 (2013-03-01) +------------------ + +* The zip release ships with sabre/vobject 2.0.6. +* Includes changes from version 1.7.5. +* Fixed: organizer email-address for shared calendars is now prefixed with + mailto:, as it should. + + +1.8.2 (2013-01-19) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Includes changes from version 1.7.4. + + +1.8.1 (2012-12-01) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Includes changes from version 1.7.3. +* Fixed: Typo in 1.7 migration script caused it to fail. + + +1.8.0 (2012-11-08) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* BC Break: Moved the entire codebase to PHP namespaces. +* BC Break: Every backend package (CalDAV, CardDAV, Auth, Locks, Principals) now + has consistent naming conventions. There's a BackendInterface, and an + AbstractBackend class. +* BC Break: Changed a bunch of constructor signatures in the CalDAV package, to + reduce dependencies on the ACL package. +* BC Break: Sabre_CalDAV_ISharedCalendar now also has a getShares method, so + sharees can figure out who is also on a shared calendar. +* Added: Sabre_DAVACL_IPrincipalCollection interface, to advertise support for + principal-property-search on any node. +* Added: Simple console script to fire up a fileserver in the current directory + using PHP 5.4's built-in webserver. +* Added: Sharee's can now also read out the list of invites for a shared + calendar. +* Added: The Proxy principal classes now both implement an interface, for + greater flexiblity. + + +1.7.13 (2014-07-28) +------------------- + +* The zip release ships with sabre/vobject 2.1.4. +* Changed: Removed phing and went with a custom build script for now. + + +1.7.12 (2014-05-15) +------------------- + +* The zip release ships with sabre/vobject 2.1.4. +* Updated: Issue #439. Lots of updates in PATCH support. The + Sabre_DAV_PartialUpdate_IFile interface is now deprecated and will be removed + in a future version. +* Fixed: Restoring old setting after changing libxml_disable_entity_loader. +* Fixed: Issue #422: Preconditions were not being set on PUT on non-existant + files. Not really a chance for data-loss, but incorrect nevertheless. +* Fixed: Issue #427: Now checking preconditions on DELETE requests. +* Fixed: Issue #428: Etag check with If: fails if the target is a collection. +* Fixed: Issue #393: PATCH request with missing end-range was handled + incorrectly. +* Added: Sabre_DAV_Exception_LengthRequired to omit 411 errors. + + +1.7.11 (2014-02-26) +------------------- + +* The zip release ships with sabre/vobject 2.1.3. +* Fixed: Issue #407: large downloads failed. +* Fixed: Issue #414: XXE security problem on older PHP versions. + + +1.7.10 (2014-02-09) +------------------- + +* Fixed: Issue #374: Don't urlescape colon (:) when it's not required. +* Fixed: Potential security vulnerability in the http client. + + +1.7.9 (2013-10-02) +------------------ + +* The zip release ships with sabre/vobject 2.1.3. +* Fixed: Issue #365. Incorrect output when principal urls have spaces in them. +* Added: Issue #367: Automatically adding a UID to vcards that don't have them. + + +1.7.8 (2013-06-17) +------------------ + +* The zip release ships with sabre/vobject 2.1.0. +* Changed: Sabre\DAV\Client::verifyPeer is now a protected property (instead of + private). +* Fixed: Text was incorrectly escaped in the Href and HrefList properties, + disallowing urls with ampersands (&) in them. +* Added: deserializer for Sabre\DAVACL\Property\CurrentUserPrivilegeSet. +* Fixed: Issue 335: Client only deserializes properties with status 200. +* Fixed: Issue 341: Escaping xml in 423 Locked error responses. +* Added: Issue 339: beforeGetPropertiesForPath event. + + +1.7.7 (2013-04-11) +------------------ + +* The zip release ships with sabre/vobject 2.0.7. +* Fixed: Assets in the browser plugins were not being served on windows + machines. + + +1.7.6 (2013-04-08) +------------------ + +* The zip release ships with sabre/vobject 2.0.7. +* Fixed: vcardurl in database schema can now hold 255 characters instead of 80 + (which is often way to small). +* Fixed: The browser plugin potentially allowed people to open any arbitrary + file on windows servers (CVE-2013-1939). + + +1.7.5 (2013-03-01) +------------------ + +* The zip release ships with sabre/vobject 2.0.6. +* Change: No longer advertising support for 4.0 vcards. iOS and OS X address + book don't handle this well, and just advertising 3.0 support seems like the + most logical course of action. +* Added: ->setVerifyPeers to Sabre_DAV_Client (greatly resisting against it, + don't use this..). + + +1.7.4 (2013-01-19) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Changed: To be compatibile with MS Office 2011 for Mac, a workaround was + removed that was added to support old versions of Windows XP (pre-SP3). + Indeed! We needed a crazy workaround to work with one MS product in the past, + and we can't keep that workaround to be compatible with another MS product. +* Fixed: expand-properties REPORT had incorrect values for the href element. +* Fixed: Range requests now work for non-seekable streams. (Thanks Alfred + Klomp). +* Fixed: Changed serialization of {DAV:}getlastmodified and {DAV:}supportedlock + to improve compatiblity with MS Office 2011 for Mac. +* Changed: reverted the automatic translation of 'DAV:' xml namespaces to + 'urn:DAV' when parsing files. Issues were reported with libxml 2.6.32, on a + relatively recent debian release, so we'll wait till 2015 to take this one out + again. +* Added: Sabre_DAV_Exception_ServiceUnavailable, for emitting 503's. + + +1.7.3 (2012-12-01) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Fixed: Removing double slashes from getPropertiesForPath. +* Change: Marked a few more properties in the CardDAV as protected, instead of + private. +* Fixed: SharingPlugin now plays nicer with other plugins with similar + functionality. +* Fixed: Issue 174. Sending back HTTP/1.0 for requests with this version. + + +1.7.2 (2012-11-08) +------------------ + +* The zip release ships with sabre/vobject 2.0.5. +* Added: ACL plugin advertises support for 'calendarserver-principal- + property-search'. +* Fixed: [#153] Allowing for relative http principals in iMip requests. +* Added: Support for cs:first-name and cs:last-name properties in sharing + invites. +* Fixed: Made a bunch of properties protected, where they were private before. +* Added: Some non-standard properties for sharing to improve compatibility. +* Fixed: some bugfixes in postgres sql script. +* Fixed: When requesting some properties using PROPFIND, they could show up as + both '200 Ok' and '403 Forbidden'. +* Fixed: calendar-proxy principals were not checked for deeper principal + membership than 1 level. +* Fixed: setGroupMemberSet argument now correctly receives relative principal + urls, instead of the absolute ones. +* Fixed: Server class will filter out any bonus properties if any extra were + returned. This means the implementor of the IProperty class can be a bit + lazier when implementing. Note: bug numbers after this line refer to Google + Code tickets. We're using github now. + + +1.7.1 (2012-10-07) +------------------ + +* Fixed: include path problem in the migration script. + + +1.7.0 (2012-10-06) +------------------ + +* BC Break: The calendarobjects database table has a bunch of new fields, and a + migration script is required to ensure everything will keep working. Read the + wiki for more details. +* BC Break: The ICalendar interface now has a new method: calendarQuery. +* BC Break: In this version a number of classes have been deleted, that have + been previously deprecated. Namely: - Sabre_DAV_Directory (now: + Sabre_DAV_Collection) - Sabre_DAV_SimpleDirectory (now: + Sabre_DAV_SimpleCollection) +* BC Break: Sabre_CalDAV_Schedule_IMip::sendMessage now has an extra argument. + If you extended this class, you should fix this method. It's only used for + informational purposes. +* BC Break: The DAV: namespace is no longer converted to urn:DAV. This was a + workaround for a bug in older PHP versions (pre-5.3). +* Removed: Sabre.includes.php was deprecated, and is now removed. +* Removed: Sabre_CalDAV_Server was deprecated, and is now removed. Please use + Sabre_DAV_Server and check the examples in the examples/ directory. +* Changed: The Sabre_VObject library now spawned into it's own project! The + VObject library is still included in the SabreDAV zip package. +* Added: Experimental interfaces to allow implementation of caldav-sharing. Note + that no implementation is provided yet, just the api hooks. +* Added: Free-busy reporting compliant with the caldav-scheduling standard. This + allows iCal and other clients to fetch other users' free-busy data. +* Added: Experimental NotificationSupport interface to add caldav notifications. +* Added: VCF Export plugin. If enabled, it can generate an export of an entire + addressbook. +* Added: Support for PATCH using a SabreDAV format, to live-patch files. +* Added: Support for Prefer: return-minimal and Brief: t headers for PROPFIND + and PROPPATCH requests. +* Changed: Responsibility for dealing with the calendar-query is now moved from + the CalDAV plugin to the CalDAV backends. This allows for heavy optimizations. +* Changed: The CalDAV PDO backend is now a lot faster for common calendar + queries. +* Changed: We are now using the composer autoloader. +* Changed: The CalDAV backend now all implement an interface. +* Changed: Instead of Sabre_DAV_Property, Sabre_DAV_PropertyInterface is now the + basis of every property class. +* Update: Caching results for principal lookups. This should cut down queries + and performance for a number of heavy requests. +* Update: ObjectTree caches lookups much more aggresively, which will help + especially speeding up a bunch of REPORT queries. +* Added: Support for the schedule-calendar-transp property. +* Fixed: Marking both the text/calendar and text/x-vcard as UTF-8 encoded. +* Fixed: Workaround for the SOGO connector, as it doesn't understand receiving + "text/x-vcard; charset=utf-8" for a contenttype. +* Added: Sabre_DAV_Client now throws more specific exceptions in cases where we + already has an exception class. +* Added: Sabre_DAV_PartialUpdate. This plugin allows you to use the PATCH method + to update parts of a file. +* Added: Tons of timezone name mappings for Microsoft Exchange. +* Added: Support for an 'exception' event in the server class. +* Fixed: Uploaded VCards without a UID are now rejected. (thanks Dominik!) +* Fixed: Rejecting calendar objects if they are not in the + supported-calendar-component list. (thanks Armin!) +* Fixed: Issue 219: serialize() now reorders correctly. +* Fixed: Sabre_DAV_XMLUtil no longer returns empty $dom->childNodes if there is + whitespace in $dom. +* Fixed: Returning 409 Conflict instead of 500 when an attempt is made to create + a file as a child of something that's not a collection. +* Fixed: Issue 237: xml-encoding values in SabreDAV error responses. +* Fixed: Returning 403, instead of 501 when an unknown REPORT is requested. +* Fixed: Postfixing slash on {DAV:}owner properties. +* Fixed: Several embarrassing spelling mistakes in docblocks. + + +1.6.10 (2013-06-17) +------------------- + +* Fixed: Text was incorrectly escaped in the Href and HrefList properties, + disallowing urls with ampersands (&) in them. +* Fixed: Issue 341: Escaping xml in 423 Locked error responses. + + +1.6.9 (2013-04-11) +------------------ + +* Fixed: Assets in the browser plugins were not being served on windows + machines. + + +1.6.8 (2013-04-08) +------------------ + +* Fixed: vcardurl in database schema can now hold 255 characters instead of 80 + (which is often way to small). +* Fixed: The browser plugin potentially allowed people to open any arbitrary + file on windows servers. (CVE-2013-1939). + + +1.6.7 (2013-03-01) +------------------ + +* Change: No longer advertising support for 4.0 vcards. iOS and OS X address + book don't handle this well, and just advertising 3.0 support seems like the + most logical course of action. +* Added: ->setVerifyPeers to Sabre_DAV_Client (greatly resisting against it, + don't use this..). + + +1.6.6 (2013-01-19) +------------------ + +* Fixed: Backported a fix for broken XML serialization in error responses. + (Thanks @DeepDiver1975!) + + +1.6.5 (2012-10-04) +------------------ + +* Fixed: Workaround for line-ending bug OS X 10.8 addressbook has. +* Added: Ability to allow users to set SSL certificates for the Client class. + (Thanks schiesbn!). +* Fixed: Directory indexes with lots of nodes should be a lot faster. +* Fixed: Issue 235: E_NOTICE thrown when doing a propfind request with + Sabre_DAV_Client, and no valid properties are returned. +* Fixed: Issue with filtering on alarms in tasks. + + +1.6.4 (2012-08-02) +------------------ + +* Fixed: Issue 220: Calendar-query filters may fail when filtering on alarms, if + an overridden event has it's alarm removed. +* Fixed: Compatibility for OS/X 10.8 iCal in the IMipHandler. +* Fixed: Issue 222: beforeWriteContent shouldn't be called for lock requests. +* Fixed: Problem with POST requests to the outbox if mailto: was not lower + cased. +* Fixed: Yearly recurrence rule expansion on leap-days no behaves correctly. +* Fixed: Correctly checking if recurring, all-day events with no dtstart fall in + a timerange if the start of the time-range exceeds the start of the instance + of an event, but not the end. +* Fixed: All-day recurring events wouldn't match if an occurence ended exactly + on the start of a time-range. +* Fixed: HTTP basic auth did not correctly deal with passwords containing colons + on some servers. +* Fixed: Issue 228: DTEND is now non-inclusive for all-day events in the + calendar-query REPORT and free-busy calculations. + + +1.6.3 (2012-06-12) +------------------ + +* Added: It's now possible to specify in Sabre_DAV_Client which type of + authentication is to be used. +* Fixed: Issue 206: Sabre_DAV_Client PUT requests are fixed. +* Fixed: Issue 205: Parsing an iCalendar 0-second date interval. +* Fixed: Issue 112: Stronger validation of iCalendar objects. Now making sure + every iCalendar object only contains 1 component, and disallowing vcards, + forcing every component to have a UID. +* Fixed: Basic validation for vcards in the CardDAV plugin. +* Fixed: Issue 213: Workaround for an Evolution bug, that prevented it from + updating events. +* Fixed: Issue 211: A time-limit query on a non-relative alarm trigger in a + recurring event could result in an endless loop. +* Fixed: All uri fields are now a maximum of 200 characters. The Bynari outlook + plugin used much longer strings so this should improve compatibility. +* Fixed: Added a workaround for a bug in KDE 4.8.2 contact syncing. See + https://bugs.kde.org/show_bug.cgi?id=300047 +* Fixed: Issue 217: Sabre_DAV_Tree_FileSystem was pretty broken. + + +1.6.2 (2012-04-16) +------------------ + +* Fixed: Sabre_VObject_Node::$parent should have been public. +* Fixed: Recurrence rules of events are now taken into consideration when doing + time-range queries on alarms. +* Fixed: Added a workaround for the fact that php's DateInterval cannot parse + weeks and days at the same time. +* Added: Sabre_DAV_Server::$exposeVersion, allowing you to hide SabreDAV's + version number from various outputs. +* Fixed: DTSTART values would be incorrect when expanding events. +* Fixed: DTSTART and DTEND would be incorrect for expansion of WEEKLY BYDAY + recurrences. +* Fixed: Issue 203: A problem with overridden events hitting the exact date and + time of a subsequent event in the recurrence set. +* Fixed: There was a problem with recurrence rules, for example the 5th tuesday + of the month, if this day did not exist. +* Added: New HTTP status codes from draft-nottingham-http-new-status-04. + + +1.6.1 (2012-03-05) +------------------ + +* Added: createFile and put() can now return an ETag. +* Added: Sending back an ETag on for operations on CardDAV backends. This should + help with OS X 10.6 Addressbook compatibility. +* Fixed: Fixed a bug where an infinite loop could occur in the recurrence + iterator if the recurrence was YEARLY, with a BYMONTH rule, and either BYDAY + or BYMONTHDAY match the first day of the month. +* Fixed: Events that are excluded using EXDATE are still counted in the COUNT= + parameter in the RRULE property. +* Added: Support for time-range filters on VALARM components. +* Fixed: Correctly filtering all-day events. +* Fixed: Sending back correct mimetypes from the browser plugin (thanks + Jürgen). +* Fixed: Issue 195: Sabre_CardDAV pear package had an incorrect dependency. +* Fixed: Calendardata would be destroyed when performing a MOVE request. + + +1.6.0 (2012-02-22) +------------------ + +* BC Break: Now requires PHP 5.3 +* BC Break: Any node that implemented Sabre_DAVACL_IACL must now also implement + the getSupportedPrivilegeSet method. See website for details. +* BC Break: Moved functions from Sabre_CalDAV_XMLUtil to + Sabre_VObject_DateTimeParser. +* BC Break: The Sabre_DAVACL_IPrincipalCollection now has two new methods: + 'searchPrincipals' and 'updatePrincipal'. +* BC Break: Sabre_DAV_ILockable is removed and all related per-node locking + functionality. +* BC Break: Sabre_DAV_Exception_FileNotFound is now deprecated in favor of + Sabre_DAV_Exception_NotFound. The former will be removed in a later version. +* BC Break: Removed Sabre_CalDAV_ICalendarUtil, use Sabre_VObject instead. +* BC Break: Sabre_CalDAV_Server is now deprecated, check out the documentation + on how to setup a caldav server with just Sabre_DAV_Server. +* BC Break: Default Principals PDO backend now needs a new field in the + 'principals' table. See the website for details. +* Added: Ability to create new calendars and addressbooks from within the + browser plugin. +* Added: Browser plugin: icons for various nodes. +* Added: Support for FREEBUSY reports! +* Added: Support for creating principals with admin-level privileges. +* Added: Possibility to let server send out invitation emails on behalf of + CalDAV client, using Sabre_CalDAV_Schedule_IMip. +* Changed: beforeCreateFile event now passes data argument by reference. +* Changed: The 'propertyMap' property from Sabre_VObject_Reader, must now be + specified in Sabre_VObject_Property::$classMap. +* Added: Ability for plugins to tell the ACL plugin which principal plugins are + searchable. +* Added: [DAVACL] Per-node overriding of supported privileges. This allows for + custom privileges where needed. +* Added: [DAVACL] Public 'principalSearch' method on the DAVACL plugin, which + allows for easy searching for principals, based on their properties. +* Added: Sabre_VObject_Component::getComponents() to return a list of only + components and not properties. +* Added: An includes.php file in every sub-package (CalDAV, CardDAV, DAV, + DAVACL, HTTP, VObject) as an alternative to the autoloader. This often works + much faster. +* Added: Support for the 'Me card', which allows Addressbook.app users specify + which vcard is their own. +* Added: Support for updating principal properties in the DAVACL principal + backends. +* Changed: Major refactoring in the calendar-query REPORT code. Should make + things more flexible and correct. +* Changed: The calendar-proxy-[read|write] principals will now only appear in + the tree, if they actually exist in the Principal backend. This should reduce + some problems people have been having with this. +* Changed: Sabre_VObject_Element_* classes are now renamed to + Sabre_VObject_Property. Old classes are retained for backwards compatibility, + but this will be removed in the future. +* Added: Sabre_VObject_FreeBusyGenerator to generate free-busy reports based on + lists of events. +* Added: Sabre_VObject_RecurrenceIterator to find all the dates and times for + recurring events. +* Fixed: Issue 97: Correctly handling RRULE for the calendar-query REPORT. +* Fixed: Issue 154: Encoding of VObject parameters with no value was incorrect. +* Added: Support for {DAV:}acl-restrictions property from RFC3744. +* Added: The contentlength for calendar objects can now be supplied by a CalDAV + backend, allowing for more optimizations. +* Fixed: Much faster implementation of Sabre_DAV_URLUtil::encodePath. +* Fixed: {DAV:}getcontentlength may now be not specified. +* Fixed: Issue 66: Using rawurldecode instead of urldecode to decode paths from + clients. This means that + will now be treated as a literal rather than a + space, and this should improve compatibility with the Windows built-in client. +* Added: Sabre_DAV_Exception_PaymentRequired exception, to emit HTTP 402 status + codes. +* Added: Some mysql unique constraints to example files. +* Fixed: Correctly formatting HTTP dates. +* Fixed: Issue 94: Sending back Last-Modified header for 304 responses. +* Added: Sabre_VObject_Component_VEvent, Sabre_VObject_Component_VJournal, + Sabre_VObject_Component_VTodo and Sabre_VObject_Component_VCalendar. +* Changed: Properties are now also automatically mapped to their appropriate + classes, if they are created using the add() or __set() methods. +* Changed: Cloning VObject objects now clones the entire tree, rather than just + the default shallow copy. +* Added: Support for recurrence expansion in the CALDAV:calendar-multiget and + CALDAV:calendar-query REPORTS. +* Changed: CalDAV PDO backend now sorts calendars based on the internal + 'calendarorder' field. +* Added: Issue 181: Carddav backends may no optionally not supply the carddata + in getCards, if etag and size are specified. This may speed up certain + requests. +* Added: More arguments to beforeWriteContent and beforeCreateFile (see + WritingPlugins wiki document). +* Added: Hook for iCalendar validation. This allows us to validate iCalendar + objects when they're uploaded. At the moment we're just validating syntax. +* Added: VObject now support Windows Timezone names correctly (thanks mrpace2). +* Added: If a timezonename could not be detected, we fall back on the default + PHP timezone. +* Added: Now a Composer package (thanks willdurand). +* Fixed: Support for \N as a newline character in the VObject reader. +* Added: afterWriteContent, afterCreateFile and afterUnbind events. +* Added: Postgresql example files. Not part of the unittests though, so use at + your own risk. +* Fixed: Issue 182: Removed backticks from sql queries, so it will work with + Postgres. + + +1.5.9 (2012-04-16) +------------------ + +* Fixed: Issue with parsing timezone identifiers that were surrounded by quotes. + (Fixes emClient compatibility). + + +1.5.8 (2012-02-22) +------------------ + +* Fixed: Issue 95: Another timezone parsing issue, this time in calendar-query. + + +1.5.7 (2012-02-19) +------------------ + +* Fixed: VObject properties are now always encoded before components. +* Fixed: Sabre_DAVACL had issues with multiple levels of privilege aggregration. +* Changed: Added 'GuessContentType' plugin to fileserver.php example. +* Fixed: The Browser plugin will now trigger the correct events when creating + files. +* Fixed: The ICSExportPlugin now considers ACL's. +* Added: Made it optional to supply carddata from an Addressbook backend when + requesting getCards. This can make some operations much faster, and could + result in much lower memory use. +* Fixed: Issue 187: Sabre_DAV_UUIDUtil was missing from includes file. +* Fixed: Issue 191: beforeUnlock was triggered twice. + + +1.5.6 (2012-01-07) +------------------ + +* Fixed: Issue 174: VObject could break UTF-8 characters. +* Fixed: pear package installation issues. + + +1.5.5 (2011-12-16) +------------------ + +* Fixed: CalDAV time-range filter workaround for recurring events. +* Fixed: Bug in Sabre_DAV_Locks_Backend_File that didn't allow multiple files to + be locked at the same time. + + +1.5.4 (2011-10-28) +------------------ + +* Fixed: GuessContentType plugin now supports mixed case file extensions. +* Fixed: DATE-TIME encoding was wrong in VObject. (we used 'DATETIME'). +* Changed: Sending back HTTP 204 after a PUT request on an existing resource + instead of HTTP 200. This should fix Evolution CardDAV client compatibility. +* Fixed: Issue 95: Parsing X-LIC-LOCATION if it's available. +* Added: All VObject elements now have a reference to their parent node. + + +1.5.3 (2011-09-28) +------------------ + +* Fixed: Sabre_DAV_Collection was missing from the includes file. +* Fixed: Issue 152. iOS 1.4.2 apparantly requires HTTP/1.1 200 OK to be in + uppercase. +* Fixed: Issue 153: Support for files with mixed newline styles in + Sabre_VObject. +* Fixed: Issue 159: Automatically converting any vcard and icalendardata to + UTF-8. +* Added: Sabre_DAV_SimpleFile class for easy static file creation. +* Added: Issue 158: Support for the CARDDAV:supported-address-data property. + + +1.5.2 (2011-09-21) +------------------ + +* Fixed: carddata and calendardata MySQL fields are now of type 'mediumblob'. + 'TEXT' was too small sometimes to hold all the data. +* Fixed: {DAV:}supported-report-set is now correctly reporting the reports for + IAddressBook. +* Added: Sabre_VObject_Property::add() to add duplicate parameters to + properties. +* Added: Issue 151: Sabre_CalDAV_ICalendar and Sabre_CalDAV_ICalendarObject + interfaces. +* Fixed: Issue 140: Not returning 201 Created if an event cancelled the creation + of a file. +* Fixed: Issue 150: Faster URLUtil::encodePath() implementation. +* Fixed: Issue 144: Browser plugin could interfere with + TemporaryFileFilterPlugin if it was loaded first. +* Added: It's not possible to specify more 'alternate uris' in principal + backends. + + +1.5.1 (2011-08-24) +------------------ + +* Fixed: Issue 137. Hiding action interface in HTML browser for non-collections. +* Fixed: addressbook-query is now correctly returned from the + {DAV:}supported-report-set property. +* Fixed: Issue 142: Bugs in groupwareserver.php example. +* Fixed: Issue 139: Rejecting PUT requests with Content-Range. + + +1.5.0 (2011-08-12) +------------------ + +* Added: CardDAV support. +* Added: An experimental WebDAV client. +* Added: MIME-Directory grouping support in the VObject library. This is very + useful for people attempting to parse vcards. +* BC Break: Adding parameters with the VObject libraries now overwrites the + previous parameter, rather than just add it. This makes more sense for 99% of + the cases. +* BC Break: lib/Sabre.autoload.php is now removed in favor of + lib/Sabre/autoload.php. +* Deprecated: Sabre_DAV_Directory is now deprecated and will be removed in a + future version. Use Sabre_DAV_Collection instead. +* Deprecated: Sabre_DAV_SimpleDirectory is now deprecated and will be removed in + a future version. Use Sabre_DAV_SimpleCollection instead. +* Fixed: Problem with overriding tablenames for the CalDAV backend. +* Added: Clark-notation parser to XML utility. +* Added: unset() support to VObject components. +* Fixed: Refactored CalDAV property fetching to be faster and simpler. +* Added: Central string-matcher for CalDAV and CardDAV plugins. +* Added: i;unicode-casemap support +* Fixed: VObject bug: wouldn't parse parameters if they weren't specified in + uppercase. +* Fixed: VObject bug: Parameters now behave more like Properties. +* Fixed: VObject bug: Parameters with no value are now correctly parsed. +* Changed: If calendars don't specify which components they allow, 'all' + components are assumed (e.g.: VEVENT, VTODO, VJOURNAL). +* Changed: Browser plugin now uses POST variable 'sabreAction' instead of + 'action' to reduce the chance of collisions. + + +1.4.4 (2011-07-07) +------------------ + +* Fixed: Issue 131: Custom CalDAV backends could break in certain cases. +* Added: The option to override the default tablename all PDO backends use. + (Issue 60). +* Fixed: Issue 124: 'File' authentication backend now takes realm into + consideration. +* Fixed: Sabre_DAV_Property_HrefList now properly deserializes. This allows + users to update the {DAV:}group-member-set property. +* Added: Helper functions for DateTime-values in Sabre_VObject package. +* Added: VObject library can now automatically map iCalendar properties to + custom classes. + + +1.4.3 (2011-04-25) +------------------ + +* Fixed: Issue 123: Added workaround for Windows 7 UNLOCK bug. +* Fixed: datatype of lastmodified field in mysql.calendars.sql. Please change + the DATETIME field to an INT to ensure this field will work correctly. +* Change: Sabre_DAV_Property_Principal is now renamed to + Sabre_DAVACL_Property_Principal. +* Added: API level support for ACL HTTP method. +* Fixed: Bug in serializing {DAV:}acl property. +* Added: deserializer for {DAV:}resourcetype property. +* Added: deserializer for {DAV:}acl property. +* Added: deserializer for {DAV:}principal property. + + +1.4.2-beta (2011-04-01) +----------------------- + +* Added: It's not possible to disable listing of nodes that are denied read + access by ACL. +* Fixed: Changed a few properties in CalDAV classes from private to protected. +* Fixed: Issue 119: Terrible things could happen when relying on guessBaseUri, + the server was running on the root of the domain and a user tried to access a + file ending in .php. This is a slight BC break. +* Fixed: Issue 118: Lock tokens in If headers without a uri should be treated as + the request uri, not 'all relevant uri's. +* Fixed: Issue 120: PDO backend was incorrectly fetching too much locks in cases + where there were similar named locked files in a directory. + + +1.4.1-beta (2011-02-26) +----------------------- + +* Fixed: Sabre_DAV_Locks_Backend_PDO returned too many locks. +* Fixed: Sabre_HTTP_Request::getHeader didn't return Content-Type when running + on apache, so a few workarounds were added. +* Change: Slightly changed CalDAV Backend API's, to allow for heavy + optimizations. This is non-bc breaking. + + +1.4.0-beta (2011-02-12) +----------------------- + +* Added: Partly RFC3744 ACL support. +* Added: Calendar-delegation (caldav-proxy) support. +* BC break: In order to fix Issue 99, a new argument had to be added to + Sabre_DAV_Locks_Backend_*::getLocks classes. Consult the classes for details. +* Deprecated: Sabre_DAV_Locks_Backend_FS is now deprecated and will be removed + in a later version. Use PDO or the new File class instead. +* Deprecated: The Sabre_CalDAV_ICalendarUtil class is now marked deprecated, and + will be removed in a future version. Please use Sabre_VObject instead. +* Removed: All principal-related functionality has been removed from the + Sabre_DAV_Auth_Plugin, and moved to the Sabre_DAVACL_Plugin. +* Added: VObject library, for easy vcard/icalendar parsing using a natural + interface. +* Added: Ability to automatically generate full .ics feeds off calendars. To + use: Add the Sabre_CalDAV_ICSExportPlugin, and add ?export to your calendar + url. +* Added: Plugins can now specify a pluginname, for easy access using + Sabre_DAV_Server::getPlugin(). +* Added: beforeGetProperties event. +* Added: updateProperties event. +* Added: Principal listings and calendar-access can now be done privately, + disallowing users from accessing or modifying other users' data. +* Added: You can now pass arrays to the Sabre_DAV_Server constructor. If it's an + array with node-objects, a Root collection will automatically be created, and + the nodes are used as top-level children. +* Added: The principal base uri is now customizable. It used to be hardcoded to + 'principals/[user]'. +* Added: getSupportedReportSet method in ServerPlugin class. This allows you to + easily specify which reports you're implementing. +* Added: A '..' link to the HTML browser. +* Fixed: Issue 99: Locks on child elements were ignored when their parent nodes + were deleted. +* Fixed: Issue 90: lockdiscovery property and LOCK response now include a + {DAV}lockroot element. +* Fixed: Issue 96: support for 'default' collation in CalDAV text-match filters. +* Fixed: Issue 102: Ensuring that copy and move with identical source and + destination uri's fails. +* Fixed: Issue 105: Supporting MKCALENDAR with no body. +* Fixed: Issue 109: Small fixes in Sabre_HTTP_Util. +* Fixed: Issue 111: Properly catching the ownername in a lock (if it's a string) +* Fixed: Sabre_DAV_ObjectTree::nodeExist always returned false for the root + node. +* Added: Global way to easily supply new resourcetypes for certain node classes. +* Fixed: Issue 59: Allowing the user to override the authentication realm in + Sabre_CalDAV_Server. +* Update: Issue 97: Looser time-range checking if there's a recurrence rule in + an event. This fixes 'missing recurring events'. + + +1.3.0 (2010-10-14) +------------------ + +* Added: childExists method to Sabre_DAV_ICollection. This is an api break, so + if you implement Sabre_DAV_ICollection directly, add the method. +* Changed: Almost all HTTP method implementations now take a uri argument, + including events. This allows for internal rerouting of certain calls. If you + have custom plugins, make sure they use this argument. If they don't, they + will likely still work, but it might get in the way of future changes. +* Changed: All getETag methods MUST now surround the etag with double-quotes. + This was a mistake made in all previous SabreDAV versions. If you don't do + this, any If-Match, If-None-Match and If: headers using Etags will work + incorrectly. (Issue 85). +* Added: Sabre_DAV_Auth_Backend_AbstractBasic class, which can be used to easily + implement basic authentication. +* Removed: Sabre_DAV_PermissionDenied class. Use Sabre_DAV_Forbidden instead. +* Removed: Sabre_DAV_IDirectory interface, use Sabre_DAV_ICollection instead. +* Added: Browser plugin now uses {DAV:}displayname if this property is + available. +* Added: Cache layer in the ObjectTree. +* Added: Tree classes now have a delete and getChildren method. +* Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if the + date is an exact match. +* Fixed: Support for multiple ETags in If-Match and If-None-Match headers. +* Fixed: Improved baseUrl handling. +* Fixed: Issue 67: Non-seekable stream support in ::put()/::get(). +* Fixed: Issue 65: Invalid dates are now ignored. +* Updated: Refactoring in Sabre_CalDAV to make everything a bit more ledgable. +* Fixed: Issue 88, Issue 89: Fixed compatibility for running SabreDAV on + Windows. +* Fixed: Issue 86: Fixed Content-Range top-boundary from 'file size' to 'file + size'-1. + + +1.2.5 (2010-08-18) +------------------ + +* Fixed: Issue 73: guessBaseUrl fails for some servers. +* Fixed: Issue 67: SabreDAV works better with non-seekable streams. +* Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if + the date is an exact match. + + +1.2.4 (2010-07-13) +------------------ + +* Fixed: Issue 62: Guessing baseUrl fails when url contains a query-string. +* Added: Apache configuration sample for CGI/FastCGI setups. +* Fixed: Issue 64: Only returning calendar-data when it was actually requested. + + +1.2.3 (2010-06-26) +------------------ + +* Fixed: Issue 57: Supporting quotes around etags in If-Match and If-None-Match + + +1.2.2 (2010-06-21) +------------------ + +* Updated: SabreDAV now attempts to guess the BaseURI if it's not set. +* Updated: Better compatibility with BitKinex +* Fixed: Issue 56: Incorrect behaviour for If-None-Match headers and GET + requests. +* Fixed: Issue with certain encoded paths in Browser Plugin. + + +1.2.1 (2010-06-07) +------------------ + +* Fixed: Issue 50, patch by Mattijs Hoitink. +* Fixed: Issue 51, Adding windows 7 lockfiles to TemporaryFileFilter. +* Fixed: Issue 38, Allowing custom filters to be added to TemporaryFileFilter. +* Fixed: Issue 53, ETags in the If: header were always failing. This behaviour + is now corrected. +* Added: Apache Authentication backend, in case authentication through .htaccess + is desired. +* Updated: Small improvements to example files. + + +1.2.0 (2010-05-24) +------------------ + +* Fixed: Browser plugin now displays international characters. +* Changed: More properties in CalDAV classes are now protected instead of + private. + + +1.2.0beta3 (2010-05-14) +----------------------- + +* Fixed: Custom properties were not properly sent back for allprops requests. +* Fixed: Issue 49, incorrect parsing of PROPPATCH, affecting Office 2007. +* Changed: Removed CalDAV items from includes.php, and added a few missing ones. + + +1.2.0beta2 (2010-05-04) +----------------------- + +* Fixed: Issue 46: Fatal error for some non-existent nodes. +* Updated: some example sql to include email address. +* Added: 208 and 508 statuscodes from RFC5842. +* Added: Apache2 configuration examples + + +1.2.0beta1 (2010-04-28) +----------------------- + +* Fixed: redundant namespace declaration in resourcetypes. +* Fixed: 2 locking bugs triggered by litmus when no Sabre_DAV_ILockable + interface is used. +* Changed: using http://sabredav.org/ns for all custom xml properties. +* Added: email address property to principals. +* Updated: CalendarObject validation. + + +1.2.0alpha4 (2010-04-24) +------------------------ + +* Added: Support for If-Range, If-Match, If-None-Match, If-Modified-Since, + If-Unmodified-Since. +* Changed: Brand new build system. Functionality is split up between Sabre, + Sabre_HTTP, Sabre_DAV and Sabre_CalDAV packages. In addition to that a new + non-pear package will be created with all this functionality combined. +* Changed: Autoloader moved to Sabre/autoload.php. +* Changed: The Allow: header is now more accurate, with appropriate HTTP methods + per uri. +* Changed: Now throwing back Sabre_DAV_Exception_MethodNotAllowed on a few + places where Sabre_DAV_Exception_NotImplemented was used. + + +1.2.0alpha3 (2010-04-20) +------------------------ + +* Update: Complete rewrite of property updating. Now easier to use and atomic. +* Fixed: Issue 16, automatically adding trailing / to baseUri. +* Added: text/plain is used for .txt files in GuessContentType plugin. +* Added: support for principal-property-search and principal-search-property-set + reports. +* Added: Issue 31: Hiding exception information by default. Can be turned on + with the Sabre_DAV_Server::$debugExceptions property. + + +1.2.0alpha2 (2010-04-08) +------------------------ + +* Added: Calendars are now private and can only be read by the owner. +* Fixed: double namespace declaration in multistatus responses. +* Added: MySQL database dumps. MySQL is now also supported next to SQLite. +* Added: expand-properties REPORT from RFC 3253. +* Added: Sabre_DAV_Property_IHref interface for properties exposing urls. +* Added: Issue 25: Throwing error on broken Finder behaviour. +* Changed: Authentication backend is now aware of current user. + + +1.2.0alpha1 (2010-03-31) +------------------------ + +* Fixed: Issue 26: Workaround for broken GVFS behaviour with encoded special + characters. +* Fixed: Issue 34: Incorrect Lock-Token response header for LOCK. Fixes Office + 2010 compatibility. +* Added: Issue 35: SabreDAV version to header to OPTIONS response to ease + debugging. +* Fixed: Issue 36: Incorrect variable name, throwing error in some requests. +* Fixed: Issue 37: Incorrect smultron regex in temporary filefilter. +* Fixed: Issue 33: Converting ISO-8859-1 characters to UTF-8. +* Fixed: Issue 39 & Issue 40: Basename fails on non-utf-8 locales. +* Added: More unittests. +* Added: SabreDAV version to all error responses. +* Added: URLUtil class for decoding urls. +* Changed: Now using pear.sabredav.org pear channel. +* Changed: Sabre_DAV_Server::getCopyAndMoveInfo is now a public method. + + +1.1.2-alpha (2010-03-18) +------------------------ + +* Added: RFC5397 - current-user-principal support. +* Fixed: Issue 27: encoding entities in property responses. +* Added: naturalselection script now allows the user to specify a 'minimum + number of bytes' for deletion. This should reduce load due to less crawling +* Added: Full support for the calendar-query report. +* Added: More unittests. +* Added: Support for complex property deserialization through the static + ::unserialize() method. +* Added: Support for modifying calendar-component-set +* Fixed: Issue 29: Added TIMEOUT_INFINITE constant + + +1.1.1-alpha (2010-03-11) +------------------------ + +* Added: RFC5689 - Extended MKCOL support. +* Fixed: Evolution support for CalDAV. +* Fixed: PDO-locks backend was pretty much completely broken. This is 100% + unittested now. +* Added: support for ctags. +* Fixed: Comma's between HTTP methods in 'Allow' method. +* Changed: default argument for Sabre_DAV_Locks_Backend_FS. This means a + datadirectory must always be specified from now on. +* Changed: Moved Sabre_DAV_Server::parseProps to + Sabre_DAV_XMLUtil::parseProperties. +* Changed: Sabre_DAV_IDirectory is now Sabre_DAV_ICollection. +* Changed: Sabre_DAV_Exception_PermissionDenied is now + Sabre_DAV_Exception_Forbidden. +* Changed: Sabre_CalDAV_ICalendarCollection is removed. +* Added: Sabre_DAV_IExtendedCollection. +* Added: Many more unittests. +* Added: support for calendar-timezone property. + + +1.1.0-alpha (2010-03-01) +------------------------ + +* Note: This version is forked from version 1.0.5, so release dates may be out + of order. +* Added: CalDAV - RFC 4791 +* Removed: Sabre_PHP_Exception. PHP has a built-in ErrorException for this. +* Added: PDO authentication backend. +* Added: Example sql for auth, caldav, locks for sqlite. +* Added: Sabre_DAV_Browser_GuessContentType plugin +* Changed: Authentication plugin refactored, making it possible to implement + non-digest authentication. +* Fixed: Better error display in browser plugin. +* Added: Support for {DAV:}supported-report-set +* Added: XML utility class with helper functions for the WebDAV protocol. +* Added: Tons of unittests +* Added: PrincipalCollection and Principal classes +* Added: Sabre_DAV_Server::getProperties for easy property retrieval +* Changed: {DAV:}resourceType defaults to 0 +* Changed: Any non-null resourceType now gets a / appended to the href value. + Before this was just for {DAV:}collection's, but this is now also the case for + for example {DAV:}principal. +* Changed: The Href property class can now optionally create non-relative uri's. +* Changed: Sabre_HTTP_Response now returns false if headers are already sent and + header-methods are called. +* Fixed: Issue 19: HEAD requests on Collections +* Fixed: Issue 21: Typo in Sabre_DAV_Property_Response +* Fixed: Issue 18: Doesn't work with Evolution Contacts + + +1.0.15 (2010-05-28) +------------------- + +* Added: Issue 31: Hiding exception information by default. Can be turned on + with the Sabre_DAV_Server::$debugExceptions property. +* Added: Moved autoload from lib/ to lib/Sabre/autoload.php. This is also the + case in the upcoming 1.2.0, so it will improve future compatibility. + + +1.0.14 (2010-04-15) +------------------- + +* Fixed: double namespace declaration in multistatus responses. + + +1.0.13 (2010-03-30) +------------------- + +* Fixed: Issue 40: Last references to basename/dirname + + +1.0.12 (2010-03-30) +------------------- + +* Fixed: Issue 37: Incorrect smultron regex in temporary filefilter. +* Fixed: Issue 26: Workaround for broken GVFS behaviour with encoded special + characters. +* Fixed: Issue 33: Converting ISO-8859-1 characters to UTF-8. +* Fixed: Issue 39: Basename fails on non-utf-8 locales. +* Added: More unittests. +* Added: SabreDAV version to all error responses. +* Added: URLUtil class for decoding urls. +* Updated: Now using pear.sabredav.org pear channel. + + +1.0.11 (2010-03-23) +------------------- + +* Non-public release. This release is identical to 1.0.10, but it is used to + test releasing packages to pear.sabredav.org. + + +1.0.10 (2010-03-22) +------------------- + +* Fixed: Issue 34: Invalid Lock-Token header response. +* Added: Issue 35: Addign SabreDAV version to HTTP OPTIONS responses. + + +1.0.9 (2010-03-19) +------------------ + +* Fixed: Issue 27: Entities not being encoded in PROPFIND responses. +* Fixed: Issue 29: Added missing TIMEOUT_INFINITE constant. + + +1.0.8 (2010-03-03) +------------------ + +* Fixed: Issue 21: typos causing errors +* Fixed: Issue 23: Comma's between methods in Allow header. +* Added: Sabre_DAV_ICollection interface, to aid in future compatibility. +* Added: Sabre_DAV_Exception_Forbidden exception. This will replace + Sabre_DAV_Exception_PermissionDenied in the future, and can already be used to + ensure future compatibility. + + +1.0.7 (2010-02-24) +------------------ + +* Fixed: Issue 19 regression for MS Office + + +1.0.6 (2010-02-23) +------------------ + +* Fixed: Issue 19: HEAD requests on Collections + + +1.0.5 (2010-01-22) +------------------ + +* Fixed: Fatal error when a malformed url was used for unlocking, in conjuction + with Sabre.autoload.php due to a incorrect filename. +* Fixed: Improved unittests and build system + + +1.0.4 (2010-01-11) +------------------ + +* Fixed: needed 2 different releases. One for googlecode and one for pearfarm. + This is to retain the old method to install SabreDAV until pearfarm becomes + the standard installation method. + + +1.0.3 (2010-01-11) +------------------ + +* Added: RFC4709 support (davmount) +* Added: 6 unittests +* Added: naturalselection. A tool to keep cache directories below a specified + theshold. +* Changed: Now using pearfarm.org channel server. + + +1.0.1 (2009-12-22) +------------------ + +* Fixed: Issue 15: typos in examples +* Fixed: Minor pear installation issues + + +1.0.0 (2009-11-02) +------------------ + +* Added: SimpleDirectory class. This class allows creating static directory + structures with ease. +* Changed: Custom complex properties and exceptions now get an instance of + Sabre_DAV_Server as their first argument in serialize() +* Changed: Href complex property now prepends server's baseUri +* Changed: delete before an overwriting copy/move is now handles by server class + instead of tree classes +* Changed: events must now explicitly return false to stop execution. Before, + execution would be stopped by anything loosely evaluating to false. +* Changed: the getPropertiesForPath method now takes a different set of + arguments, and returns a different response. This allows plugin developers to + return statuses for properties other than 200 and 404. The hrefs are now also + always calculated relative to the baseUri, and not the uri of the request. +* Changed: generatePropFindResponse is renamed to generateMultiStatus, and now + takes a list of properties similar to the response of getPropertiesForPath. + This was also needed to improve flexibility for plugin development. +* Changed: Auth plugins are no longer included. They were not yet stable + quality, so they will probably be reintroduced in a later version. +* Changed: PROPPATCH also used generateMultiStatus now. +* Removed: unknownProperties event. This is replaced by the afterGetProperties + event, which should provide more flexibility. +* Fixed: Only calling getSize() on IFile instances in httpHead() +* Added: beforeBind event. This is invoked upon file or directory creation +* Added: beforeWriteContent event, this is invoked by PUT and LOCK on an + existing resource. +* Added: beforeUnbind event. This is invoked right before deletion of any + resource. +* Added: afterGetProperties event. This event can be used to make modifications + to property responses. +* Added: beforeLock and beforeUnlock events. +* Added: afterBind event. +* Fixed: Copy and Move could fail in the root directory. This is now fixed. +* Added: Plugins can now be retrieved by their classname. This is useful for + inter-plugin communication. +* Added: The Auth backend can now return usernames and user-id's. +* Added: The Auth backend got a getUsers method +* Added: Sabre_DAV_FSExt_Directory now returns quota info + + +0.12.1-beta (2009-09-11) +------------------------ + +* Fixed: UNLOCK bug. Unlock didn't work at all + + +0.12-beta (2009-09-10) +---------------------- + +* Updated: Browser plugin now shows multiple {DAV:}resourcetype values if + available. +* Added: Experimental PDO backend for Locks Manager +* Fixed: Sending Content-Length: 0 for every empty response. This improves NGinx + compatibility. +* Fixed: Last modification time is reported in UTC timezone. This improves + Finder compatibility. + + +0.11-beta (2009-08-11) +---------------------- + +* Updated: Now in Beta +* Updated: Pear package no longer includes docs/ directory. These just contained + rfc's, which are publicly available. This reduces the package from ~800k to + ~60k +* Added: generatePropfindResponse now takes a baseUri argument +* Added: ResourceType property can now contain multiple resourcetypes. +* Fixed: Issue 13. + + +0.10-alpha (2009-08-03) +----------------------- + +* Added: Plugin to automatically map GET requests to non-files to PROPFIND + (Sabre_DAV_Browser_MapGetToPropFind). This should allow easier debugging of + complicated WebDAV setups. +* Added: Sabre_DAV_Property_Href class. For future use. +* Added: Ability to choose to use auth-int, auth or both for HTTP Digest + authentication. (Issue 11) +* Changed: Made more methods in Sabre_DAV_Server public. +* Fixed: TemporaryFileFilter plugin now intercepts HTTP LOCK requests to + non-existent files. (Issue 12) +* Added: Central list of defined xml namespace prefixes. This can reduce + Bandwidth and legibility for xml bodies with user-defined namespaces. +* Added: now a PEAR-compatible package again, thanks to Michael Gauthier +* Changed: moved default copy and move logic from ObjectTree to Tree class + +0.9a-alpha (2009-07-21) +---------------------- + +* Fixed: Broken release + +0.9-alpha (2009-07-21) +---------------------- + +* Changed: Major refactoring, removed most of the logic from the Tree objects. + The Server class now directly works with the INode, IFile and IDirectory + objects. If you created your own Tree objects, this will most likely break in + this release. +* Changed: Moved all the Locking logic from the Tree and Server classes into a + separate plugin. +* Changed: TemporaryFileFilter is now a plugin. +* Added: Comes with an autoloader script. This can be used instead of the + includer script, and is preferred by some people. +* Added: AWS Authentication class. +* Added: simpleserversetup.py script. This will quickly get a fileserver up and + running. +* Added: When subscribing to events, it is now possible to supply a priority. + This is for example needed to ensure that the Authentication Plugin is used + before any other Plugin. +* Added: 22 new tests. +* Added: Users-manager plugin for .htdigest files. Experimental and subject to + change. +* Added: RFC 2324 HTTP 418 status code +* Fixed: Exclusive locks could in some cases be picked up as shared locks +* Fixed: Digest auth for non-apache servers had a bug (still not actually tested + this well). + + +0.8-alpha (2009-05-30) +---------------------- + +* Changed: Renamed all exceptions! This is a compatibility break. Every + Exception now follows Sabre_DAV_Exception_FileNotFound convention instead of + Sabre_DAV_FileNotFoundException. +* Added: Browser plugin now allows uploading and creating directories straight + from the browser. +* Added: 12 more unittests +* Fixed: Locking bug, which became prevalent on Windows Vista. +* Fixed: Netdrive support +* Fixed: TemporaryFileFilter filtered out too many files. Fixed some of the + regexes. +* Fixed: Added README and ChangeLog to package + + +0.7-alpha (2009-03-29) +---------------------- + +* Added: System to return complex properties from PROPFIND. +* Added: support for {DAV:}supportedlock. +* Added: support for {DAV:}lockdiscovery. +* Added: 6 new tests. +* Added: New plugin system. +* Added: Simple HTML directory plugin, for browser access. +* Added: Server class now sends back standard pre-condition error xml bodies. + This was new since RFC4918. +* Added: Sabre_DAV_Tree_Aggregrate, which can 'host' multiple Tree objects into + one. +* Added: simple basis for HTTP REPORT method. This method is not used yet, but + can be used by plugins to add reports. +* Changed: ->getSize is only called for files, no longer for collections. r303 +* Changed: Sabre_DAV_FilterTree is now Sabre_DAV_Tree_Filter +* Changed: Sabre_DAV_TemporaryFileFilter is now called + Sabre_DAV_Tree_TemporaryFileFilter. +* Changed: removed functions (get(/set)HTTPRequest(/Response)) from Server + class, and using a public property instead. +* Fixed: bug related to parsing proppatch and propfind requests. Didn't show up + in most clients, but it needed fixing regardless. (r255) +* Fixed: auth-int is now properly supported within HTTP Digest. +* Fixed: Using application/xml for a mimetype vs. text/xml as per RFC4918 sec + 8.2. +* Fixed: TemporaryFileFilter now lets through GET's if they actually exist on + the backend. (r274) +* FIxed: Some methods didn't get passed through in the FilterTree (r283). +* Fixed: LockManager is now slightly more complex, Tree classes slightly less. + (r287) + + +0.6-alpha (2009-02-16) +---------------------- + +* Added: Now uses streams for files, instead of strings. This means it won't + require to hold entire files in memory, which can be an issue if you're + dealing with big files. Note that this breaks compatibility for put() and + createFile methods. +* Added: HTTP Digest Authentication helper class. +* Added: Support for HTTP Range header +* Added: Support for ETags within If: headers +* Added: The API can now return ETags and override the default Content-Type +* Added: starting with basic framework for unittesting, using PHPUnit. +* Added: 49 unittests. +* Added: Abstraction for the HTTP request. +* Updated: Using Clark Notation for tags in properties. This means tags are + serialized as {namespace}tagName instead of namespace#tagName +* Fixed: HTTP_BasicAuth class now works as expected. +* Fixed: DAV_Server uses / for a default baseUrl. +* Fixed: Last modification date is no longer ignored in PROPFIND. +* Fixed: PROPFIND now sends back information about the requestUri even when + "Depth: 1" is specified. + + +0.5-alpha (2009-01-14) +---------------------- + +* Added: Added a very simple example for implementing a mapping to PHP file + streams. This should allow easy implementation of for example a WebDAV to FTP + proxy. +* Added: HTTP Basic Authentication helper class. +* Added: Sabre_HTTP_Response class. This centralizes HTTP operations and will be + a start towards the creating of a testing framework. +* Updated: Backwards compatibility break: all require_once() statements are + removed from all the files. It is now recommended to use autoloading of + classes, or just including lib/Sabre.includes.php. This fix was made to allow + easier integration into applications not using this standard inclusion model. +* Updated: Better in-file documentation. +* Updated: Sabre_DAV_Tree can now work with Sabre_DAV_LockManager. +* Updated: Fixes a shared-lock bug. +* Updated: Removed ?> from the bottom of each php file. +* Updated: Split up some operations from Sabre_DAV_Server to + Sabre_HTTP_Response. +* Fixed: examples are now actually included in the pear package. + + +0.4-alpha (2008-11-05) +---------------------- + +* Passes all litmus tests! +* Added: more examples +* Added: Custom property support +* Added: Shared lock support +* Added: Depth support to locks +* Added: Locking on unmapped urls (non-existent nodes) +* Fixed: Advertising as WebDAV class 3 support + + +0.3-alpha (2008-06-29) +---------------------- + +* Fully working in MS Windows clients. +* Added: temporary file filter: support for smultron files. +* Added: Phing build scripts +* Added: PEAR package +* Fixed: MOVE bug identified using finder. +* Fixed: Using gzuncompress instead of gzdecode in the temporary file filter. + This seems more common. + + +0.2-alpha (2008-05-27) +---------------------- + +* Somewhat working in Windows clients +* Added: Working PROPPATCH method (doesn't support custom properties yet) +* Added: Temporary filename handling system +* Added: Sabre_DAV_IQuota to return quota information +* Added: PROPFIND now reads the request body and only supplies the requested + properties + + +0.1-alpha (2008-04-04) +---------------------- + +* First release! +* Passes litmus: basic, http and copymove test. +* Fully working in Finder and DavFS2. + +Project started: 2007-12-13 + +[vobj]: http://sabre.io/vobject/ +[evnt]: http://sabre.io/event/ +[http]: http://sabre.io/http/ +[uri]: http://sabre.io/uri/ +[xml]: http://sabre.io/xml/ +[mi20]: http://sabre.io/dav/upgrade/1.8-to-2.0/ +[rfc6638]: http://tools.ietf.org/html/rfc6638 "CalDAV Scheduling" +[rfc7240]: http://tools.ietf.org/html/rfc7240 +[calendar-availability]: https://tools.ietf.org/html/draft-daboo-calendar-availability-05 diff --git a/vendor/sabre/dav/LICENSE b/vendor/sabre/dav/LICENSE new file mode 100644 index 000000000..fd3539e33 --- /dev/null +++ b/vendor/sabre/dav/LICENSE @@ -0,0 +1,27 @@ +Copyright (C) 2007-2016 fruux GmbH (https://fruux.com/). + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of SabreDAV nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sabre/dav/README.md b/vendor/sabre/dav/README.md new file mode 100644 index 000000000..8edcd4073 --- /dev/null +++ b/vendor/sabre/dav/README.md @@ -0,0 +1,36 @@ +![sabre's logo](http://sabre.io/img/logo.png) sabre/dav +======================================================= + +Introduction +------------ + +sabre/dav is the most popular WebDAV framework for PHP. Use it to create WebDAV, CalDAV and CardDAV servers. + +Full documentation can be found on the website: + +http://sabre.io/ + +Build status +------------ + +| branch | status | minimum PHP version | +| ------------ | ------ | ------------------- | +| master | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=master)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 | +| 3.1 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=3.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 | +| 3.0 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=3.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | +| 2.1 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=2.1)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | +| 2.0 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=2.0)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 | +| 1.8 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.8)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | +| 1.7 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.7)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | +| 1.6 | [![Build Status](https://travis-ci.org/fruux/sabre-dav.svg?branch=1.6)](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 | + +Documentation +------------- + +* [Introduction](http://sabre.io/dav/). +* [Installation](http://sabre.io/dav/install/). + +Made at fruux +------------- + +SabreDAV is being developed by [fruux](https://fruux.com/). Drop us a line for commercial services or enterprise support. diff --git a/vendor/sabre/dav/bin/build.php b/vendor/sabre/dav/bin/build.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/googlecode_upload.py b/vendor/sabre/dav/bin/googlecode_upload.py old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/migrateto20.php b/vendor/sabre/dav/bin/migrateto20.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/migrateto21.php b/vendor/sabre/dav/bin/migrateto21.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/migrateto30.php b/vendor/sabre/dav/bin/migrateto30.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/migrateto32.php b/vendor/sabre/dav/bin/migrateto32.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/sabredav.php b/vendor/sabre/dav/bin/sabredav.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/vobject/bin/bench.php b/vendor/sabre/vobject/bin/bench.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/vobject/bin/fetch_windows_zones.php b/vendor/sabre/vobject/bin/fetch_windows_zones.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/vobject/bin/generateicalendardata.php b/vendor/sabre/vobject/bin/generateicalendardata.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/vobject/bin/mergeduplicates.php b/vendor/sabre/vobject/bin/mergeduplicates.php old mode 100755 new mode 100644 -- cgit v1.2.3 From 85e82e919e146454a8b3973ed4a2a69066b98aa3 Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Thu, 9 Jun 2016 22:05:52 +0200 Subject: more style work --- include/attach.php | 2 +- view/theme/redbasic/css/style.css | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/attach.php b/include/attach.php index 78efde51f..17e5067ff 100644 --- a/include/attach.php +++ b/include/attach.php @@ -1903,4 +1903,4 @@ function get_attach_binname($s) { $p = substr($p,strpos($p,'/')+1); } return $p; -} \ No newline at end of file +} diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index ae2826516..6510fb525 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1138,10 +1138,20 @@ margin-right: 50px; list-style-type: none; } +.generic-icons { + font-size: 1.2em; + color: $toolicon_colour; + margin-right: 7px; +} + +.generic-icons:hover { + color: $toolicon_colour; +} + .admin-icons { font-size: 1.2em; color: $toolicon_colour; - margin-right: 10px; + margin-right: 7px; } a .drop-icons { -- cgit v1.2.3 From b6d425838f9025d8faf6dbfe90fce091d94b3cd7 Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Mon, 13 Jun 2016 17:19:49 +0200 Subject: css fixes --- view/theme/redbasic/css/style.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index 9e2a0431b..5768ccbd9 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1152,12 +1152,15 @@ margin-right: 50px; margin-right: 7px; } +.drop-icons, a .drop-icons { color: $toolicon_colour; font-size: 1.2em; text-decoration: none; + cursor: pointer; } - + +.drop-icons:hover, a .drop-icons:hover { color: #FF0000; } -- cgit v1.2.3 From 24569a18dbb423f47429905cb38282813b0a6462 Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Tue, 14 Jun 2016 23:21:26 +0200 Subject: css fix --- view/css/widgets.css | 1 + 1 file changed, 1 insertion(+) diff --git a/view/css/widgets.css b/view/css/widgets.css index 38809896c..2a7c57f53 100644 --- a/view/css/widgets.css +++ b/view/css/widgets.css @@ -11,6 +11,7 @@ width: 100%; border-top-right-radius: 0px; border-bottom-right-radius: 0px; + border-right: 0px; } .tags { -- cgit v1.2.3 From 7a4efcf67f57d6437af5596ad99920c1793cf450 Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Sun, 19 Jun 2016 20:34:38 +0200 Subject: return something so we can make a conclusion --- view/js/main.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/view/js/main.js b/view/js/main.js index f279417d9..2caf5a1dd 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -941,6 +941,11 @@ function dropItem(url, object) { $('body').css('cursor', 'auto'); }); }); + return true; + + } + else { + return false; } } -- cgit v1.2.3 From e2de2f65d5f434f800ac9fb6b824f9cbb5f860e8 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Sun, 26 Jun 2016 20:15:42 -0700 Subject: issue #442, tables contain too much whitespace (there's a definite issue here, but I should note the offending example was full of carriage returns as well as linefeeds; which exacerbated the problem). --- include/bbcode.php | 14 +++++++++++++- include/network.php | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/include/bbcode.php b/include/bbcode.php index 0bf326506..7f7be4300 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -498,6 +498,18 @@ function bb_highlight($match) { return $match[0]; } +function bb_fixtable_lf($match) { + + // remove extraneous whitespace between table element tags since newlines will all + // be converted to '<br />' and turn your neatly crafted tables into a whole lot of + // empty space. + + $x = preg_replace("/\]\s+\[/",'][',$match[1]); + return '[table]' . $x . '[/table]'; + +} + + // BBcode 2 HTML was written by WAY2WEB.net // extended to work with Mistpark/Friendica/Redmatrix/Hubzilla - Mike Macgirvin @@ -579,7 +591,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) $Text = preg_replace_callback("/\[code=(.*?)\](.*?)\[\/code\]/ism", 'bb_highlight', $Text); } - + $Text = preg_replace_callback("/\[table\](.*?)\[\/table\]/ism",'bb_fixtable_lf',$Text); // Convert new line chars to html <br /> tags diff --git a/include/network.php b/include/network.php index 91dac936e..96bf714f6 100644 --- a/include/network.php +++ b/include/network.php @@ -1336,8 +1336,20 @@ function discover_by_webbie($webbie) { $fullname = $vcard['fn']; if($vcard['photo'] && (strpos($vcard['photo'],'http') !== 0)) $vcard['photo'] = $diaspora_base . '/' . $vcard['photo']; + if(($vcard['key']) && (! $pubkey)) + $pubkey = $vcard['key']; if(! $avatar) $avatar = $vcard['photo']; + if($diaspora) { + if(($vcard['guid']) && (! $diaspora_guid)) + $diaspora_guid = $vcard['guid']; + if(($vcard['url']) && (! $diaspora_base)) + $diaspora_base = $vcard['url']; + + + + + } } } -- cgit v1.2.3 From 2029b2b9ed0544d4559d7a918a0902587fd580bc Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Sun, 26 Jun 2016 21:58:09 -0700 Subject: document the daemon classes --- Zotlabs/Daemon/README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Zotlabs/Daemon/README.md diff --git a/Zotlabs/Daemon/README.md b/Zotlabs/Daemon/README.md new file mode 100644 index 000000000..cb5b00a56 --- /dev/null +++ b/Zotlabs/Daemon/README.md @@ -0,0 +1,43 @@ +Daemon (background) Processes +============================= + + +This directory provides background tasks which are executed by a +command-line process and detached from normal web processing. + +Background tasks are invoked by calling + + + Zotlabs\Daemon\Master::Summon([ $cmd, $arg1, $argn... ]); + +The Master class loads the desired command file and passes the arguments. + + +To create a background task 'Foo' use the following template. + + <?php + + namespace Zotlabs\Daemon; + + class Foo { + + static public function run($argc,$argv) { + // do something + } + } + + +The Master class "summons" the command by creating an executable script +from the provided arguments, then it invokes "Release" to execute the script +detached from web processing. This process calls the static::run() function +with any command line arguments using the traditional argc, argv format. + +Please note: These are *real* $argc, $argv variables passed from the command +line, and not the parsed argc() and argv() functions/variables which were +obtained from parsing path components of the request URL by web processes. + +Background processes do not emit displayable output except through logs. They +should also not make any assumptions about their HTML and web environment +(as they do not have a web environment), particularly with respect to global +variables such as $_SERVER, $_REQUEST, $_GET, $_POST, $_COOKIES, and $_SESSION. + -- cgit v1.2.3 From 3035c792dcef91cd679034ee67eb2b28ed6f3d35 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Sun, 26 Jun 2016 22:13:59 -0700 Subject: remove the app $a passed to profile_load, also add profile_load to mod_wiki which should fix issue #431 --- Zotlabs/Module/Achievements.php | 2 +- Zotlabs/Module/Block.php | 2 +- Zotlabs/Module/Blocks.php | 2 +- Zotlabs/Module/Cal.php | 2 +- Zotlabs/Module/Channel.php | 2 +- Zotlabs/Module/Chat.php | 2 +- Zotlabs/Module/Cloud.php | 2 +- Zotlabs/Module/Common.php | 2 +- Zotlabs/Module/Connect.php | 2 +- Zotlabs/Module/Cover_photo.php | 2 +- Zotlabs/Module/Dav.php | 2 +- Zotlabs/Module/Editblock.php | 2 +- Zotlabs/Module/Editlayout.php | 2 +- Zotlabs/Module/Editwebpage.php | 2 +- Zotlabs/Module/Hcard.php | 2 +- Zotlabs/Module/Id.php | 2 +- Zotlabs/Module/Layouts.php | 2 +- Zotlabs/Module/Page.php | 2 +- Zotlabs/Module/Photos.php | 2 +- Zotlabs/Module/Profile.php | 2 +- Zotlabs/Module/Profile_photo.php | 2 +- Zotlabs/Module/Profiles.php | 4 ++-- Zotlabs/Module/Profperm.php | 2 +- Zotlabs/Module/Viewconnections.php | 2 +- Zotlabs/Module/Webpages.php | 2 +- Zotlabs/Module/Wiki.php | 2 ++ include/channel.php | 3 +-- 27 files changed, 29 insertions(+), 28 deletions(-) diff --git a/Zotlabs/Module/Achievements.php b/Zotlabs/Module/Achievements.php index 8ddefb3e5..1529448d3 100644 --- a/Zotlabs/Module/Achievements.php +++ b/Zotlabs/Module/Achievements.php @@ -18,7 +18,7 @@ class Achievements extends \Zotlabs\Web\Controller { $profile = 0; $profile = argv(1); - profile_load($a,$which,$profile); + profile_load($which,$profile); $r = q("select channel_id from channel where channel_address = '%s'", dbesc($which) diff --git a/Zotlabs/Module/Block.php b/Zotlabs/Module/Block.php index 45e61e4ea..e671730f6 100644 --- a/Zotlabs/Module/Block.php +++ b/Zotlabs/Module/Block.php @@ -12,7 +12,7 @@ class Block extends \Zotlabs\Web\Controller { $which = argv(1); $profile = 0; - profile_load($a,$which,$profile); + profile_load($which,$profile); if(\App::$profile['profile_uid']) head_set_icon(\App::$profile['thumb']); diff --git a/Zotlabs/Module/Blocks.php b/Zotlabs/Module/Blocks.php index 475cfa6b3..e6a97794d 100644 --- a/Zotlabs/Module/Blocks.php +++ b/Zotlabs/Module/Blocks.php @@ -22,7 +22,7 @@ class Blocks extends \Zotlabs\Web\Controller { else return; - profile_load($a,$which); + profile_load($which); } diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index 1da42684d..fd4169e68 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -20,7 +20,7 @@ class Cal extends \Zotlabs\Web\Controller { if(argc() > 1) { $nick = argv(1); - profile_load($a,$nick); + profile_load($nick); $channelx = channelx_by_nick($nick); diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 29bfcbc3c..d09388901 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -48,7 +48,7 @@ class Channel extends \Zotlabs\Web\Controller { // Run profile_load() here to make sure the theme is set before // we start loading content - profile_load($a,$which,$profile); + profile_load($which,$profile); } diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index 026e8369a..ff55a9319 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -39,7 +39,7 @@ class Chat extends \Zotlabs\Web\Controller { // Run profile_load() here to make sure the theme is set before // we start loading content - profile_load($a,$which,$profile); + profile_load($which,$profile); } diff --git a/Zotlabs/Module/Cloud.php b/Zotlabs/Module/Cloud.php index b691475ce..833b1b493 100644 --- a/Zotlabs/Module/Cloud.php +++ b/Zotlabs/Module/Cloud.php @@ -37,7 +37,7 @@ class Cloud extends \Zotlabs\Web\Controller { \App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n"; if ($which) - profile_load($a, $which, $profile); + profile_load( $which, $profile); $auth = new \Zotlabs\Storage\BasicAuth(); diff --git a/Zotlabs/Module/Common.php b/Zotlabs/Module/Common.php index 1c428d256..2f3c57267 100644 --- a/Zotlabs/Module/Common.php +++ b/Zotlabs/Module/Common.php @@ -21,7 +21,7 @@ class Common extends \Zotlabs\Web\Controller { ); if($x) - profile_load($a,$x[0]['channel_address'],0); + profile_load($x[0]['channel_address'],0); } diff --git a/Zotlabs/Module/Connect.php b/Zotlabs/Module/Connect.php index f68e0baac..962c05cce 100644 --- a/Zotlabs/Module/Connect.php +++ b/Zotlabs/Module/Connect.php @@ -26,7 +26,7 @@ class Connect extends \Zotlabs\Web\Controller { if($r) \App::$data['channel'] = $r[0]; - profile_load($a,$which,''); + profile_load($which,''); } function post() { diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php index 5633976c8..9887b8203 100644 --- a/Zotlabs/Module/Cover_photo.php +++ b/Zotlabs/Module/Cover_photo.php @@ -29,7 +29,7 @@ class Cover_photo extends \Zotlabs\Web\Controller { } $channel = \App::get_channel(); - profile_load($a,$channel['channel_address']); + profile_load($channel['channel_address']); } diff --git a/Zotlabs/Module/Dav.php b/Zotlabs/Module/Dav.php index 2fddabe19..6528e0271 100644 --- a/Zotlabs/Module/Dav.php +++ b/Zotlabs/Module/Dav.php @@ -58,7 +58,7 @@ class Dav extends \Zotlabs\Web\Controller { \App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n"; if ($which) - profile_load($a, $which, $profile); + profile_load( $which, $profile); diff --git a/Zotlabs/Module/Editblock.php b/Zotlabs/Module/Editblock.php index 1d6ef7a0a..6a9fa5f2d 100644 --- a/Zotlabs/Module/Editblock.php +++ b/Zotlabs/Module/Editblock.php @@ -21,7 +21,7 @@ class Editblock extends \Zotlabs\Web\Controller { else return; - profile_load($a,$which); + profile_load($which); } diff --git a/Zotlabs/Module/Editlayout.php b/Zotlabs/Module/Editlayout.php index fe794b5fd..26732dc77 100644 --- a/Zotlabs/Module/Editlayout.php +++ b/Zotlabs/Module/Editlayout.php @@ -21,7 +21,7 @@ class Editlayout extends \Zotlabs\Web\Controller { else return; - profile_load($a,$which); + profile_load($which); } diff --git a/Zotlabs/Module/Editwebpage.php b/Zotlabs/Module/Editwebpage.php index 6d67c08e7..5cd409e1e 100644 --- a/Zotlabs/Module/Editwebpage.php +++ b/Zotlabs/Module/Editwebpage.php @@ -23,7 +23,7 @@ class Editwebpage extends \Zotlabs\Web\Controller { else return; - profile_load($a,$which); + profile_load($which); } diff --git a/Zotlabs/Module/Hcard.php b/Zotlabs/Module/Hcard.php index 2636e676b..93c8d3ece 100644 --- a/Zotlabs/Module/Hcard.php +++ b/Zotlabs/Module/Hcard.php @@ -40,7 +40,7 @@ class Hcard extends \Zotlabs\Web\Controller { } } - profile_load($a,$which,$profile); + profile_load($which,$profile); } diff --git a/Zotlabs/Module/Id.php b/Zotlabs/Module/Id.php index 6a94b57f5..e053bf99c 100644 --- a/Zotlabs/Module/Id.php +++ b/Zotlabs/Module/Id.php @@ -57,7 +57,7 @@ class Id extends \Zotlabs\Web\Controller { $profile = ''; $channel = \App::get_channel(); - profile_load($a,$which,$profile); + profile_load($which,$profile); $op = new MysqlProvider; $op->server(); diff --git a/Zotlabs/Module/Layouts.php b/Zotlabs/Module/Layouts.php index a0b1c31cc..c07f65ce1 100644 --- a/Zotlabs/Module/Layouts.php +++ b/Zotlabs/Module/Layouts.php @@ -21,7 +21,7 @@ class Layouts extends \Zotlabs\Web\Controller { else return; - profile_load($a,$which); + profile_load($which); } diff --git a/Zotlabs/Module/Page.php b/Zotlabs/Module/Page.php index deb23da68..6ef285dd0 100644 --- a/Zotlabs/Module/Page.php +++ b/Zotlabs/Module/Page.php @@ -13,7 +13,7 @@ class Page extends \Zotlabs\Web\Controller { $which = argv(1); $profile = 0; - profile_load($a,$which,$profile); + profile_load($which,$profile); diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 1bdc23897..1633e08ef 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -27,7 +27,7 @@ class Photos extends \Zotlabs\Web\Controller { if(argc() > 1) { $nick = argv(1); - profile_load($a,$nick); + profile_load($nick); $channelx = channelx_by_nick($nick); diff --git a/Zotlabs/Module/Profile.php b/Zotlabs/Module/Profile.php index 8bf358bc8..9e868db92 100644 --- a/Zotlabs/Module/Profile.php +++ b/Zotlabs/Module/Profile.php @@ -48,7 +48,7 @@ class Profile extends \Zotlabs\Web\Controller { } } - profile_load($a,$which,$profile); + profile_load($which,$profile); } diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php index 72c92e721..62c5e99ae 100644 --- a/Zotlabs/Module/Profile_photo.php +++ b/Zotlabs/Module/Profile_photo.php @@ -34,7 +34,7 @@ class Profile_photo extends \Zotlabs\Web\Controller { } $channel = \App::get_channel(); - profile_load($a,$channel['channel_address']); + profile_load($channel['channel_address']); } diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php index 06e5cfd7b..899c79b15 100644 --- a/Zotlabs/Module/Profiles.php +++ b/Zotlabs/Module/Profiles.php @@ -193,7 +193,7 @@ class Profiles extends \Zotlabs\Web\Controller { $chan = \App::get_channel(); - profile_load($a,$chan['channel_address'],$r[0]['id']); + profile_load($chan['channel_address'],$r[0]['id']); } } @@ -584,7 +584,7 @@ class Profiles extends \Zotlabs\Web\Controller { if($is_default) { // reload the info for the sidebar widget - why does this not work? - profile_load($a,$channel['channel_address']); + profile_load($channel['channel_address']); \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel())); } } diff --git a/Zotlabs/Module/Profperm.php b/Zotlabs/Module/Profperm.php index 79ce7a7ed..b1da147c1 100644 --- a/Zotlabs/Module/Profperm.php +++ b/Zotlabs/Module/Profperm.php @@ -17,7 +17,7 @@ class Profperm extends \Zotlabs\Web\Controller { $profile = \App::$argv[1]; - profile_load($a,$which,$profile); + profile_load($which,$profile); } diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php index ea478f92a..7523c259b 100644 --- a/Zotlabs/Module/Viewconnections.php +++ b/Zotlabs/Module/Viewconnections.php @@ -11,7 +11,7 @@ class Viewconnections extends \Zotlabs\Web\Controller { return; } if(argc() > 1) - profile_load($a,argv(1)); + profile_load(argv(1)); } function get() { diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index fc292be6f..bb8d9c6ed 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -23,7 +23,7 @@ class Webpages extends \Zotlabs\Web\Controller { else return; - profile_load($a,$which); + profile_load($which); } diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index de5863d2e..6a8bdf0db 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -20,6 +20,8 @@ class Wiki extends \Zotlabs\Web\Controller { notice(t('You must be logged in to see this page.') . EOL); goaway('/login'); } + profile_load($nick); + } function get() { diff --git a/include/channel.php b/include/channel.php index a7624f060..913768017 100644 --- a/include/channel.php +++ b/include/channel.php @@ -761,11 +761,10 @@ function identity_export_year($channel_id,$year,$month = 0) { * * The channel default theme is also selected for use, unless over-riden elsewhere. * - * @param[in,out] App &$a * @param string $nickname * @param string $profile */ -function profile_load(&$a, $nickname, $profile = '') { +function profile_load($nickname, $profile = '') { // logger('profile_load: ' . $nickname . (($profile) ? ' profile: ' . $profile : '')); -- cgit v1.2.3 From 8d298d5a068845856c9827c0d2ea3f02f1399d72 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Sun, 26 Jun 2016 22:26:45 -0700 Subject: fix for the rendering side of issue #412. We traditionally store all "user generated" content with ENT_COMPAT encoding to reduce the attack vector for JS CSS exploits. This may present compatibility issues sharing wikis to platforms which do not provide such CSS protection. We can either decide that wikis are inherently insecure and filter them on render (with an associated performance penalty), or keep the existing method of filtering on store. I'm not making that choice. I'm merely fixing the obvious rendering issue in mono-platform viewing. --- Zotlabs/Module/Wiki.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 6a8bdf0db..38b49effc 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -125,7 +125,7 @@ class Wiki extends \Zotlabs\Web\Controller { notice('Error retrieving page content' . EOL); goaway('/'.argv(0).'/'.argv(1).'/'.$wikiUrlName); } - $content = ($p['content'] !== '' ? $p['content'] : '"# New page\n"'); + $content = ($p['content'] !== '' ? htmlspecialchars_decode($p['content'],ENT_COMPAT) : '"# New page\n"'); // Render the Markdown-formatted page content in HTML require_once('library/markdown.php'); $renderedContent = wiki_convert_links(Markdown(json_decode($content)),argv(0).'/'.argv(1).'/'.$wikiUrlName); -- cgit v1.2.3 From fe7020e2f8a3ba70f808ce4fcb20759101aafd44 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Mon, 27 Jun 2016 05:18:35 -0700 Subject: start on re-write of the permissions doc. Some of this will change (slightly), as the permissions framework is currently evolving. Most of the concepts and mechanisms will remain the same, but we need to simplify and do a better job of explaining the concepts. --- doc/permissions.bb | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/doc/permissions.bb b/doc/permissions.bb index ceb3fec17..cc831dd61 100644 --- a/doc/permissions.bb +++ b/doc/permissions.bb @@ -1,16 +1,20 @@ [h1]Permissions[/h1] -Permissions in the $Projectname are more complete than you may be used to. This allows us to define more fine graded relationships than the black and white "this person is my friend, so they can do everything" or "this person is not my friend, so they can't do anything" permissions you may find elsewhere. +Permissions in $Projectname are more complete than you may be used to. This allows us to define more fine graded relationships than the black and white "this person is my friend, so they can do everything" or "this person is not my friend, so they can't do anything" permissions you may find elsewhere. +[b]Permission Roles[/b] -[b]Default Permissions[/b] +When you create a channel we allow you to select different 'roles' for that channel. These create an entire family of permissions and privacy settings that are appropriate for that role. Typical roles are "Social - mostly public", "Social - mostly private", "Forum - public" and many others. These bring a level of simplicity to managing permissions. Just choose a role and appropriate permissions are automatically applied. You can also choose 'Custom/Expert mode' and change any individual permission setting in any way you desire. -On your settings page, you will find a list of default permissions. These permissions are automatically applied to everybody unless you specify otherwise. The scope of these permissions varies from "Only me" to "Everybody" - though some scopes may not be available for some permissions. For example, you can't allow "anybody on the internet" to send you private messages, because we'd have no way to identify the sender, therefore no way to reply to them. -We highly recommend that you use the "typical social network" settings when you create your first channel, as it allows others to communicate with you and help you out if you have difficulty. You will find that these settings allow you as much privacy as you desire - when you desire it; but also allow you to communicate in public if you choose to. You are free to use much more private settings once you have learned your way around. +[b]Default Permission Limits[/b] + +There are a large number of individual permissions. These control everything from the ability to view your stream to the ability to chat with you. Every permission has a limit. The scope of these permissions varies from "Only me" to "Everybody on the internet" - though some scopes may not be available for some permissions. The limit applies to any published thing you create which has no privacy or access control. For example if you publish a photo and didn't select a specific audience with permission to view it, we apply the limit. These limits apply to everything within that permission rule, so you cannot apply a limit to one photo. The limit applies to all your photos. If all your photos are visible to everybody on the internet and you reduce the limit only to friends, [b]all[/b] of your photos will now be visible only to friends. -Be aware that altering the scope of who can see your "public" items is a more or less [b]permanent[/b] change. Your public items have no identified permissions attached to them - they are public. If you restrict who can see these items, there is no way of making any single item public ever again - without allowing access to every public item you ever created. You are certainly free to do this, but beware of the consequences. +[b]Access Control[/b] + +Access Control is the preferred method of managing privacy in [i]most[/i] cases, rather than using permission limits. This creates lists of either connections or privacy groups (or both) and uses the access list to decide if a permission is allowed. An access list is attached to everything you publish. Unlike permission limits, if you change the access control list on a single photo, it doesn't affect any of your other photos. You can use privacy groups and a "default access control list" to create and automate the management of access control lists to provide any level of privacy you desire on anything you publish. -A more useful privacy setup is to leave "public" items visible to anybody on the internet; but force everything you create to be restricted. This can be done on your Channel Settings page by selecting the role "Social - restricted". This ensures a Default Privacy Group for all new contacts, and sets your Default Post Permissions to restrict all your posts to that group. We use the Default Post Permissions for everything you create - posts, photos, events, webpages, and everything else. However you can then edit the permissions when you create any individual thing and remove your default privacy group to make just that item visible to anybody. +We highly recommend that you use the "typical social network" settings when you create your first channel, as it allows others to communicate with you and help you out if you have difficulty. You will find that these settings allow you as much privacy as you desire - when you desire it; but also allow you to communicate in public if you choose to. You are free to use much more private settings once you have learned your way around. [dl terms="l"] @@ -22,11 +26,11 @@ A more useful privacy setup is to leave "public" items visible to anybody on the [*= Anybody in your address book ] Anybody you do not know will have this permission denied, but anybody you accept as a contact will have this permission approved. This is the way most legacy platforms handle permissions. - [*= Anybody On This Hub ] Anybody using the same hub as you will have permission approved. Anybody who registered at a different hub will have this permission denied. + [*= Anybody On This Hub ] Anybody with a channel on the same hub/website as you will have permission approved. Anybody who is registered at a different hub will have this permission denied. [*= Anybody in this network ] Anybody in the $Projectname will have this permission approved. Even complete strangers. However, anybody not logged in/authenticated will have this permission denied. - [*= Anybody authenticated ] This is similar to "anybody in this network" except that it can include anybody who can authenticate by any means - and therefore may include visitors from other networks. + [*= Anybody authenticated ] This is similar to "anybody in this network" except that it can include anybody who can authenticate by any means - and therefore [i]may[/i] include visitors from other networks. [*= Anybody on the internet ] Completely public. This permission will be approved for anybody at all. [/dl] -- cgit v1.2.3 From f40f7b4d6e291a05ea0a20145bdbe7d98b3d837c Mon Sep 17 00:00:00 2001 From: Habeas Codice <habeascodice@federated.social> Date: Mon, 27 Jun 2016 06:28:08 -0700 Subject: typos --- install/schema_postgres.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install/schema_postgres.sql b/install/schema_postgres.sql index 64cf37f7e..378308233 100644 --- a/install/schema_postgres.sql +++ b/install/schema_postgres.sql @@ -827,15 +827,15 @@ CREATE TABLE "obj" ( "obj_id" serial NOT NULL, "obj_page" char(64) NOT NULL DEFAULT '', "obj_verb" text NOT NULL DEFAULT '', - "obj_type" bigint NOT NULL DEFAULT '0', + "obj_type" bigint NOT NULL DEFAULT 0, "obj_obj" text NOT NULL DEFAULT '', - "obj_channel" bigint NOT NULL DEFAULT '0', + "obj_channel" bigint NOT NULL DEFAULT 0, "obj_term" char(255) NOT NULL DEFAULT '', "obj_url" char(255) NOT NULL DEFAULT '', "obj_imgurl" char(255) NOT NULL DEFAULT '', "obj_created" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00', "obj_edited" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00', - "obj_quantity" int(11) NOT NULL DEFAUL '0'. + "obj_quantity" bigint NOT NULL DEFAULT 0, "allow_cid" text NOT NULL, "allow_gid" text NOT NULL, "deny_cid" text NOT NULL, -- cgit v1.2.3 From ee1d52749733c1de7e88ede6c63f155215e1ae1c Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Mon, 27 Jun 2016 16:15:47 -0700 Subject: comment on the setup page about the possible need for intermediate certs. --- Zotlabs/Module/New_channel.php | 4 ++-- Zotlabs/Module/Setup.php | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index 30d7c83c6..1dcf84fb0 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -62,7 +62,7 @@ class New_channel extends \Zotlabs\Web\Controller { } - function post() { + function post() { $arr = $_POST; @@ -96,7 +96,7 @@ class New_channel extends \Zotlabs\Web\Controller { } - function get() { + function get() { $acc = \App::get_account(); diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index c4878e217..c5d0ccc21 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -596,7 +596,7 @@ class Setup extends \Zotlabs\Web\Controller { if(! is_writable('store')) { $status = false; - $help = t('Red uses the store directory to save uploaded files. The web server needs to have write access to the store directory under the Red top level folder') . EOL; + $help = t('This software uses the store directory to save uploaded files. The web server needs to have write access to the store directory under the Red top level folder') . EOL; $help .= t('Please ensure that the user that your web server runs as (e.g. www-data) has write access to this folder.').EOL; } @@ -639,6 +639,9 @@ class Setup extends \Zotlabs\Web\Controller { $help .= t('If your certificate is not recognized, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues.') . EOL; $help .= t('This can cause usability issues elsewhere (not just on your own site) so we must insist on this requirement.') .EOL; $help .= t('Providers are available that issue free certificates which are browser-valid.'). EOL; + + $help .= t('If you are confident that the certificate is valid and signed by a trusted authority, check to see if you have failed to install an intermediate cert. These are not normally required by browsers, but are required for server-to-server communications.') . EOL; + $this->check_add($checks, t('SSL certificate validation'), false, true, $help); } @@ -695,6 +698,7 @@ class Setup extends \Zotlabs\Web\Controller { // install the standard theme set_config('system', 'allowed_themes', 'redbasic'); + // Set a lenient list of ciphers if using openssl. Other ssl engines // (e.g. NSS used in RedHat) require different syntax, so hopefully // the default curl cipher list will work for most sites. If not, @@ -704,7 +708,9 @@ class Setup extends \Zotlabs\Web\Controller { // z_fetch_url() is also used to import shared links and other content // so in theory most any cipher could show up and we should do our best // to make the content available rather than tell folks that there's a - // weird SSL error which they can't do anything about. + // weird SSL error which they can't do anything about. This does not affect + // the SSL server, but is only a client negotiation to find something workable. + // Hence it will not make your system susceptible to POODL or other nasties. $x = curl_version(); if(stristr($x['ssl_version'],'openssl')) -- cgit v1.2.3 From 3704ff57cb65dce6ddd17136580e3bf82e7d97f2 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Mon, 27 Jun 2016 16:50:06 -0700 Subject: replace [+] and [-] with chevron icons --- Zotlabs/Lib/ThreadItem.php | 2 +- include/js_strings.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index f724ac95d..6625b7b52 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -418,7 +418,7 @@ class ThreadItem { if(($nb_children > $visible_comments) || ($thread_level > 1)) { $result['children'][0]['comment_firstcollapsed'] = true; $result['children'][0]['num_comments'] = $comment_count_txt; - $result['children'][0]['hide_text'] = t('[+] show all'); + $result['children'][0]['hide_text'] = sprintf( t('%s show all'), '<i class="fa fa-chevron-down"></i>'); if($thread_level > 1) { $result['children'][$nb_children - 1]['comment_lastcollapsed'] = true; } diff --git a/include/js_strings.php b/include/js_strings.php index b1817f373..1b4668061 100644 --- a/include/js_strings.php +++ b/include/js_strings.php @@ -4,10 +4,10 @@ function js_strings() { return replace_macros(get_markup_template('js_strings.tpl'), array( '$delitem' => t('Delete this item?'), '$comment' => t('Comment'), - '$showmore' => t('[+] show all'), - '$showfewer' => t('[-] show less'), - '$divgrowmore' => t('[+] expand'), - '$divgrowless' => t('[-] collapse'), + '$showmore' => sprintf( t('%s show all'), '<i class=\'fa fa-chevron-down\'></i>'), + '$showfewer' => sprintf( t('%s show less'), '<i class=\'fa fa-chevron-up\'></i>'), + '$divgrowmore' => sprintf( t('%s expand'), '<i class=\'fa fa-chevron-down\'></i>'), + '$divgrowless' => sprintf( t('%s collapse'),'<i class=\'fa fa-chevron-up\'></i>'), '$pwshort' => t("Password too short"), '$pwnomatch' => t("Passwords do not match"), '$everybody' => t('everybody'), -- cgit v1.2.3 From b155e93ab134759f3d31a509d197916a5af84adb Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Mon, 27 Jun 2016 19:04:00 -0700 Subject: add letsencrypt x3 intermediate cert and new cert file, improve UX of new registrations --- Zotlabs/Module/Register.php | 3 +- include/account.php | 18 +- include/nav.php | 4 +- library/cacert.pem | 560 ++++++++++--------------- library/certs/cacert.pem | 531 +++++++++-------------- library/certs/lets-encrypt-x3-cross-signed.pem | 27 ++ view/tpl/register.tpl | 3 + 7 files changed, 457 insertions(+), 689 deletions(-) create mode 100644 library/certs/lets-encrypt-x3-cross-signed.pem diff --git a/Zotlabs/Module/Register.php b/Zotlabs/Module/Register.php index 7cd1ee501..6afa4a94c 100644 --- a/Zotlabs/Module/Register.php +++ b/Zotlabs/Module/Register.php @@ -259,7 +259,8 @@ class Register extends \Zotlabs\Web\Controller { '$email' => $email, '$pass1' => $password, '$pass2' => $password2, - '$submit' => ((UNO || $auto_create || $registration_is) ? t('Register') : t('Proceed to create your first channel')) + '$submit' => t('Register'), + '$verify_note' => t('This site may require email verification after submitting this form. If you are returned to a login page, please check your email for instructions.') )); return $o; diff --git a/include/account.php b/include/account.php index caf12878e..c02a74928 100644 --- a/include/account.php +++ b/include/account.php @@ -499,11 +499,27 @@ function account_approve($hash) { intval($register[0]['uid']) ); + // get a fresh copy after we've modified it. + + $account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1", + intval($register[0]['uid']) + ); + + if(! $account) + return $ret; + + + if(get_config('system','auto_channel_create') || UNO) auto_channel_create($register[0]['uid']); + else { + $_SESSION['login_return_url'] = 'new_channel'; + authenticate_success($account[0],true,true,false,true); + } + - info( t('Account verified. Please login.') . EOL ); + // info( t('Account verified. Please login.') . EOL ); return true; } diff --git a/include/nav.php b/include/nav.php index 70faec598..21e9d2c3a 100644 --- a/include/nav.php +++ b/include/nav.php @@ -126,7 +126,7 @@ EOT; $nav['lock'] = array('logout','','lock', sprintf( t('%s - click to logout'), $observer['xchan_addr'])); } - else { + elseif(! $_SESSION['authenticated']) { $nav['loginmenu'][] = Array('rmagic',t('Remote authentication'),'',t('Click to authenticate to your home hub'),'rmagic_nav_btn'); } @@ -143,7 +143,7 @@ EOT; if((App::$module != 'home') && (! (local_channel()))) $nav['home'] = array($homelink, t('Home'), "", t('Home Page'),'home_nav_btn'); - if((App::$config['system']['register_policy'] == REGISTER_OPEN) && (! local_channel()) && (! remote_channel())) + if((App::$config['system']['register_policy'] == REGISTER_OPEN) && (! $_SESSION['authenticated'])) $nav['register'] = array('register',t('Register'), "", t('Create an account'),'register_nav_btn'); if(! get_config('system','hide_help')) { diff --git a/library/cacert.pem b/library/cacert.pem index ef43898ab..29dbfa286 100644 --- a/library/cacert.pem +++ b/library/cacert.pem @@ -1,7 +1,7 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Wed Sep 2 18:30:34 2015 +## Certificate data from Mozilla as of: Wed Apr 20 03:12:05 2016 ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,30 +14,10 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.25. -## SHA1: ed3c0bbfb7912bcc00cd2033b0cb85c98d10559c +## SHA1: 5df367cda83086392e1acdf22bfef00c48d5eba6 ## -Equifax Secure CA -================= ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE -ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 -MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT -B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB -nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR -fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW -8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG -A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE -CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG -A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS -spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB -Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 -zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB -BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 -70+sB3c4 ------END CERTIFICATE----- - GlobalSign Root CA ================== -----BEGIN CERTIFICATE----- @@ -105,30 +85,6 @@ xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== -----END CERTIFICATE----- -Verisign Class 4 Public Primary Certification Authority - G3 -============================================================ ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy -dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS -tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM -8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW -Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX -Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA -j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt -mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd -RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG -UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- - Entrust.net Premium 2048 Secure Server CA ========================================= -----BEGIN CERTIFICATE----- @@ -673,53 +629,6 @@ EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH llpwrN9M -----END CERTIFICATE----- -Staat der Nederlanden Root CA -============================= ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE -ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g -Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w -HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh -bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt -vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P -jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca -C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth -vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 -22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV -HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v -dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN -BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR -EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw -MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y -nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR -iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== ------END CERTIFICATE----- - -UTN DATACorp SGC Root CA -======================== ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ -BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa -MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w -HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy -dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys -raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo -wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA -9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv -33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud -DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 -BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD -LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 -DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 -I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx -EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP -DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- - UTN USERFirst Hardware Root CA ============================== -----BEGIN CERTIFICATE----- @@ -800,41 +709,6 @@ IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== -----END CERTIFICATE----- -NetLock Notary (Class A) Root -============================= ------BEGIN CERTIFICATE----- -MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI -EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 -dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j -ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX -DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH -EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD -VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz -cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM -D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ -z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC -/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 -tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 -4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG -A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC -Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv -bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu -IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn -LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 -ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz -IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh -IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu -b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh -bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg -Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp -bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 -ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP -ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB -CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr -KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM -8CgHrTwXZoi1/baI ------END CERTIFICATE----- - XRamp Global CA Root ==================== -----BEGIN CERTIFICATE----- @@ -1142,54 +1016,6 @@ vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 oKfN5XozNmr6mis= -----END CERTIFICATE----- -TURKTRUST Certificate Services Provider Root 1 -============================================== ------BEGIN CERTIFICATE----- -MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP -MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 -acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx -MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg -U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB -TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC -aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX -yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i -Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ -8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 -W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME -BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 -sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE -q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy -B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY -nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H ------END CERTIFICATE----- - -TURKTRUST Certificate Services Provider Root 2 -============================================== ------BEGIN CERTIFICATE----- -MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP -MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg -QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN -MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr -dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G -A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls -acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe -LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI -x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g -QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr -5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB -AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt -Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 -Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ -hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P -9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 -UrbnBEI= ------END CERTIFICATE----- - SwissSign Gold CA - G2 ====================== -----BEGIN CERTIFICATE----- @@ -1589,56 +1415,6 @@ PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- -TC TrustCenter Class 2 CA II -============================ ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy -IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw -MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 -c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE -AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw -IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 -xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ -Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u -SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB -7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 -Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU -cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i -SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G -dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ -KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj -TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP -JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk -vQ== ------END CERTIFICATE----- - -TC TrustCenter Universal CA I -============================= ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy -IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN -MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg -VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw -JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC -qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv -xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw -ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O -gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j -BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG -1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy -vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 -ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT -ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a -7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY ------END CERTIFICATE----- - Deutsche Telekom Root CA 2 ========================== -----BEGIN CERTIFICATE----- @@ -1661,28 +1437,6 @@ dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU Cm26OWMohpLzGITY+9HPBVZkVw== -----END CERTIFICATE----- -ComSign Secured CA -================== ------BEGIN CERTIFICATE----- -MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE -AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w -NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD -QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs -49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH -7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB -kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 -9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw -AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t -U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA -j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC -AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a -BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp -FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP -51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz -OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== ------END CERTIFICATE----- - Cybertrust Global Root ====================== -----BEGIN CERTIFICATE----- @@ -1784,26 +1538,6 @@ fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho -----END CERTIFICATE----- -Buypass Class 3 CA 1 -==================== ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 -MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh -c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx -ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 -n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia -AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c -1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P -AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 -pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA -EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 -htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj -el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 ------END CERTIFICATE----- - EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 ========================================================================== -----BEGIN CERTIFICATE----- @@ -2085,30 +1819,6 @@ IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm 66+KAQ== -----END CERTIFICATE----- -CA Disig -======== ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK -QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw -MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz -bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm -GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD -Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo -hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt -ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w -gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P -AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz -aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff -ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa -BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t -WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 -mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ -CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K -ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA -4Z7CRneC9VkGjCFMhwnN5ag= ------END CERTIFICATE----- - Juur-SK ======= -----BEGIN CERTIFICATE----- @@ -2635,29 +2345,6 @@ iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt +GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= -----END CERTIFICATE----- -A-Trust-nQual-03 -================ ------BEGIN CERTIFICATE----- -MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE -Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy -a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R -dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw -RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 -ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 -c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA -zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n -yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE -SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 -iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V -cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV -eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 -ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr -sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd -JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS -mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 -ahq97BvIxYSazQ== ------END CERTIFICATE----- - TWCA Root Certification Authority ================================= -----BEGIN CERTIFICATE----- @@ -3986,6 +3673,196 @@ PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- + +TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 +========================================================= +-----BEGIN CERTIFICATE----- +MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN +BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp +bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg +RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw +ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w +SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE +n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp +ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537 +jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m +ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP +9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV +4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH +HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo +BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq +URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl +lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8 +B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU= +-----END CERTIFICATE----- + +TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6 +========================================================= +-----BEGIN CERTIFICATE----- +MIIEJjCCAw6gAwIBAgIGfaHyZeyKMA0GCSqGSIb3DQEBCwUAMIGxMQswCQYDVQQGEwJUUjEPMA0G +A1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls +acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg2MB4XDTEzMTIxODA5 +MDQxMFoXDTIzMTIxNjA5MDQxMFowgbExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExTTBL +BgNVBAoMRFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSf +aSBIaXptZXRsZXJpIEEuxZ4uMUIwQAYDVQQDDDlUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlm +aWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLEgSDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCdsGjW6L0UlqMACprx9MfMkU1xeHe59yEmFXNRFpQJRwXiM/VomjX/3EsvMsew7eKC5W/a +2uqsxgbPJQ1BgfbBOCK9+bGlprMBvD9QFyv26WZV1DOzXPhDIHiTVRZwGTLmiddk671IUP320EED +wnS3/faAz1vFq6TWlRKb55cTMgPp1KtDWxbtMyJkKbbSk60vbNg9tvYdDjTu0n2pVQ8g9P0pu5Fb +HH3GQjhtQiht1AH7zYiXSX6484P4tZgvsycLSF5W506jM7NE1qXyGJTtHB6plVxiSvgNZ1GpryHV ++DKdeboaX+UEVU0TRv/yz3THGmNtwx8XEsMeED5gCLMxAgMBAAGjQjBAMB0GA1UdDgQWBBTdVRcT +9qzoSCHK77Wv0QAy7Z6MtTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQsFAAOCAQEAb1gNl0OqFlQ+v6nfkkU/hQu7VtMMUszIv3ZnXuaqs6fvuay0EBQNdH49ba3R +fdCaqaXKGDsCQC4qnFAUi/5XfldcEQlLNkVS9z2sFP1E34uXI9TDwe7UU5X+LEr+DXCqu4svLcsy +o4LyVN/Y8t3XSHLuSqMplsNEzm61kod2pLv0kmzOLBQJZo6NrRa1xxsJYTvjIKIDgI6tflEATseW +hvtDmHd9KMeP2Cpu54Rvl0EpABZeTeIT6lnAY2c6RPuY/ATTMHKm9ocJV612ph1jmv3XZch4gyt1 +O6VbuA1df74jrlZVlFjvH4GMKrLN5ptjnhi85WsGtAuYSyher4hYyw== +-----END CERTIFICATE----- + +Certinomis - Root CA +==================== +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK +Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg +LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx +EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD +ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos +P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo +d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap +z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00 +8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x +RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE +6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t +FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV +PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH +i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj +YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I +6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF +AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV +WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw +Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX +lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ +y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9 +Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng +DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi +I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM +cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr +hkIGuUE= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +=============================== +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +Certification Authority of WoSign G2 +==================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG +EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g +QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx +CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai +XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du +W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9 +5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK +v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI +hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY +P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3 +TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu ++sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+ +7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg= +-----END CERTIFICATE----- + +CA WoSign ECC Root +================== +-----BEGIN CERTIFICATE----- +MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD +TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v +dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK +ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU +t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw +QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R +MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0 +Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu +a/GRspBl9JrmkO5K +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +=============== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G @@ -4078,33 +3955,30 @@ Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= -----END CERTIFICATE----- - -Lets Encrypt -============ -----BEGIN CERTIFICATE----- -MIIEqDCCA5CgAwIBAgIRAJgT9HUT5XULQ+dDHpceRL0wDQYJKoZIhvcNAQELBQAw -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzAeFw0xNTEwMTkyMjMzMzZaFw0yMDEwMTkyMjMzMzZa -MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD -ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAJzTDPBa5S5Ht3JdN4OzaGMw6tc1Jhkl4b2+NfFwki+3uEtB -BaupnjUIWOyxKsRohwuj43Xk5vOnYnG6eYFgH9eRmp/z0HhncchpDpWRz/7mmelg -PEjMfspNdxIknUcbWuu57B43ABycrHunBerOSuu9QeU2mLnL/W08lmjfIypCkAyG -dGfIf6WauFJhFBM/ZemCh8vb+g5W9oaJ84U/l4avsNwa72sNlRZ9xCugZbKZBDZ1 -gGusSvMbkEl4L6KWTyogJSkExnTA0DHNjzE4lRa6qDO4Q/GxH8Mwf6J5MRM9LTb4 -4/zyM2q5OTHFr8SNDR1kFjOq+oQpttQLwNh9w5MCAwEAAaOCAZIwggGOMBIGA1Ud -EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMH8GCCsGAQUFBwEBBHMwcTAy -BggrBgEFBQcwAYYmaHR0cDovL2lzcmcudHJ1c3RpZC5vY3NwLmlkZW50cnVzdC5j -b20wOwYIKwYBBQUHMAKGL2h0dHA6Ly9hcHBzLmlkZW50cnVzdC5jb20vcm9vdHMv -ZHN0cm9vdGNheDMucDdjMB8GA1UdIwQYMBaAFMSnsaR7LHH62+FLkHX/xBVghYkQ -MFQGA1UdIARNMEswCAYGZ4EMAQIBMD8GCysGAQQBgt8TAQEBMDAwLgYIKwYBBQUH -AgEWImh0dHA6Ly9jcHMucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcwPAYDVR0fBDUw -MzAxoC+gLYYraHR0cDovL2NybC5pZGVudHJ1c3QuY29tL0RTVFJPT1RDQVgzQ1JM -LmNybDATBgNVHR4EDDAKoQgwBoIELm1pbDAdBgNVHQ4EFgQUqEpqYwR93brm0Tm3 -pkVl7/Oo7KEwDQYJKoZIhvcNAQELBQADggEBANHIIkus7+MJiZZQsY14cCoBG1hd -v0J20/FyWo5ppnfjL78S2k4s2GLRJ7iD9ZDKErndvbNFGcsW+9kKK/TnY21hp4Dd -ITv8S9ZYQ7oaoqs7HwhEMY9sibED4aXw09xrJZTC9zK1uIfW6t5dHQjuOWv+HHoW -ZnupyxpsEUlEaFb+/SCI4KCSBdAsYxAcsHYI5xxEI4LutHp6s3OT2FuO90WfdsIk -6q78OMSdn875bNjdBYAqxUp2/LEIHfDBkLoQz0hFJmwAbYahqKaLn73PAAm1X2kj -f1w8DdnkabOLGeOVcj9LQ+s67vBykx4anTjURkbqZslUEUsn2k5xeua2zUk= +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow +SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT +GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF +q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 +SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 +Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA +a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj +/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG +CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv +bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k +c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw +VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC +ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz +MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu +Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF +AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo +uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ +wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu +X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG +PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 +KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE----- diff --git a/library/certs/cacert.pem b/library/certs/cacert.pem index e4da7fc15..c15368bdc 100644 --- a/library/certs/cacert.pem +++ b/library/certs/cacert.pem @@ -1,7 +1,7 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Wed Sep 2 18:30:34 2015 +## Certificate data from Mozilla as of: Wed Apr 20 03:12:05 2016 ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,30 +14,10 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.25. -## SHA1: ed3c0bbfb7912bcc00cd2033b0cb85c98d10559c +## SHA1: 5df367cda83086392e1acdf22bfef00c48d5eba6 ## -Equifax Secure CA -================= ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE -ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 -MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT -B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB -nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR -fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW -8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG -A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE -CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG -A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS -spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB -Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 -zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB -BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 -70+sB3c4 ------END CERTIFICATE----- - GlobalSign Root CA ================== -----BEGIN CERTIFICATE----- @@ -105,30 +85,6 @@ xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== -----END CERTIFICATE----- -Verisign Class 4 Public Primary Certification Authority - G3 -============================================================ ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy -dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS -tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM -8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW -Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX -Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA -j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt -mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd -RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG -UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- - Entrust.net Premium 2048 Secure Server CA ========================================= -----BEGIN CERTIFICATE----- @@ -673,53 +629,6 @@ EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH llpwrN9M -----END CERTIFICATE----- -Staat der Nederlanden Root CA -============================= ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE -ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g -Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w -HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh -bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt -vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P -jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca -C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth -vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 -22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV -HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v -dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN -BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR -EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw -MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y -nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR -iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== ------END CERTIFICATE----- - -UTN DATACorp SGC Root CA -======================== ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ -BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa -MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w -HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy -dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys -raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo -wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA -9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv -33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud -DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 -BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD -LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 -DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 -I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx -EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP -DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- - UTN USERFirst Hardware Root CA ============================== -----BEGIN CERTIFICATE----- @@ -800,41 +709,6 @@ IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== -----END CERTIFICATE----- -NetLock Notary (Class A) Root -============================= ------BEGIN CERTIFICATE----- -MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI -EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 -dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j -ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX -DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH -EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD -VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz -cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM -D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ -z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC -/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 -tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 -4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG -A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC -Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv -bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu -IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn -LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 -ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz -IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh -IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu -b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh -bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg -Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp -bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 -ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP -ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB -CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr -KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM -8CgHrTwXZoi1/baI ------END CERTIFICATE----- - XRamp Global CA Root ==================== -----BEGIN CERTIFICATE----- @@ -1142,54 +1016,6 @@ vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 oKfN5XozNmr6mis= -----END CERTIFICATE----- -TURKTRUST Certificate Services Provider Root 1 -============================================== ------BEGIN CERTIFICATE----- -MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP -MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 -acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx -MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg -U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB -TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC -aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX -yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i -Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ -8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 -W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME -BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 -sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE -q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy -B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY -nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H ------END CERTIFICATE----- - -TURKTRUST Certificate Services Provider Root 2 -============================================== ------BEGIN CERTIFICATE----- -MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP -MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg -QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN -MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr -dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G -A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls -acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe -LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI -x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g -QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr -5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB -AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt -Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 -Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ -hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P -9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 -UrbnBEI= ------END CERTIFICATE----- - SwissSign Gold CA - G2 ====================== -----BEGIN CERTIFICATE----- @@ -1589,56 +1415,6 @@ PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- -TC TrustCenter Class 2 CA II -============================ ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy -IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw -MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 -c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE -AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw -IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 -xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ -Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u -SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB -7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 -Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU -cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i -SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G -dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ -KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj -TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP -JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk -vQ== ------END CERTIFICATE----- - -TC TrustCenter Universal CA I -============================= ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy -IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN -MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg -VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw -JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC -qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv -xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw -ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O -gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j -BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG -1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy -vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 -ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT -ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a -7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY ------END CERTIFICATE----- - Deutsche Telekom Root CA 2 ========================== -----BEGIN CERTIFICATE----- @@ -1661,28 +1437,6 @@ dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU Cm26OWMohpLzGITY+9HPBVZkVw== -----END CERTIFICATE----- -ComSign Secured CA -================== ------BEGIN CERTIFICATE----- -MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE -AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w -NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD -QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs -49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH -7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB -kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 -9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw -AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t -U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA -j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC -AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a -BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp -FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP -51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz -OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== ------END CERTIFICATE----- - Cybertrust Global Root ====================== -----BEGIN CERTIFICATE----- @@ -1784,26 +1538,6 @@ fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho -----END CERTIFICATE----- -Buypass Class 3 CA 1 -==================== ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 -MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh -c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx -ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 -n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia -AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c -1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P -AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 -pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA -EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 -htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj -el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 ------END CERTIFICATE----- - EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 ========================================================================== -----BEGIN CERTIFICATE----- @@ -2085,30 +1819,6 @@ IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm 66+KAQ== -----END CERTIFICATE----- -CA Disig -======== ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK -QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw -MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz -bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm -GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD -Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo -hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt -ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w -gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P -AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz -aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff -ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa -BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t -WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 -mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ -CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K -ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA -4Z7CRneC9VkGjCFMhwnN5ag= ------END CERTIFICATE----- - Juur-SK ======= -----BEGIN CERTIFICATE----- @@ -2635,29 +2345,6 @@ iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt +GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= -----END CERTIFICATE----- -A-Trust-nQual-03 -================ ------BEGIN CERTIFICATE----- -MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE -Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy -a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R -dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw -RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 -ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 -c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA -zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n -yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE -SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 -iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V -cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV -eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 -ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr -sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd -JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS -mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 -ahq97BvIxYSazQ== ------END CERTIFICATE----- - TWCA Root Certification Authority ================================= -----BEGIN CERTIFICATE----- @@ -3987,32 +3674,192 @@ kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- -Lets Encrypt -============ +TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 +========================================================= +-----BEGIN CERTIFICATE----- +MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN +BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp +bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg +RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw +ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w +SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE +n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp +ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537 +jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m +ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP +9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV +4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH +HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo +BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq +URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl +lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8 +B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU= +-----END CERTIFICATE----- + +TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6 +========================================================= +-----BEGIN CERTIFICATE----- +MIIEJjCCAw6gAwIBAgIGfaHyZeyKMA0GCSqGSIb3DQEBCwUAMIGxMQswCQYDVQQGEwJUUjEPMA0G +A1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls +acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg2MB4XDTEzMTIxODA5 +MDQxMFoXDTIzMTIxNjA5MDQxMFowgbExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExTTBL +BgNVBAoMRFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSf +aSBIaXptZXRsZXJpIEEuxZ4uMUIwQAYDVQQDDDlUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlm +aWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLEgSDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCdsGjW6L0UlqMACprx9MfMkU1xeHe59yEmFXNRFpQJRwXiM/VomjX/3EsvMsew7eKC5W/a +2uqsxgbPJQ1BgfbBOCK9+bGlprMBvD9QFyv26WZV1DOzXPhDIHiTVRZwGTLmiddk671IUP320EED +wnS3/faAz1vFq6TWlRKb55cTMgPp1KtDWxbtMyJkKbbSk60vbNg9tvYdDjTu0n2pVQ8g9P0pu5Fb +HH3GQjhtQiht1AH7zYiXSX6484P4tZgvsycLSF5W506jM7NE1qXyGJTtHB6plVxiSvgNZ1GpryHV ++DKdeboaX+UEVU0TRv/yz3THGmNtwx8XEsMeED5gCLMxAgMBAAGjQjBAMB0GA1UdDgQWBBTdVRcT +9qzoSCHK77Wv0QAy7Z6MtTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQsFAAOCAQEAb1gNl0OqFlQ+v6nfkkU/hQu7VtMMUszIv3ZnXuaqs6fvuay0EBQNdH49ba3R +fdCaqaXKGDsCQC4qnFAUi/5XfldcEQlLNkVS9z2sFP1E34uXI9TDwe7UU5X+LEr+DXCqu4svLcsy +o4LyVN/Y8t3XSHLuSqMplsNEzm61kod2pLv0kmzOLBQJZo6NrRa1xxsJYTvjIKIDgI6tflEATseW +hvtDmHd9KMeP2Cpu54Rvl0EpABZeTeIT6lnAY2c6RPuY/ATTMHKm9ocJV612ph1jmv3XZch4gyt1 +O6VbuA1df74jrlZVlFjvH4GMKrLN5ptjnhi85WsGtAuYSyher4hYyw== +-----END CERTIFICATE----- + +Certinomis - Root CA +==================== +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK +Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg +LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx +EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD +ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos +P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo +d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap +z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00 +8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x +RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE +6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t +FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV +PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH +i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj +YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I +6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF +AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV +WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw +Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX +lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ +y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9 +Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng +DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi +I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM +cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr +hkIGuUE= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +=============================== +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +Certification Authority of WoSign G2 +==================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG +EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g +QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx +CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai +XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du +W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9 +5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK +v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI +hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY +P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3 +TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu ++sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+ +7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg= +-----END CERTIFICATE----- + +CA WoSign ECC Root +================== +-----BEGIN CERTIFICATE----- +MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD +TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v +dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK +ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU +t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw +QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R +MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0 +Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu +a/GRspBl9JrmkO5K +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +=============== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== -----BEGIN CERTIFICATE----- -MIIEqDCCA5CgAwIBAgIRAJgT9HUT5XULQ+dDHpceRL0wDQYJKoZIhvcNAQELBQAw -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzAeFw0xNTEwMTkyMjMzMzZaFw0yMDEwMTkyMjMzMzZa -MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD -ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAJzTDPBa5S5Ht3JdN4OzaGMw6tc1Jhkl4b2+NfFwki+3uEtB -BaupnjUIWOyxKsRohwuj43Xk5vOnYnG6eYFgH9eRmp/z0HhncchpDpWRz/7mmelg -PEjMfspNdxIknUcbWuu57B43ABycrHunBerOSuu9QeU2mLnL/W08lmjfIypCkAyG -dGfIf6WauFJhFBM/ZemCh8vb+g5W9oaJ84U/l4avsNwa72sNlRZ9xCugZbKZBDZ1 -gGusSvMbkEl4L6KWTyogJSkExnTA0DHNjzE4lRa6qDO4Q/GxH8Mwf6J5MRM9LTb4 -4/zyM2q5OTHFr8SNDR1kFjOq+oQpttQLwNh9w5MCAwEAAaOCAZIwggGOMBIGA1Ud -EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMH8GCCsGAQUFBwEBBHMwcTAy -BggrBgEFBQcwAYYmaHR0cDovL2lzcmcudHJ1c3RpZC5vY3NwLmlkZW50cnVzdC5j -b20wOwYIKwYBBQUHMAKGL2h0dHA6Ly9hcHBzLmlkZW50cnVzdC5jb20vcm9vdHMv -ZHN0cm9vdGNheDMucDdjMB8GA1UdIwQYMBaAFMSnsaR7LHH62+FLkHX/xBVghYkQ -MFQGA1UdIARNMEswCAYGZ4EMAQIBMD8GCysGAQQBgt8TAQEBMDAwLgYIKwYBBQUH -AgEWImh0dHA6Ly9jcHMucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcwPAYDVR0fBDUw -MzAxoC+gLYYraHR0cDovL2NybC5pZGVudHJ1c3QuY29tL0RTVFJPT1RDQVgzQ1JM -LmNybDATBgNVHR4EDDAKoQgwBoIELm1pbDAdBgNVHQ4EFgQUqEpqYwR93brm0Tm3 -pkVl7/Oo7KEwDQYJKoZIhvcNAQELBQADggEBANHIIkus7+MJiZZQsY14cCoBG1hd -v0J20/FyWo5ppnfjL78S2k4s2GLRJ7iD9ZDKErndvbNFGcsW+9kKK/TnY21hp4Dd -ITv8S9ZYQ7oaoqs7HwhEMY9sibED4aXw09xrJZTC9zK1uIfW6t5dHQjuOWv+HHoW -ZnupyxpsEUlEaFb+/SCI4KCSBdAsYxAcsHYI5xxEI4LutHp6s3OT2FuO90WfdsIk -6q78OMSdn875bNjdBYAqxUp2/LEIHfDBkLoQz0hFJmwAbYahqKaLn73PAAm1X2kj -f1w8DdnkabOLGeOVcj9LQ+s67vBykx4anTjURkbqZslUEUsn2k5xeua2zUk= +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP -----END CERTIFICATE----- diff --git a/library/certs/lets-encrypt-x3-cross-signed.pem b/library/certs/lets-encrypt-x3-cross-signed.pem new file mode 100644 index 000000000..0002462ce --- /dev/null +++ b/library/certs/lets-encrypt-x3-cross-signed.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow +SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT +GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF +q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 +SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 +Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA +a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj +/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG +CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv +bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k +c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw +VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC +ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz +MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu +Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF +AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo +uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ +wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu +X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG +PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 +KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== +-----END CERTIFICATE----- diff --git a/view/tpl/register.tpl b/view/tpl/register.tpl index 4a827ca16..c84934626 100755 --- a/view/tpl/register.tpl +++ b/view/tpl/register.tpl @@ -54,5 +54,8 @@ <button class="btn btn-primary" type="submit" name="submit" id="newchannel-submit-button" value="{{$submit}}">{{$submit}}</button> <div id="register-submit-end" class="register-field-end"></div> </form> + <br /> + <div class="descriptive-text">{{$verify_note}}</div> + </div> </div> -- cgit v1.2.3 From 30a5fe30617ef19d7cb896783442d43277ce5a8e Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Mon, 27 Jun 2016 19:53:35 -0700 Subject: provide a daemon for implementing zot magic-auth over curl. --- Zotlabs/Daemon/CurlAuth.php | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Zotlabs/Daemon/CurlAuth.php diff --git a/Zotlabs/Daemon/CurlAuth.php b/Zotlabs/Daemon/CurlAuth.php new file mode 100644 index 000000000..d0296a729 --- /dev/null +++ b/Zotlabs/Daemon/CurlAuth.php @@ -0,0 +1,52 @@ +<?php + +namespace Zotlabs\Daemon; + +// generate a curl compatible cookie file with an authenticated session for the given channel_id. +// If this file is then used with curl and the destination url is sent through zid() or manually +// manipulated to add a zid, it should allow curl to provide zot magic-auth across domains. + +// Handles expiration of stale cookies currently by deleting them and rewriting the file. + +class CurlAuth { + + static public function run($argc,$argv) { + + if($argc != 2) + killme(); + + session_start(); + + $_SESSION['authenticated'] = 1; + $_SESSION['uid'] = $argv[1]; + + $x = session_id(); + + $f = 'store/[data]/cookie_' . $argv[1]; + + $e = file_exists($f); + + $output = ''; + + if($e) { + $lines = file($f); + if($lines) { + foreach($lines as $line) { + if(strlen($line) > 0 && $line[0] != '#' && substr_count($line, "\t") == 6) { + $tokens = explode("\t", $line); + $tokens = array_map('trim', $tokens); + if($tokens[4] > time()) { + $output .= $line . "\n"; + } + } + else + $output .= $line; + } + } + } + + file_put_contents($f, $output . 'HttpOnly_' . \App::get_hostname() . "\tFALSE\t/\tFALSE\t0\tPHPSESSID\t" . $x, (($e) ? FILE_APPEND : 0)); + + killme(); + } +} \ No newline at end of file -- cgit v1.2.3 From 7d7f43c2056fd50ff26aed5df553bf4936ead196 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Mon, 27 Jun 2016 22:25:37 -0700 Subject: still working through some issues with curl magic-auth fixed profile photo upload --- Zotlabs/Daemon/CurlAuth.php | 7 +++++-- Zotlabs/Lib/SuperCurl.php | 15 +++++++++++++++ Zotlabs/Module/Cover_photo.php | 2 +- Zotlabs/Module/Profile_photo.php | 5 ++--- include/network.php | 7 +++++++ 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Zotlabs/Daemon/CurlAuth.php b/Zotlabs/Daemon/CurlAuth.php index d0296a729..be12bc779 100644 --- a/Zotlabs/Daemon/CurlAuth.php +++ b/Zotlabs/Daemon/CurlAuth.php @@ -15,7 +15,7 @@ class CurlAuth { if($argc != 2) killme(); - session_start(); + \App::$session->start(); $_SESSION['authenticated'] = 1; $_SESSION['uid'] = $argv[1]; @@ -23,6 +23,7 @@ class CurlAuth { $x = session_id(); $f = 'store/[data]/cookie_' . $argv[1]; + $c = 'store/[data]/cookien_' . $argv[1]; $e = file_exists($f); @@ -44,8 +45,10 @@ class CurlAuth { } } } + $t = time() + (24 * 3600); + file_put_contents($f, $output . 'HttpOnly_' . \App::get_hostname() . "\tFALSE\t/\tTRUE\t$t\tPHPSESSID\t" . $x, (($e) ? FILE_APPEND : 0)); - file_put_contents($f, $output . 'HttpOnly_' . \App::get_hostname() . "\tFALSE\t/\tFALSE\t0\tPHPSESSID\t" . $x, (($e) ? FILE_APPEND : 0)); + file_put_contents($c,$x); killme(); } diff --git a/Zotlabs/Lib/SuperCurl.php b/Zotlabs/Lib/SuperCurl.php index 40ca1addb..fd47c399c 100644 --- a/Zotlabs/Lib/SuperCurl.php +++ b/Zotlabs/Lib/SuperCurl.php @@ -26,6 +26,7 @@ class SuperCurl { private $request_method = 'GET'; private $upload = false; + private $cookies = false; private function set_data($s) { @@ -62,6 +63,11 @@ class SuperCurl { case 'http_auth': $this->auth = $v; break; + case 'magicauth': + $this->magicauth = $v; + \Zotlabs\Daemon\Master::Summon([ 'CurlAuth', $v ]); + sleep(2); + break; case 'custom': $this->request_method = $v; break; @@ -90,8 +96,17 @@ class SuperCurl { function exec() { $opts = $this->curlopts; + $url = $this->url; if($this->auth) $opts['http_auth'] = $this->auth; + if($this->magicauth) { + $opts['cookiejar'] = 'store/[data]/cookie_' . $this->magicauth; + $opts['cookiefile'] = 'store/[data]/cookie_' . $this->magicauth; + $opts['cookie'] = 'PHPSESSID=' . trim(file_get_contents('store/[data]/cookien_' . $this->magicauth)); + $c = channelx_by_n($this->magicauth); + if($c) + $url = zid($this->url,$c['channel_address'] . '@' . \App::get_hostname()); + } if($this->custom) $opts['custom'] = $this->custom; if($this->headers) diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php index 9887b8203..886958b37 100644 --- a/Zotlabs/Module/Cover_photo.php +++ b/Zotlabs/Module/Cover_photo.php @@ -50,7 +50,7 @@ class Cover_photo extends \Zotlabs\Web\Controller { check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo'); - if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) { + if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) { // phase 2 - we have finished cropping diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php index 62c5e99ae..9359b80f8 100644 --- a/Zotlabs/Module/Profile_photo.php +++ b/Zotlabs/Module/Profile_photo.php @@ -53,7 +53,7 @@ class Profile_photo extends \Zotlabs\Web\Controller { check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo'); - if((array_key_exists('postfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) { + if((array_key_exists('cropfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) { // phase 2 - we have finished cropping @@ -90,12 +90,11 @@ class Profile_photo extends \Zotlabs\Web\Controller { $srcY = $_POST['ystart']; $srcW = $_POST['xfinal'] - $srcX; $srcH = $_POST['yfinal'] - $srcY; - + $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = %d LIMIT 1", dbesc($image_id), dbesc(local_channel()), intval($scale)); - if($r) { $base_image = $r[0]; diff --git a/include/network.php b/include/network.php index 96bf714f6..47863b680 100644 --- a/include/network.php +++ b/include/network.php @@ -101,6 +101,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { if(x($opts,'cookiefile')) @curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']); + if(x($opts,'cookie')) + @curl_setopt($ch, CURLOPT_COOKIE, $opts['cookie']); + @curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, ((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true)); @@ -258,6 +261,10 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { if(x($opts,'cookiefile')) @curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']); + + if(x($opts,'cookie')) + @curl_setopt($ch, CURLOPT_COOKIE, $opts['cookie']); + @curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, ((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true)); -- cgit v1.2.3 From aff58934c0c33ad9bf68c0a3b3a0a224fee978ef Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Tue, 28 Jun 2016 11:56:28 +0200 Subject: update fullcalendar to version 2.8.0 --- library/fullcalendar/CHANGELOG.txt | 20 ++ library/fullcalendar/fullcalendar.css | 3 +- library/fullcalendar/fullcalendar.js | 283 +++++++++++++++++++++++----- library/fullcalendar/fullcalendar.min.css | 4 +- library/fullcalendar/fullcalendar.min.js | 10 +- library/fullcalendar/fullcalendar.print.css | 2 +- library/fullcalendar/gcal.js | 2 +- library/fullcalendar/lang-all.js | 6 +- view/css/mod_cal.css | 4 - view/css/mod_events.css | 4 - 10 files changed, 267 insertions(+), 71 deletions(-) diff --git a/library/fullcalendar/CHANGELOG.txt b/library/fullcalendar/CHANGELOG.txt index 32559a8ad..f488738b8 100644 --- a/library/fullcalendar/CHANGELOG.txt +++ b/library/fullcalendar/CHANGELOG.txt @@ -1,4 +1,24 @@ +v2.8.0 (2016-06-19) +------------------- + +- getEventSources method (#3103, #2433) +- getEventSourceById method (#3223) +- refetchEventSources method (#3103, #1328, #254) +- removeEventSources method (#3165, #948) +- prevent flicker when refetchEvents is called (#3123, #2558) +- fix for removing event sources that share same URL (#3209) +- jQuery 3 support (#3197, #3124) +- Travis CI integration (#3218) +- EditorConfig for promoting consistent code style (#141) +- use en dash when formatting ranges (#3077) +- height:auto always shows scrollbars in month view on FF (#3202) +- new languages: + - Basque (#2992) + - Galician (#194) + - Luxembourgish (#2979) + + v2.7.3 (2016-06-02) ------------------- diff --git a/library/fullcalendar/fullcalendar.css b/library/fullcalendar/fullcalendar.css index 81e9c1ee2..166bd09d3 100644 --- a/library/fullcalendar/fullcalendar.css +++ b/library/fullcalendar/fullcalendar.css @@ -1,5 +1,5 @@ /*! - * FullCalendar v2.7.3 Stylesheet + * FullCalendar v2.8.0 Stylesheet * Docs & License: http://fullcalendar.io/ * (c) 2016 Adam Shaw */ @@ -367,6 +367,7 @@ hr.fc-divider { .fc table { width: 100%; + box-sizing: border-box; /* fix scrollbar issue in firefox */ table-layout: fixed; border-collapse: collapse; border-spacing: 0; diff --git a/library/fullcalendar/fullcalendar.js b/library/fullcalendar/fullcalendar.js index cbe67697d..2460eb5e7 100644 --- a/library/fullcalendar/fullcalendar.js +++ b/library/fullcalendar/fullcalendar.js @@ -1,5 +1,5 @@ /*! - * FullCalendar v2.7.3 + * FullCalendar v2.8.0 * Docs & License: http://fullcalendar.io/ * (c) 2016 Adam Shaw */ @@ -19,7 +19,7 @@ ;; var FC = $.fullCalendar = { - version: "2.7.3", + version: "2.8.0", internalApiVersion: 4 }; var fcViews = FC.views = {}; @@ -1054,6 +1054,20 @@ function debounce(func, wait, immediate) { }; } + +// HACK around jQuery's now A+ promises: execute callback synchronously if already resolved. +// thenFunc shouldn't accept args. +// similar to whenResources in Scheduler plugin. +function syncThen(promise, thenFunc) { + // not a promise, or an already-resolved promise? + if (!promise || !promise.then || promise.state() === 'resolved') { + return $.when(thenFunc()); // resolve immediately + } + else if (thenFunc) { + return promise.then(thenFunc); + } +} + ;; var ambigDateOfMonthRegex = /^\s*\d{4}-\d\d$/; @@ -3960,7 +3974,7 @@ var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, { fillSegTag: 'div', // subclasses can override - // Builds the HTML needed for one fill segment. Generic enought o work with different types. + // Builds the HTML needed for one fill segment. Generic enough to work with different types. fillSegHtml: function(type, seg) { // custom hooks per-type @@ -8106,15 +8120,14 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, { this.calendar.freezeContentHeight(); - return this.clear().then(function() { // clear the content first (async) + return syncThen(this.clear(), function() { // clear the content first return ( _this.displaying = - $.when(_this.displayView(date)) // displayView might return a promise - .then(function() { - _this.forceScroll(_this.computeInitialScroll(scrollState)); - _this.calendar.unfreezeContentHeight(); - _this.triggerRender(); - }) + syncThen(_this.displayView(date), function() { // displayView might return a promise + _this.forceScroll(_this.computeInitialScroll(scrollState)); + _this.calendar.unfreezeContentHeight(); + _this.triggerRender(); + }) ); }); }, @@ -8128,7 +8141,7 @@ var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, { var displaying = this.displaying; if (displaying) { // previously displayed, or in the process of being displayed? - return displaying.then(function() { // wait for the display to finish + return syncThen(displaying, function() { // wait for the display to finish _this.displaying = null; _this.clearEvents(); return _this.clearView(); // might return a promise. chain it @@ -9321,6 +9334,7 @@ function Calendar_constructor(element, overrides) { t.render = render; t.destroy = destroy; t.refetchEvents = refetchEvents; + t.refetchEventSources = refetchEventSources; t.reportEvents = reportEvents; t.reportEventChange = reportEventChange; t.rerenderEvents = renderEvents; // `renderEvents` serves as a rerender. an API method @@ -9511,6 +9525,7 @@ function Calendar_constructor(element, overrides) { EventManager.call(t, options); var isFetchNeeded = t.isFetchNeeded; var fetchEvents = t.fetchEvents; + var fetchEventSources = t.fetchEventSources; @@ -9750,11 +9765,16 @@ function Calendar_constructor(element, overrides) { function refetchEvents() { // can be called as an API method - destroyEvents(); // so that events are cleared before user starts waiting for AJAX fetchAndRenderEvents(); } + // TODO: move this into EventManager? + function refetchEventSources(matchInputs) { + fetchEventSources(t.getEventSourcesByMatchArray(matchInputs)); + } + + function renderEvents() { // destroys old events if previously rendered if (elementVisible()) { freezeContentHeight(); @@ -9762,13 +9782,6 @@ function Calendar_constructor(element, overrides) { unfreezeContentHeight(); } } - - - function destroyEvents() { - freezeContentHeight(); - currentView.clearEvents(); - unfreezeContentHeight(); - } function getAndRenderEvents() { @@ -9979,7 +9992,7 @@ function Calendar_constructor(element, overrides) { Calendar.defaults = { - titleRangeSeparator: ' \u2014 ', // emphasized dash + titleRangeSeparator: ' \u2013 ', // en dash monthYearFormat: 'MMMM YYYY', // required for en. other languages rely on datepicker computable option defaultTimedEventDuration: '02:00:00', @@ -10528,14 +10541,14 @@ function Header(calendar, options) { function disableButton(buttonName) { el.find('.fc-' + buttonName + '-button') - .attr('disabled', 'disabled') + .prop('disabled', true) .addClass(tm + '-state-disabled'); } function enableButton(buttonName) { el.find('.fc-' + buttonName + '-button') - .removeAttr('disabled') + .prop('disabled', false) .removeClass(tm + '-state-disabled'); } @@ -10566,8 +10579,14 @@ function EventManager(options) { // assumed to be a calendar // exports t.isFetchNeeded = isFetchNeeded; t.fetchEvents = fetchEvents; + t.fetchEventSources = fetchEventSources; + t.getEventSources = getEventSources; + t.getEventSourceById = getEventSourceById; + t.getEventSourcesByMatchArray = getEventSourcesByMatchArray; + t.getEventSourcesByMatch = getEventSourcesByMatch; t.addEventSource = addEventSource; t.removeEventSource = removeEventSource; + t.removeEventSources = removeEventSources; t.updateEvent = updateEvent; t.renderEvent = renderEvent; t.removeEvents = removeEvents; @@ -10585,8 +10604,7 @@ function EventManager(options) { // assumed to be a calendar var stickySource = { events: [] }; var sources = [ stickySource ]; var rangeStart, rangeEnd; - var currentFetchID = 0; - var pendingSourceCnt = 0; + var pendingSourceCnt = 0; // outstanding fetch requests, max one per source var cache = []; // holds events that have already been expanded @@ -10616,23 +10634,58 @@ function EventManager(options) { // assumed to be a calendar function fetchEvents(start, end) { rangeStart = start; rangeEnd = end; - cache = []; - var fetchID = ++currentFetchID; - var len = sources.length; - pendingSourceCnt = len; - for (var i=0; i<len; i++) { - fetchEventSource(sources[i], fetchID); + fetchEventSources(sources, 'reset'); + } + + + // expects an array of event source objects (the originals, not copies) + // `specialFetchType` is an optimization parameter that affects purging of the event cache. + function fetchEventSources(specificSources, specialFetchType) { + var i, source; + + if (specialFetchType === 'reset') { + cache = []; + } + else if (specialFetchType !== 'add') { + cache = excludeEventsBySources(cache, specificSources); + } + + for (i = 0; i < specificSources.length; i++) { + source = specificSources[i]; + + // already-pending sources have already been accounted for in pendingSourceCnt + if (source._status !== 'pending') { + pendingSourceCnt++; + } + + source._fetchId = (source._fetchId || 0) + 1; + source._status = 'pending'; + } + + for (i = 0; i < specificSources.length; i++) { + source = specificSources[i]; + + tryFetchEventSource(source, source._fetchId); } } - - - function fetchEventSource(source, fetchID) { + + + // fetches an event source and processes its result ONLY if it is still the current fetch. + // caller is responsible for incrementing pendingSourceCnt first. + function tryFetchEventSource(source, fetchId) { _fetchEventSource(source, function(eventInputs) { var isArraySource = $.isArray(source.events); var i, eventInput; var abstractEvent; - if (fetchID == currentFetchID) { + if ( + // is this the source's most recent fetch? + // if not, rely on an upcoming fetch of this source to decrement pendingSourceCnt + fetchId === source._fetchId && + // event source no longer valid? + source._status !== 'rejected' + ) { + source._status = 'resolved'; if (eventInputs) { for (i = 0; i < eventInputs.length; i++) { @@ -10654,13 +10707,29 @@ function EventManager(options) { // assumed to be a calendar } } - pendingSourceCnt--; - if (!pendingSourceCnt) { - reportEvents(cache); - } + decrementPendingSourceCnt(); } }); } + + + function rejectEventSource(source) { + var wasPending = source._status === 'pending'; + + source._status = 'rejected'; + + if (wasPending) { + decrementPendingSourceCnt(); + } + } + + + function decrementPendingSourceCnt() { + pendingSourceCnt--; + if (!pendingSourceCnt) { + reportEvents(cache); + } + } function _fetchEventSource(source, callback) { @@ -10776,14 +10845,13 @@ function EventManager(options) { // assumed to be a calendar /* Sources -----------------------------------------------------------------------------*/ - + function addEventSource(sourceInput) { var source = buildEventSource(sourceInput); if (source) { sources.push(source); - pendingSourceCnt++; - fetchEventSource(source, currentFetchID); // will eventually call reportEvents + fetchEventSources([ source ], 'add'); // will eventually call reportEvents } } @@ -10833,19 +10901,120 @@ function EventManager(options) { // assumed to be a calendar } - function removeEventSource(source) { - sources = $.grep(sources, function(src) { - return !isSourcesEqual(src, source); - }); - // remove all client events from that source - cache = $.grep(cache, function(e) { - return !isSourcesEqual(e.source, source); - }); + function removeEventSource(matchInput) { + removeSpecificEventSources( + getEventSourcesByMatch(matchInput) + ); + } + + + // if called with no arguments, removes all. + function removeEventSources(matchInputs) { + if (matchInputs == null) { + removeSpecificEventSources(sources, true); // isAll=true + } + else { + removeSpecificEventSources( + getEventSourcesByMatchArray(matchInputs) + ); + } + } + + + function removeSpecificEventSources(targetSources, isAll) { + var i; + + // cancel pending requests + for (i = 0; i < targetSources.length; i++) { + rejectEventSource(targetSources[i]); + } + + if (isAll) { // an optimization + sources = []; + cache = []; + } + else { + // remove from persisted source list + sources = $.grep(sources, function(source) { + for (i = 0; i < targetSources.length; i++) { + if (source === targetSources[i]) { + return false; // exclude + } + } + return true; // include + }); + + cache = excludeEventsBySources(cache, targetSources); + } + reportEvents(cache); } - function isSourcesEqual(source1, source2) { + function getEventSources() { + return sources.slice(1); // returns a shallow copy of sources with stickySource removed + } + + + function getEventSourceById(id) { + return $.grep(sources, function(source) { + return source.id && source.id === id; + })[0]; + } + + + // like getEventSourcesByMatch, but accepts multple match criteria (like multiple IDs) + function getEventSourcesByMatchArray(matchInputs) { + + // coerce into an array + if (!matchInputs) { + matchInputs = []; + } + else if (!$.isArray(matchInputs)) { + matchInputs = [ matchInputs ]; + } + + var matchingSources = []; + var i; + + // resolve raw inputs to real event source objects + for (i = 0; i < matchInputs.length; i++) { + matchingSources.push.apply( // append + matchingSources, + getEventSourcesByMatch(matchInputs[i]) + ); + } + + return matchingSources; + } + + + // matchInput can either by a real event source object, an ID, or the function/URL for the source. + // returns an array of matching source objects. + function getEventSourcesByMatch(matchInput) { + var i, source; + + // given an proper event source object + for (i = 0; i < sources.length; i++) { + source = sources[i]; + if (source === matchInput) { + return [ source ]; + } + } + + // an ID match + source = getEventSourceById(matchInput); + if (source) { + return [ source ]; + } + + return $.grep(sources, function(source) { + return isSourcesEquivalent(matchInput, source); + }); + } + + + function isSourcesEquivalent(source1, source2) { return source1 && source2 && getSourcePrimitive(source1) == getSourcePrimitive(source2); } @@ -10858,6 +11027,20 @@ function EventManager(options) { // assumed to be a calendar ) || source; // the given argument *is* the primitive } + + + // util + // returns a filtered array without events that are part of any of the given sources + function excludeEventsBySources(specificEvents, specificSources) { + return $.grep(specificEvents, function(event) { + for (var i = 0; i < specificSources.length; i++) { + if (event.source === specificSources[i]) { + return false; // exclude + } + } + return true; // keep + }); + } diff --git a/library/fullcalendar/fullcalendar.min.css b/library/fullcalendar/fullcalendar.min.css index 3a251eb19..9f395b445 100644 --- a/library/fullcalendar/fullcalendar.min.css +++ b/library/fullcalendar/fullcalendar.min.css @@ -1,5 +1,5 @@ /*! - * FullCalendar v2.7.3 Stylesheet + * FullCalendar v2.8.0 Stylesheet * Docs & License: http://fullcalendar.io/ * (c) 2016 Adam Shaw - */.fc-bgevent,.fc-highlight{opacity:.3;filter:alpha(opacity=30)}.fc-icon,body .fc{font-size:1em}.fc-button-group,.fc-icon{display:inline-block}.fc-bg,.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc-icon,.fc-unselectable{-khtml-user-select:none;-webkit-touch-callout:none}.fc .fc-axis,.fc button,.fc-time-grid-event .fc-time,.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}.fc th,.fc-basic-view .fc-week-number,.fc-icon,.fc-toolbar{text-align:center}.fc-unthemed .fc-content,.fc-unthemed .fc-divider,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed .fc-popover .fc-header .fc-close{color:#666}.fc-unthemed .fc-today{background:#fcf8e3}.fc-highlight{background:#bce8f1}.fc-bgevent{background:#8fdf82}.fc-nonbusiness{background:#d7d7d7}.fc-icon{height:1em;line-height:1em;overflow:hidden;font-family:"Courier New",Courier,monospace;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fc-icon:after{position:relative}.fc-icon-left-single-arrow:after{content:"\02039";font-weight:700;font-size:200%;top:-7%}.fc-icon-right-single-arrow:after{content:"\0203A";font-weight:700;font-size:200%;top:-7%}.fc-icon-left-double-arrow:after{content:"\000AB";font-size:160%;top:-7%}.fc-icon-right-double-arrow:after{content:"\000BB";font-size:160%;top:-7%}.fc-icon-left-triangle:after{content:"\25C4";font-size:125%;top:3%}.fc-icon-right-triangle:after{content:"\25BA";font-size:125%;top:3%}.fc-icon-down-triangle:after{content:"\25BC";font-size:125%;top:2%}.fc-icon-x:after{content:"\000D7";font-size:200%;top:6%}.fc button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;height:2.1em;padding:0 .6em;font-size:1em;cursor:pointer}.fc button::-moz-focus-inner{margin:0;padding:0}.fc-state-default{border:1px solid;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.fc-state-default.fc-corner-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.fc-state-default.fc-corner-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.fc button .fc-icon{position:relative;top:-.05em;margin:0 .2em;vertical-align:middle}.fc-state-active,.fc-state-disabled,.fc-state-down,.fc-state-hover{color:#333;background-color:#e6e6e6}.fc-state-hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fc-state-active,.fc-state-down{background-color:#ccc;background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.fc-state-disabled{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.fc-event.fc-draggable,.fc-event[href],.fc-popover .fc-header .fc-close{cursor:pointer}.fc .fc-button-group>*{float:left;margin:0 0 0 -1px}.fc .fc-button-group>:first-child{margin-left:0}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{padding:2px 4px}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-ltr .fc-popover .fc-header .fc-title,.fc-rtl .fc-popover .fc-header .fc-close{float:left}.fc-ltr .fc-popover .fc-header .fc-close,.fc-rtl .fc-popover .fc-header .fc-title{float:right}.fc-unthemed .fc-popover{border-width:1px;border-style:solid}.fc-unthemed .fc-popover .fc-header .fc-close{font-size:.9em;margin-top:2px}.fc-popover>.ui-widget-header+.ui-widget-content{border-top:0}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-bg table,.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-clear{clear:both}.fc-bg,.fc-bgevent-skeleton,.fc-helper-skeleton,.fc-highlight-skeleton{position:absolute;top:0;left:0;right:0}.fc table{width:100%;table-layout:fixed;border-collapse:collapse;border-spacing:0;font-size:1em}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-helper-skeleton{z-index:5}.fc-row .fc-content-skeleton td,.fc-row .fc-helper-skeleton td{background:0 0;border-color:transparent;border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-helper-skeleton tbody td{border-top:0}.fc-scroller{-webkit-overflow-scrolling:touch}.fc-row.fc-rigid,.fc-time-grid-event{overflow:hidden}.fc-scroller>.fc-day-grid,.fc-scroller>.fc-time-grid{position:relative;width:100%}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.3;border-radius:3px;border:1px solid #3a87ad;background-color:#3a87ad;font-weight:400}.fc-event,.fc-event:hover,.ui-widget .fc-event{color:#fff;text-decoration:none}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-bg{z-index:1;background:#fff;opacity:.25;filter:alpha(opacity=25)}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:4;display:none}.fc-event.fc-allow-mouse-resize .fc-resizer,.fc-event.fc-selected .fc-resizer{display:block}.fc-event.fc-selected .fc-resizer:before{content:"";position:absolute;z-index:9999;top:50%;left:50%;width:40px;height:40px;margin-left:-20px;margin-top:-20px}.fc-event.fc-selected{z-index:9999!important;box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event.fc-selected.fc-dragging{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-h-event.fc-selected:before{content:"";position:absolute;z-index:3;top:-10px;bottom:-10px;left:0;right:0}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-ltr .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-end-resizer{cursor:w-resize;left:-1px}.fc-ltr .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-start-resizer{cursor:e-resize;right:-1px}.fc-h-event.fc-allow-mouse-resize .fc-resizer{width:7px;top:-1px;bottom:-1px}.fc-h-event.fc-selected .fc-resizer{border-radius:4px;border-width:1px;width:6px;height:6px;border-style:solid;border-color:inherit;background:#fff;top:50%;margin-top:-4px}.fc-ltr .fc-h-event.fc-selected .fc-start-resizer,.fc-rtl .fc-h-event.fc-selected .fc-end-resizer{margin-left:-4px}.fc-ltr .fc-h-event.fc-selected .fc-end-resizer,.fc-rtl .fc-h-event.fc-selected .fc-start-resizer{margin-right:-4px}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}.fc-day-grid-event.fc-selected:after{content:"";position:absolute;z-index:1;top:-1px;right:-1px;bottom:-1px;left:-1px;background:#000;opacity:.25;filter:alpha(opacity=25)}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer{margin-left:-2px}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer{margin-right:-2px}a.fc-more{margin:1px 3px;font-size:.85em;cursor:pointer;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc-limited{display:none}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-now-indicator{position:absolute;border:0 solid red}.fc-unselectable{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.fc-toolbar{margin-bottom:1em}.fc-toolbar .fc-left{float:left}.fc-toolbar .fc-right{float:right}.fc-toolbar .fc-center{display:inline-block}.fc .fc-toolbar>*>*{float:left;margin-left:.75em}.fc .fc-toolbar>*>:first-child{margin-left:0}.fc-toolbar h2{margin:0}.fc-toolbar button{position:relative}.fc-toolbar .fc-state-hover,.fc-toolbar .ui-state-hover{z-index:2}.fc-toolbar .fc-state-down{z-index:3}.fc-toolbar .fc-state-active,.fc-toolbar .ui-state-active{z-index:4}.fc-toolbar button:focus{z-index:5}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}.fc-basicDay-view .fc-content-skeleton,.fc-basicWeek-view .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc-basic-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-basic-view .fc-day-number,.fc-basic-view .fc-week-number{padding:0 2px}.fc-basic-view td.fc-day-number,.fc-basic-view td.fc-week-number span{padding-top:2px;padding-bottom:2px}.fc-basic-view .fc-week-number span{display:inline-block;min-width:1.25em}.fc-ltr .fc-basic-view .fc-day-number{text-align:right}.fc-rtl .fc-basic-view .fc-day-number{text-align:left}.fc-day-number.fc-other-month{opacity:.3;filter:alpha(opacity=30)}.fc-agenda-view .fc-day-grid{position:relative;z-index:2}.fc-agenda-view .fc-day-grid .fc-row{min-height:3em}.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.ui-widget td.fc-axis{font-weight:400}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-content-col{position:relative}.fc-time-grid .fc-content-skeleton{position:absolute;z-index:3;top:0;left:0;right:0}.fc-time-grid .fc-business-container{position:relative;z-index:1}.fc-time-grid .fc-bgevent-container{position:relative;z-index:2}.fc-time-grid .fc-highlight-container{z-index:3;position:relative}.fc-time-grid .fc-event-container{position:relative;z-index:4}.fc-time-grid .fc-now-indicator-line{z-index:5}.fc-time-grid .fc-helper-container{position:relative;z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-slats .ui-widget-content{background:0 0}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-v-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-v-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event.fc-selected{overflow:visible}.fc-time-grid-event.fc-selected .fc-bg{display:none}.fc-time-grid-event .fc-content{overflow:hidden}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:"\000A0-\000A0"}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after{content:"="}.fc-time-grid-event.fc-selected .fc-resizer{border-radius:5px;border-width:1px;width:8px;height:8px;border-style:solid;border-color:inherit;background:#fff;left:50%;margin-left:-5px;bottom:-5px}.fc-time-grid .fc-now-indicator-line{border-top-width:1px;left:0;right:0}.fc-time-grid .fc-now-indicator-arrow{margin-top:-5px}.fc-ltr .fc-time-grid .fc-now-indicator-arrow{left:0;border-width:5px 0 5px 6px;border-top-color:transparent;border-bottom-color:transparent}.fc-rtl .fc-time-grid .fc-now-indicator-arrow{right:0;border-width:5px 6px 5px 0;border-top-color:transparent;border-bottom-color:transparent} \ No newline at end of file + */.fc-bgevent,.fc-highlight{opacity:.3;filter:alpha(opacity=30)}.fc-icon,body .fc{font-size:1em}.fc-button-group,.fc-icon{display:inline-block}.fc-bg,.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc-icon,.fc-unselectable{-khtml-user-select:none;-webkit-touch-callout:none}.fc .fc-axis,.fc button,.fc-time-grid-event .fc-time,.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}.fc th,.fc-basic-view .fc-week-number,.fc-icon,.fc-toolbar{text-align:center}.fc-unthemed .fc-content,.fc-unthemed .fc-divider,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed .fc-popover .fc-header .fc-close{color:#666}.fc-unthemed .fc-today{background:#fcf8e3}.fc-highlight{background:#bce8f1}.fc-bgevent{background:#8fdf82}.fc-nonbusiness{background:#d7d7d7}.fc-icon{height:1em;line-height:1em;overflow:hidden;font-family:"Courier New",Courier,monospace;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fc-icon:after{position:relative}.fc-icon-left-single-arrow:after{content:"\02039";font-weight:700;font-size:200%;top:-7%}.fc-icon-right-single-arrow:after{content:"\0203A";font-weight:700;font-size:200%;top:-7%}.fc-icon-left-double-arrow:after{content:"\000AB";font-size:160%;top:-7%}.fc-icon-right-double-arrow:after{content:"\000BB";font-size:160%;top:-7%}.fc-icon-left-triangle:after{content:"\25C4";font-size:125%;top:3%}.fc-icon-right-triangle:after{content:"\25BA";font-size:125%;top:3%}.fc-icon-down-triangle:after{content:"\25BC";font-size:125%;top:2%}.fc-icon-x:after{content:"\000D7";font-size:200%;top:6%}.fc button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;height:2.1em;padding:0 .6em;font-size:1em;cursor:pointer}.fc button::-moz-focus-inner{margin:0;padding:0}.fc-state-default{border:1px solid;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.fc-state-default.fc-corner-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.fc-state-default.fc-corner-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.fc button .fc-icon{position:relative;top:-.05em;margin:0 .2em;vertical-align:middle}.fc-state-active,.fc-state-disabled,.fc-state-down,.fc-state-hover{color:#333;background-color:#e6e6e6}.fc-state-hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fc-state-active,.fc-state-down{background-color:#ccc;background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.fc-state-disabled{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.fc-event.fc-draggable,.fc-event[href],.fc-popover .fc-header .fc-close{cursor:pointer}.fc .fc-button-group>*{float:left;margin:0 0 0 -1px}.fc .fc-button-group>:first-child{margin-left:0}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{padding:2px 4px}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-ltr .fc-popover .fc-header .fc-title,.fc-rtl .fc-popover .fc-header .fc-close{float:left}.fc-ltr .fc-popover .fc-header .fc-close,.fc-rtl .fc-popover .fc-header .fc-title{float:right}.fc-unthemed .fc-popover{border-width:1px;border-style:solid}.fc-unthemed .fc-popover .fc-header .fc-close{font-size:.9em;margin-top:2px}.fc-popover>.ui-widget-header+.ui-widget-content{border-top:0}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-bg table,.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-clear{clear:both}.fc-bg,.fc-bgevent-skeleton,.fc-helper-skeleton,.fc-highlight-skeleton{position:absolute;top:0;left:0;right:0}.fc table{width:100%;box-sizing:border-box;table-layout:fixed;border-collapse:collapse;border-spacing:0;font-size:1em}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-helper-skeleton{z-index:5}.fc-row .fc-content-skeleton td,.fc-row .fc-helper-skeleton td{background:0 0;border-color:transparent;border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-helper-skeleton tbody td{border-top:0}.fc-scroller{-webkit-overflow-scrolling:touch}.fc-row.fc-rigid,.fc-time-grid-event{overflow:hidden}.fc-scroller>.fc-day-grid,.fc-scroller>.fc-time-grid{position:relative;width:100%}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.3;border-radius:3px;border:1px solid #3a87ad;background-color:#3a87ad;font-weight:400}.fc-event,.fc-event:hover,.ui-widget .fc-event{color:#fff;text-decoration:none}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-bg{z-index:1;background:#fff;opacity:.25;filter:alpha(opacity=25)}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:4;display:none}.fc-event.fc-allow-mouse-resize .fc-resizer,.fc-event.fc-selected .fc-resizer{display:block}.fc-event.fc-selected .fc-resizer:before{content:"";position:absolute;z-index:9999;top:50%;left:50%;width:40px;height:40px;margin-left:-20px;margin-top:-20px}.fc-event.fc-selected{z-index:9999!important;box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event.fc-selected.fc-dragging{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-h-event.fc-selected:before{content:"";position:absolute;z-index:3;top:-10px;bottom:-10px;left:0;right:0}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-ltr .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-end-resizer{cursor:w-resize;left:-1px}.fc-ltr .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-start-resizer{cursor:e-resize;right:-1px}.fc-h-event.fc-allow-mouse-resize .fc-resizer{width:7px;top:-1px;bottom:-1px}.fc-h-event.fc-selected .fc-resizer{border-radius:4px;border-width:1px;width:6px;height:6px;border-style:solid;border-color:inherit;background:#fff;top:50%;margin-top:-4px}.fc-ltr .fc-h-event.fc-selected .fc-start-resizer,.fc-rtl .fc-h-event.fc-selected .fc-end-resizer{margin-left:-4px}.fc-ltr .fc-h-event.fc-selected .fc-end-resizer,.fc-rtl .fc-h-event.fc-selected .fc-start-resizer{margin-right:-4px}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}.fc-day-grid-event.fc-selected:after{content:"";position:absolute;z-index:1;top:-1px;right:-1px;bottom:-1px;left:-1px;background:#000;opacity:.25;filter:alpha(opacity=25)}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer{margin-left:-2px}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer{margin-right:-2px}a.fc-more{margin:1px 3px;font-size:.85em;cursor:pointer;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc-limited{display:none}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-now-indicator{position:absolute;border:0 solid red}.fc-unselectable{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.fc-toolbar{margin-bottom:1em}.fc-toolbar .fc-left{float:left}.fc-toolbar .fc-right{float:right}.fc-toolbar .fc-center{display:inline-block}.fc .fc-toolbar>*>*{float:left;margin-left:.75em}.fc .fc-toolbar>*>:first-child{margin-left:0}.fc-toolbar h2{margin:0}.fc-toolbar button{position:relative}.fc-toolbar .fc-state-hover,.fc-toolbar .ui-state-hover{z-index:2}.fc-toolbar .fc-state-down{z-index:3}.fc-toolbar .fc-state-active,.fc-toolbar .ui-state-active{z-index:4}.fc-toolbar button:focus{z-index:5}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}.fc-basicDay-view .fc-content-skeleton,.fc-basicWeek-view .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc-basic-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-basic-view .fc-day-number,.fc-basic-view .fc-week-number{padding:0 2px}.fc-basic-view td.fc-day-number,.fc-basic-view td.fc-week-number span{padding-top:2px;padding-bottom:2px}.fc-basic-view .fc-week-number span{display:inline-block;min-width:1.25em}.fc-ltr .fc-basic-view .fc-day-number{text-align:right}.fc-rtl .fc-basic-view .fc-day-number{text-align:left}.fc-day-number.fc-other-month{opacity:.3;filter:alpha(opacity=30)}.fc-agenda-view .fc-day-grid{position:relative;z-index:2}.fc-agenda-view .fc-day-grid .fc-row{min-height:3em}.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.ui-widget td.fc-axis{font-weight:400}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-content-col{position:relative}.fc-time-grid .fc-content-skeleton{position:absolute;z-index:3;top:0;left:0;right:0}.fc-time-grid .fc-business-container{position:relative;z-index:1}.fc-time-grid .fc-bgevent-container{position:relative;z-index:2}.fc-time-grid .fc-highlight-container{z-index:3;position:relative}.fc-time-grid .fc-event-container{position:relative;z-index:4}.fc-time-grid .fc-now-indicator-line{z-index:5}.fc-time-grid .fc-helper-container{position:relative;z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-slats .ui-widget-content{background:0 0}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-v-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-v-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event.fc-selected{overflow:visible}.fc-time-grid-event.fc-selected .fc-bg{display:none}.fc-time-grid-event .fc-content{overflow:hidden}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:"\000A0-\000A0"}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after{content:"="}.fc-time-grid-event.fc-selected .fc-resizer{border-radius:5px;border-width:1px;width:8px;height:8px;border-style:solid;border-color:inherit;background:#fff;left:50%;margin-left:-5px;bottom:-5px}.fc-time-grid .fc-now-indicator-line{border-top-width:1px;left:0;right:0}.fc-time-grid .fc-now-indicator-arrow{margin-top:-5px}.fc-ltr .fc-time-grid .fc-now-indicator-arrow{left:0;border-width:5px 0 5px 6px;border-top-color:transparent;border-bottom-color:transparent}.fc-rtl .fc-time-grid .fc-now-indicator-arrow{right:0;border-width:5px 6px 5px 0;border-top-color:transparent;border-bottom-color:transparent} \ No newline at end of file diff --git a/library/fullcalendar/fullcalendar.min.js b/library/fullcalendar/fullcalendar.min.js index f27380229..d05408974 100644 --- a/library/fullcalendar/fullcalendar.min.js +++ b/library/fullcalendar/fullcalendar.min.js @@ -1,9 +1,9 @@ /*! - * FullCalendar v2.7.3 + * FullCalendar v2.8.0 * Docs & License: http://fullcalendar.io/ * (c) 2016 Adam Shaw */ -!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("moment")):a(jQuery,moment)}(function(a,b){function c(a){return W(a,Xa)}function d(b){var c,d={views:b.views||{}};return a.each(b,function(b,e){"views"!=b&&(a.isPlainObject(e)&&!/(time|duration|interval)$/i.test(b)&&-1==a.inArray(b,Xa)?(c=null,a.each(e,function(a,e){/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(a)?(d.views[a]||(d.views[a]={}),d.views[a][b]=e):(c||(c={}),c[a]=e)}),c&&(d[b]=c)):d[b]=e)}),d}function e(a,b){b.left&&a.css({"border-left-width":1,"margin-left":b.left-1}),b.right&&a.css({"border-right-width":1,"margin-right":b.right-1})}function f(a){a.css({"margin-left":"","margin-right":"","border-left-width":"","border-right-width":""})}function g(){a("body").addClass("fc-not-allowed")}function h(){a("body").removeClass("fc-not-allowed")}function i(b,c,d){var e=Math.floor(c/b.length),f=Math.floor(c-e*(b.length-1)),g=[],h=[],i=[],k=0;j(b),b.each(function(c,d){var j=c===b.length-1?f:e,l=a(d).outerHeight(!0);j>l?(g.push(d),h.push(l),i.push(a(d).height())):k+=l}),d&&(c-=k,e=Math.floor(c/g.length),f=Math.floor(c-e*(g.length-1))),a(g).each(function(b,c){var d=b===g.length-1?f:e,j=h[b],k=i[b],l=d-(j-k);d>j&&a(c).height(l)})}function j(a){a.height("")}function k(b){var c=0;return b.find("> span").each(function(b,d){var e=a(d).outerWidth();e>c&&(c=e)}),c++,b.width(c),c}function l(a,b){var c,d=a.add(b);return d.css({position:"relative",left:-1}),c=a.outerHeight()-b.outerHeight(),d.css({position:"",left:""}),c}function m(b){var c=b.css("position"),d=b.parents().filter(function(){var b=a(this);return/(auto|scroll)/.test(b.css("overflow")+b.css("overflow-y")+b.css("overflow-x"))}).eq(0);return"fixed"!==c&&d.length?d:a(b[0].ownerDocument||document)}function n(a,b){var c=a.offset(),d=c.left-(b?b.left:0),e=c.top-(b?b.top:0);return{left:d,right:d+a.outerWidth(),top:e,bottom:e+a.outerHeight()}}function o(a,b){var c=a.offset(),d=q(a),e=c.left+t(a,"border-left-width")+d.left-(b?b.left:0),f=c.top+t(a,"border-top-width")+d.top-(b?b.top:0);return{left:e,right:e+a[0].clientWidth,top:f,bottom:f+a[0].clientHeight}}function p(a,b){var c=a.offset(),d=c.left+t(a,"border-left-width")+t(a,"padding-left")-(b?b.left:0),e=c.top+t(a,"border-top-width")+t(a,"padding-top")-(b?b.top:0);return{left:d,right:d+a.width(),top:e,bottom:e+a.height()}}function q(a){var b=a.innerWidth()-a[0].clientWidth,c={left:0,right:0,top:0,bottom:a.innerHeight()-a[0].clientHeight};return r()&&"rtl"==a.css("direction")?c.left=b:c.right=b,c}function r(){return null===Ya&&(Ya=s()),Ya}function s(){var b=a("<div><div/></div>").css({position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}).appendTo("body"),c=b.children(),d=c.offset().left>b.offset().left;return b.remove(),d}function t(a,b){return parseFloat(a.css(b))||0}function u(a){return 1==a.which&&!a.ctrlKey}function v(a){if(void 0!==a.pageX)return a.pageX;var b=a.originalEvent.touches;return b?b[0].pageX:void 0}function w(a){if(void 0!==a.pageY)return a.pageY;var b=a.originalEvent.touches;return b?b[0].pageY:void 0}function x(a){return/^touch/.test(a.type)}function y(a){a.addClass("fc-unselectable").on("selectstart",z)}function z(a){a.preventDefault()}function A(a){return window.addEventListener?(window.addEventListener("scroll",a,!0),!0):!1}function B(a){return window.removeEventListener?(window.removeEventListener("scroll",a,!0),!0):!1}function C(a,b){var c={left:Math.max(a.left,b.left),right:Math.min(a.right,b.right),top:Math.max(a.top,b.top),bottom:Math.min(a.bottom,b.bottom)};return c.left<c.right&&c.top<c.bottom?c:!1}function D(a,b){return{left:Math.min(Math.max(a.left,b.left),b.right),top:Math.min(Math.max(a.top,b.top),b.bottom)}}function E(a){return{left:(a.left+a.right)/2,top:(a.top+a.bottom)/2}}function F(a,b){return{left:a.left-b.left,top:a.top-b.top}}function G(b){var c,d,e=[],f=[];for("string"==typeof b?f=b.split(/\s*,\s*/):"function"==typeof b?f=[b]:a.isArray(b)&&(f=b),c=0;c<f.length;c++)d=f[c],"string"==typeof d?e.push("-"==d.charAt(0)?{field:d.substring(1),order:-1}:{field:d,order:1}):"function"==typeof d&&e.push({func:d});return e}function H(a,b,c){var d,e;for(d=0;d<c.length;d++)if(e=I(a,b,c[d]))return e;return 0}function I(a,b,c){return c.func?c.func(a,b):J(a[c.field],b[c.field])*(c.order||1)}function J(b,c){return b||c?null==c?-1:null==b?1:"string"===a.type(b)||"string"===a.type(c)?String(b).localeCompare(String(c)):b-c:0}function K(a,b){var c,d,e,f,g=a.start,h=a.end,i=b.start,j=b.end;return h>i&&j>g?(g>=i?(c=g.clone(),e=!0):(c=i.clone(),e=!1),j>=h?(d=h.clone(),f=!0):(d=j.clone(),f=!1),{start:c,end:d,isStart:e,isEnd:f}):void 0}function L(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days"),ms:a.time()-c.time()})}function M(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days")})}function N(a,c,d){return b.duration(Math.round(a.diff(c,d,!0)),d)}function O(a,b){var c,d,e;for(c=0;c<$a.length&&(d=$a[c],e=P(d,a,b),!(e>=1&&ha(e)));c++);return d}function P(a,c,d){return null!=d?d.diff(c,a,!0):b.isDuration(c)?c.as(a):c.end.diff(c.start,a,!0)}function Q(a,b,c){var d;return T(c)?(b-a)/c:(d=c.asMonths(),Math.abs(d)>=1&&ha(d)?b.diff(a,"months",!0)/d:b.diff(a,"days",!0)/c.asDays())}function R(a,b){var c,d;return T(a)||T(b)?a/b:(c=a.asMonths(),d=b.asMonths(),Math.abs(c)>=1&&ha(c)&&Math.abs(d)>=1&&ha(d)?c/d:a.asDays()/b.asDays())}function S(a,c){var d;return T(a)?b.duration(a*c):(d=a.asMonths(),Math.abs(d)>=1&&ha(d)?b.duration({months:d*c}):b.duration({days:a.asDays()*c}))}function T(a){return Boolean(a.hours()||a.minutes()||a.seconds()||a.milliseconds())}function U(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function V(a){return/^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(a)}function W(a,b){var c,d,e,f,g,h,i={};if(b)for(c=0;c<b.length;c++){for(d=b[c],e=[],f=a.length-1;f>=0;f--)if(g=a[f][d],"object"==typeof g)e.unshift(g);else if(void 0!==g){i[d]=g;break}e.length&&(i[d]=W(e))}for(c=a.length-1;c>=0;c--){h=a[c];for(d in h)d in i||(i[d]=h[d])}return i}function X(a){var b=function(){};return b.prototype=a,new b}function Y(a,b){for(var c in a)$(a,c)&&(b[c]=a[c])}function Z(a,b){var c,d,e=["constructor","toString","valueOf"];for(c=0;c<e.length;c++)d=e[c],a[d]!==Object.prototype[d]&&(b[d]=a[d])}function $(a,b){return cb.call(a,b)}function _(b){return/undefined|null|boolean|number|string/.test(a.type(b))}function aa(b,c,d){if(a.isFunction(b)&&(b=[b]),b){var e,f;for(e=0;e<b.length;e++)f=b[e].apply(c,d)||f;return f}}function ba(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]}function ca(a){return(a+"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"<br />")}function da(a){return a.replace(/&.*?;/g,"")}function ea(b){var c=[];return a.each(b,function(a,b){null!=b&&c.push(a+":"+b)}),c.join(";")}function fa(a){return a.charAt(0).toUpperCase()+a.slice(1)}function ga(a,b){return a-b}function ha(a){return a%1===0}function ia(a,b){var c=a[b];return function(){return c.apply(a,arguments)}}function ja(a,b,c){var d,e,f,g,h,i=function(){var j=+new Date-g;b>j?d=setTimeout(i,b-j):(d=null,c||(h=a.apply(f,e),f=e=null))};return function(){f=this,e=arguments,g=+new Date;var j=c&&!d;return d||(d=setTimeout(i,b)),j&&(h=a.apply(f,e),f=e=null),h}}function ka(c,d,e){var f,g,h,i,j=c[0],k=1==c.length&&"string"==typeof j;return b.isMoment(j)?(i=b.apply(null,c),ma(j,i)):U(j)||void 0===j?i=b.apply(null,c):(f=!1,g=!1,k?db.test(j)?(j+="-01",c=[j],f=!0,g=!0):(h=eb.exec(j))&&(f=!h[5],g=!0):a.isArray(j)&&(g=!0),i=d||f?b.utc.apply(b,c):b.apply(null,c),f?(i._ambigTime=!0,i._ambigZone=!0):e&&(g?i._ambigZone=!0:k&&(i.utcOffset?i.utcOffset(j):i.zone(j)))),i._fullCalendar=!0,i}function la(a,c){var d,e,f=!1,g=!1,h=a.length,i=[];for(d=0;h>d;d++)e=a[d],b.isMoment(e)||(e=Va.moment.parseZone(e)),f=f||e._ambigTime,g=g||e._ambigZone,i.push(e);for(d=0;h>d;d++)e=i[d],c||!f||e._ambigTime?g&&!e._ambigZone&&(i[d]=e.clone().stripZone()):i[d]=e.clone().stripTime();return i}function ma(a,b){a._ambigTime?b._ambigTime=!0:b._ambigTime&&(b._ambigTime=!1),a._ambigZone?b._ambigZone=!0:b._ambigZone&&(b._ambigZone=!1)}function na(a,b){a.year(b[0]||0).month(b[1]||0).date(b[2]||0).hours(b[3]||0).minutes(b[4]||0).seconds(b[5]||0).milliseconds(b[6]||0)}function oa(a,b){return gb.format.call(a,b)}function pa(a,b){return qa(a,va(b))}function qa(a,b){var c,d="";for(c=0;c<b.length;c++)d+=ra(a,b[c]);return d}function ra(a,b){var c,d;return"string"==typeof b?b:(c=b.token)?hb[c]?hb[c](a):oa(a,c):b.maybe&&(d=qa(a,b.maybe),d.match(/[1-9]/))?d:""}function sa(a,b,c,d,e){var f;return a=Va.moment.parseZone(a),b=Va.moment.parseZone(b),f=(a.localeData||a.lang).call(a),c=f.longDateFormat(c)||c,d=d||" - ",ta(a,b,va(c),d,e)}function ta(a,b,c,d,e){var f,g,h,i,j=a.clone().stripZone(),k=b.clone().stripZone(),l="",m="",n="",o="",p="";for(g=0;g<c.length&&(f=ua(a,b,j,k,c[g]),f!==!1);g++)l+=f;for(h=c.length-1;h>g&&(f=ua(a,b,j,k,c[h]),f!==!1);h--)m=f+m;for(i=g;h>=i;i++)n+=ra(a,c[i]),o+=ra(b,c[i]);return(n||o)&&(p=e?o+d+n:n+d+o),l+p+m}function ua(a,b,c,d,e){var f,g;return"string"==typeof e?e:(f=e.token)&&(g=ib[f.charAt(0)],g&&c.isSame(d,g))?oa(a,f):!1}function va(a){return a in jb?jb[a]:jb[a]=wa(a)}function wa(a){for(var b,c=[],d=/\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;b=d.exec(a);)b[1]?c.push(b[1]):b[2]?c.push({maybe:wa(b[2])}):b[3]?c.push({token:b[3]}):b[5]&&c.push(b[5]);return c}function xa(){}function ya(a,b){var c;return $(b,"constructor")&&(c=b.constructor),"function"!=typeof c&&(c=b.constructor=function(){a.apply(this,arguments)}),c.prototype=X(a.prototype),Y(b,c.prototype),Z(b,c.prototype),Y(a,c),c}function za(a,b){Y(b,a.prototype)}function Aa(a,b){return a||b?a&&b?a.component===b.component&&Ba(a,b)&&Ba(b,a):!1:!0}function Ba(a,b){for(var c in a)if(!/^(component|left|right|top|bottom)$/.test(c)&&a[c]!==b[c])return!1;return!0}function Ca(a){var b=Ea(a);return"background"===b||"inverse-background"===b}function Da(a){return"inverse-background"===Ea(a)}function Ea(a){return ba((a.source||{}).rendering,a.rendering)}function Fa(a){var b,c,d={};for(b=0;b<a.length;b++)c=a[b],(d[c._id]||(d[c._id]=[])).push(c);return d}function Ga(a,b){return a.start-b.start}function Ha(c){var d,e,f,g,h=Va.dataAttrPrefix;return h&&(h+="-"),d=c.data(h+"event")||null,d&&(d="object"==typeof d?a.extend({},d):{},e=d.start,null==e&&(e=d.time),f=d.duration,g=d.stick,delete d.start,delete d.time,delete d.duration,delete d.stick),null==e&&(e=c.data(h+"start")),null==e&&(e=c.data(h+"time")),null==f&&(f=c.data(h+"duration")),null==g&&(g=c.data(h+"stick")),e=null!=e?b.duration(e):null,f=null!=f?b.duration(f):null,g=Boolean(g),{eventProps:d,startTime:e,duration:f,stick:g}}function Ia(a,b){var c,d;for(c=0;c<b.length;c++)if(d=b[c],d.leftCol<=a.rightCol&&d.rightCol>=a.leftCol)return!0;return!1}function Ja(a,b){return a.leftCol-b.leftCol}function Ka(a){var b,c,d,e=[];for(b=0;b<a.length;b++){for(c=a[b],d=0;d<e.length&&Na(c,e[d]).length;d++);c.level=d,(e[d]||(e[d]=[])).push(c)}return e}function La(a){var b,c,d,e,f;for(b=0;b<a.length;b++)for(c=a[b],d=0;d<c.length;d++)for(e=c[d],e.forwardSegs=[],f=b+1;f<a.length;f++)Na(e,a[f],e.forwardSegs)}function Ma(a){var b,c,d=a.forwardSegs,e=0;if(void 0===a.forwardPressure){for(b=0;b<d.length;b++)c=d[b],Ma(c),e=Math.max(e,1+c.forwardPressure);a.forwardPressure=e}}function Na(a,b,c){c=c||[];for(var d=0;d<b.length;d++)Oa(a,b[d])&&c.push(b[d]);return c}function Oa(a,b){return a.bottom>b.top&&a.top<b.bottom}function Pa(c,d){function e(){T?h()&&(k(),i()):f()}function f(){U=O.theme?"ui":"fc",c.addClass("fc"),O.isRTL?c.addClass("fc-rtl"):c.addClass("fc-ltr"),O.theme?c.addClass("ui-widget"):c.addClass("fc-unthemed"),T=a("<div class='fc-view-container'/>").prependTo(c),R=N.header=new Sa(N,O),S=R.render(),S&&c.prepend(S),i(O.defaultView),O.handleWindowResize&&(Y=ja(m,O.windowResizeDelay),a(window).resize(Y))}function g(){V&&V.removeElement(),R.removeElement(),T.remove(),c.removeClass("fc fc-ltr fc-rtl fc-unthemed ui-widget"),Y&&a(window).unbind("resize",Y)}function h(){return c.is(":visible")}function i(b){ca++,V&&b&&V.type!==b&&(R.deactivateButton(V.type),H(),V.removeElement(),V=N.view=null),!V&&b&&(V=N.view=ba[b]||(ba[b]=N.instantiateView(b)),V.setElement(a("<div class='fc-view fc-"+b+"-view' />").appendTo(T)),R.activateButton(b)),V&&(Z=V.massageCurrentDate(Z),V.displaying&&Z.isWithin(V.intervalStart,V.intervalEnd)||h()&&(V.display(Z),I(),u(),v(),q())),I(),ca--}function j(a){return h()?(a&&l(),ca++,V.updateSize(!0),ca--,!0):void 0}function k(){h()&&l()}function l(){W="number"==typeof O.contentHeight?O.contentHeight:"number"==typeof O.height?O.height-(S?S.outerHeight(!0):0):Math.round(T.width()/Math.max(O.aspectRatio,.5))}function m(a){!ca&&a.target===window&&V.start&&j(!0)&&V.trigger("windowResize",aa)}function n(){p(),r()}function o(){h()&&(H(),V.displayEvents(da),I())}function p(){H(),V.clearEvents(),I()}function q(){!O.lazyFetching||$(V.start,V.end)?r():o()}function r(){_(V.start,V.end)}function s(a){da=a,o()}function t(){o()}function u(){R.updateTitle(V.title)}function v(){var a=N.getNow();a.isWithin(V.intervalStart,V.intervalEnd)?R.disableButton("today"):R.enableButton("today")}function w(a,b){V.select(N.buildSelectSpan.apply(N,arguments))}function x(){V&&V.unselect()}function y(){Z=V.computePrevDate(Z),i()}function z(){Z=V.computeNextDate(Z),i()}function A(){Z.add(-1,"years"),i()}function B(){Z.add(1,"years"),i()}function C(){Z=N.getNow(),i()}function D(a){Z=N.moment(a).stripZone(),i()}function E(a){Z.add(b.duration(a)),i()}function F(a,b){var c;b=b||"day",c=N.getViewSpec(b)||N.getUnitViewSpec(b),Z=a.clone(),i(c?c.type:null)}function G(){return N.applyTimezone(Z)}function H(){T.css({width:"100%",height:T.height(),overflow:"hidden"})}function I(){T.css({width:"",height:"",overflow:""})}function J(){return N}function K(){return V}function L(a,b){return void 0===b?O[a]:void("height"!=a&&"contentHeight"!=a&&"aspectRatio"!=a||(O[a]=b,j(!0)))}function M(a,b){var c=Array.prototype.slice.call(arguments,2);return b=b||aa,this.triggerWith(a,b,c),O[a]?O[a].apply(b,c):void 0}var N=this;N.initOptions(d||{});var O=this.options;N.render=e,N.destroy=g,N.refetchEvents=n,N.reportEvents=s,N.reportEventChange=t,N.rerenderEvents=o,N.changeView=i,N.select=w,N.unselect=x,N.prev=y,N.next=z,N.prevYear=A,N.nextYear=B,N.today=C,N.gotoDate=D,N.incrementDate=E,N.zoomTo=F,N.getDate=G,N.getCalendar=J,N.getView=K,N.option=L,N.trigger=M;var P=X(Ra(O.lang));if(O.monthNames&&(P._months=O.monthNames),O.monthNamesShort&&(P._monthsShort=O.monthNamesShort),O.dayNames&&(P._weekdays=O.dayNames),O.dayNamesShort&&(P._weekdaysShort=O.dayNamesShort),null!=O.firstDay){var Q=X(P._week);Q.dow=O.firstDay,P._week=Q}P._fullCalendar_weekCalc=function(a){return"function"==typeof a?a:"local"===a?a:"iso"===a||"ISO"===a?"ISO":void 0}(O.weekNumberCalculation),N.defaultAllDayEventDuration=b.duration(O.defaultAllDayEventDuration),N.defaultTimedEventDuration=b.duration(O.defaultTimedEventDuration),N.moment=function(){var a;return"local"===O.timezone?(a=Va.moment.apply(null,arguments),a.hasTime()&&a.local()):a="UTC"===O.timezone?Va.moment.utc.apply(null,arguments):Va.moment.parseZone.apply(null,arguments),"_locale"in a?a._locale=P:a._lang=P,a},N.getIsAmbigTimezone=function(){return"local"!==O.timezone&&"UTC"!==O.timezone},N.applyTimezone=function(a){if(!a.hasTime())return a.clone();var b,c=N.moment(a.toArray()),d=a.time()-c.time();return d&&(b=c.clone().add(d),a.time()-b.time()===0&&(c=b)),c},N.getNow=function(){var a=O.now;return"function"==typeof a&&(a=a()),N.moment(a).stripZone()},N.getEventEnd=function(a){return a.end?a.end.clone():N.getDefaultEventEnd(a.allDay,a.start)},N.getDefaultEventEnd=function(a,b){var c=b.clone();return a?c.stripTime().add(N.defaultAllDayEventDuration):c.add(N.defaultTimedEventDuration),N.getIsAmbigTimezone()&&c.stripZone(),c},N.humanizeDuration=function(a){return(a.locale||a.lang).call(a,O.lang).humanize()},Ta.call(N,O);var R,S,T,U,V,W,Y,Z,$=N.isFetchNeeded,_=N.fetchEvents,aa=c[0],ba={},ca=0,da=[];Z=null!=O.defaultDate?N.moment(O.defaultDate).stripZone():N.getNow(),N.getSuggestedViewHeight=function(){return void 0===W&&k(),W},N.isHeightAuto=function(){return"auto"===O.contentHeight||"auto"===O.height},N.freezeContentHeight=H,N.unfreezeContentHeight=I,N.initialize()}function Qa(b){a.each(Cb,function(a,c){null==b[a]&&(b[a]=c(b))})}function Ra(a){var c=b.localeData||b.langData;return c.call(b,a)||c.call(b,"en")}function Sa(b,c){function d(){var b=c.header;return n=c.theme?"ui":"fc",b?o=a("<div class='fc-toolbar'/>").append(f("left")).append(f("right")).append(f("center")).append('<div class="fc-clear"/>'):void 0}function e(){o.remove(),o=a()}function f(d){var e=a('<div class="fc-'+d+'"/>'),f=c.header[d];return f&&a.each(f.split(" "),function(d){var f,g=a(),h=!0;a.each(this.split(","),function(d,e){var f,i,j,k,l,m,o,q,r,s;"title"==e?(g=g.add(a("<h2> </h2>")),h=!1):((f=(b.options.customButtons||{})[e])?(j=function(a){f.click&&f.click.call(s[0],a)},k="",l=f.text):(i=b.getViewSpec(e))?(j=function(){b.changeView(e)},p.push(e),k=i.buttonTextOverride,l=i.buttonTextDefault):b[e]&&(j=function(){b[e]()},k=(b.overrides.buttonText||{})[e],l=c.buttonText[e]),j&&(m=f?f.themeIcon:c.themeButtonIcons[e],o=f?f.icon:c.buttonIcons[e],q=k?ca(k):m&&c.theme?"<span class='ui-icon ui-icon-"+m+"'></span>":o&&!c.theme?"<span class='fc-icon fc-icon-"+o+"'></span>":ca(l),r=["fc-"+e+"-button",n+"-button",n+"-state-default"],s=a('<button type="button" class="'+r.join(" ")+'">'+q+"</button>").click(function(a){s.hasClass(n+"-state-disabled")||(j(a),(s.hasClass(n+"-state-active")||s.hasClass(n+"-state-disabled"))&&s.removeClass(n+"-state-hover"))}).mousedown(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-down")}).mouseup(function(){s.removeClass(n+"-state-down")}).hover(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-hover")},function(){s.removeClass(n+"-state-hover").removeClass(n+"-state-down")}),g=g.add(s)))}),h&&g.first().addClass(n+"-corner-left").end().last().addClass(n+"-corner-right").end(),g.length>1?(f=a("<div/>"),h&&f.addClass("fc-button-group"),f.append(g),e.append(f)):e.append(g)}),e}function g(a){o.find("h2").text(a)}function h(a){o.find(".fc-"+a+"-button").addClass(n+"-state-active")}function i(a){o.find(".fc-"+a+"-button").removeClass(n+"-state-active")}function j(a){o.find(".fc-"+a+"-button").attr("disabled","disabled").addClass(n+"-state-disabled")}function k(a){o.find(".fc-"+a+"-button").removeAttr("disabled").removeClass(n+"-state-disabled")}function l(){return p}var m=this;m.render=d,m.removeElement=e,m.updateTitle=g,m.activateButton=h,m.deactivateButton=i,m.disableButton=j,m.enableButton=k,m.getViewsWithButtons=l;var n,o=a(),p=[]}function Ta(c){function d(a,b){return!I||I>a||b>J}function e(a,b){I=a,J=b,S=[];var c=++Q,d=P.length;R=d;for(var e=0;d>e;e++)f(P[e],c)}function f(b,c){g(b,function(d){var e,f,g,h=a.isArray(b.events);if(c==Q){if(d)for(e=0;e<d.length;e++)f=d[e],g=h?f:s(f,b),g&&S.push.apply(S,w(g));R--,R||K(S)}})}function g(b,d){var e,f,h=Va.sourceFetchers;for(e=0;e<h.length;e++){if(f=h[e].call(H,b,I.clone(),J.clone(),c.timezone,d),f===!0)return;if("object"==typeof f)return void g(f,d)}var i=b.events;if(i)a.isFunction(i)?(H.pushLoading(),i.call(H,I.clone(),J.clone(),c.timezone,function(a){d(a),H.popLoading()})):a.isArray(i)?d(i):d();else{var j=b.url;if(j){var k,l=b.success,m=b.error,n=b.complete;k=a.isFunction(b.data)?b.data():b.data;var o=a.extend({},k||{}),p=ba(b.startParam,c.startParam),q=ba(b.endParam,c.endParam),r=ba(b.timezoneParam,c.timezoneParam);p&&(o[p]=I.format()),q&&(o[q]=J.format()),c.timezone&&"local"!=c.timezone&&(o[r]=c.timezone),H.pushLoading(),a.ajax(a.extend({},Db,b,{data:o,success:function(b){b=b||[];var c=aa(l,this,arguments);a.isArray(c)&&(b=c),d(b)},error:function(){aa(m,this,arguments),d()},complete:function(){aa(n,this,arguments),H.popLoading()}}))}else d()}}function h(a){var b=i(a);b&&(P.push(b),R++,f(b,Q))}function i(b){var c,d,e=Va.sourceNormalizers;if(a.isFunction(b)||a.isArray(b)?c={events:b}:"string"==typeof b?c={url:b}:"object"==typeof b&&(c=a.extend({},b)),c){for(c.className?"string"==typeof c.className&&(c.className=c.className.split(/\s+/)):c.className=[],a.isArray(c.events)&&(c.origArray=c.events,c.events=a.map(c.events,function(a){return s(a,c)})),d=0;d<e.length;d++)e[d].call(H,c);return c}}function j(b){P=a.grep(P,function(a){return!k(a,b)}),S=a.grep(S,function(a){return!k(a.source,b)}),K(S)}function k(a,b){return a&&b&&l(a)==l(b)}function l(a){return("object"==typeof a?a.origArray||a.googleCalendarId||a.url||a.events:null)||a}function m(a){a.start=H.moment(a.start),a.end?a.end=H.moment(a.end):a.end=null,x(a,n(a)),K(S)}function n(b){var c={};return a.each(b,function(a,b){o(a)&&void 0!==b&&_(b)&&(c[a]=b)}),c}function o(a){return!/^_|^(id|allDay|start|end)$/.test(a)}function p(a,b){var c,d,e,f=s(a);if(f){for(c=w(f),d=0;d<c.length;d++)e=c[d],e.source||(b&&(O.events.push(e),e.source=O),S.push(e));return K(S),c}return[]}function q(b){var c,d;for(null==b?b=function(){return!0}:a.isFunction(b)||(c=b+"",b=function(a){return a._id==c}),S=a.grep(S,b,!0),d=0;d<P.length;d++)a.isArray(P[d].events)&&(P[d].events=a.grep(P[d].events,b,!0));K(S)}function r(b){return a.isFunction(b)?a.grep(S,b):null!=b?(b+="",a.grep(S,function(a){return a._id==b})):S}function s(d,e){var f,g,h,i={};if(c.eventDataTransform&&(d=c.eventDataTransform(d)),e&&e.eventDataTransform&&(d=e.eventDataTransform(d)),a.extend(i,d),e&&(i.source=e),i._id=d._id||(void 0===d.id?"_fc"+Eb++:d.id+""),d.className?"string"==typeof d.className?i.className=d.className.split(/\s+/):i.className=d.className:i.className=[],f=d.start||d.date,g=d.end,V(f)&&(f=b.duration(f)),V(g)&&(g=b.duration(g)),d.dow||b.isDuration(f)||b.isDuration(g))i.start=f?b.duration(f):null,i.end=g?b.duration(g):null,i._recurring=!0;else{if(f&&(f=H.moment(f),!f.isValid()))return!1;g&&(g=H.moment(g),g.isValid()||(g=null)),h=d.allDay,void 0===h&&(h=ba(e?e.allDayDefault:void 0,c.allDayDefault)),t(f,g,h,i)}return H.normalizeEvent(i),i}function t(a,b,c,d){d.start=a,d.end=b,d.allDay=c,u(d),Ua(d)}function u(a){v(a),a.end&&!a.end.isAfter(a.start)&&(a.end=null),a.end||(c.forceEventDuration?a.end=H.getDefaultEventEnd(a.allDay,a.start):a.end=null)}function v(a){null==a.allDay&&(a.allDay=!(a.start.hasTime()||a.end&&a.end.hasTime())),a.allDay?(a.start.stripTime(),a.end&&a.end.stripTime()):(a.start.hasTime()||(a.start=H.applyTimezone(a.start.time(0))),a.end&&!a.end.hasTime()&&(a.end=H.applyTimezone(a.end.time(0))))}function w(b,c,d){var e,f,g,h,i,j,k,l,m,n=[];if(c=c||I,d=d||J,b)if(b._recurring){if(f=b.dow)for(e={},g=0;g<f.length;g++)e[f[g]]=!0;for(h=c.clone().stripTime();h.isBefore(d);)e&&!e[h.day()]||(i=b.start,j=b.end,k=h.clone(),l=null,i&&(k=k.time(i)),j&&(l=h.clone().time(j)),m=a.extend({},b),t(k,l,!i&&!j,m),n.push(m)),h.add(1,"days")}else n.push(b);return n}function x(b,c,d){function e(a,b){return d?N(a,b,d):c.allDay?M(a,b):L(a,b)}var f,g,h,i,j,k,l={};return c=c||{},c.start||(c.start=b.start.clone()),void 0===c.end&&(c.end=b.end?b.end.clone():null),null==c.allDay&&(c.allDay=b.allDay),u(c),f={start:b._start.clone(),end:b._end?b._end.clone():H.getDefaultEventEnd(b._allDay,b._start),allDay:c.allDay},u(f),g=null!==b._end&&null===c.end,h=e(c.start,f.start),c.end?(i=e(c.end,f.end),j=i.subtract(h)):j=null,a.each(c,function(a,b){o(a)&&void 0!==b&&(l[a]=b)}),k=y(r(b._id),g,c.allDay,h,j,l),{dateDelta:h,durationDelta:j,undo:k}}function y(b,c,d,e,f,g){var h=H.getIsAmbigTimezone(),i=[];return e&&!e.valueOf()&&(e=null),f&&!f.valueOf()&&(f=null),a.each(b,function(b,j){var k,l;k={start:j.start.clone(),end:j.end?j.end.clone():null,allDay:j.allDay},a.each(g,function(a){k[a]=j[a]}),l={start:j._start,end:j._end,allDay:d},u(l),c?l.end=null:f&&!l.end&&(l.end=H.getDefaultEventEnd(l.allDay,l.start)),e&&(l.start.add(e),l.end&&l.end.add(e)),f&&l.end.add(f),h&&!l.allDay&&(e||f)&&(l.start.stripZone(),l.end&&l.end.stripZone()),a.extend(j,g,l),Ua(j),i.push(function(){a.extend(j,k),Ua(j)})}),function(){for(var a=0;a<i.length;a++)i[a]()}}function z(b){var d,e=c.businessHours,f={className:"fc-nonbusiness",start:"09:00",end:"17:00",dow:[1,2,3,4,5],rendering:"inverse-background"},g=H.getView();return e&&(d=a.extend({},f,"object"==typeof e?e:{})),d?(b&&(d.start=null,d.end=null),w(s(d),g.start,g.end)):[]}function A(a,b){var d=b.source||{},e=ba(b.constraint,d.constraint,c.eventConstraint),f=ba(b.overlap,d.overlap,c.eventOverlap);return D(a,e,f,b)}function B(b,c,d){var e,f;return d&&(e=a.extend({},d,c),f=w(s(e))[0]),f?A(b,f):C(b)}function C(a){return D(a,c.selectConstraint,c.selectOverlap)}function D(a,b,c,d){var e,f,g,h,i,j;if(null!=b){for(e=E(b),f=!1,h=0;h<e.length;h++)if(F(e[h],a)){f=!0;break}if(!f)return!1}for(g=H.getPeerEvents(a,d),h=0;h<g.length;h++)if(i=g[h],G(i,a)){if(c===!1)return!1;if("function"==typeof c&&!c(i,d))return!1;if(d){if(j=ba(i.overlap,(i.source||{}).overlap),j===!1)return!1;if("function"==typeof j&&!j(d,i))return!1}}return!0}function E(a){return"businessHours"===a?z():"object"==typeof a?w(s(a)):r(a)}function F(a,b){var c=a.start.clone().stripZone(),d=H.getEventEnd(a).stripZone();return b.start>=c&&b.end<=d}function G(a,b){var c=a.start.clone().stripZone(),d=H.getEventEnd(a).stripZone();return b.start<d&&b.end>c}var H=this;H.isFetchNeeded=d,H.fetchEvents=e,H.addEventSource=h,H.removeEventSource=j,H.updateEvent=m,H.renderEvent=p,H.removeEvents=q,H.clientEvents=r,H.mutateEvent=x,H.normalizeEventDates=u,H.normalizeEventTimes=v;var I,J,K=H.reportEvents,O={events:[]},P=[O],Q=0,R=0,S=[];a.each((c.events?[c.events]:[]).concat(c.eventSources||[]),function(a,b){var c=i(b);c&&P.push(c)}),H.getBusinessHoursEvents=z,H.isEventSpanAllowed=A,H.isExternalSpanAllowed=B,H.isSelectionSpanAllowed=C,H.getEventCache=function(){return S}}function Ua(a){a._allDay=a.allDay,a._start=a.start.clone(),a._end=a.end?a.end.clone():null}var Va=a.fullCalendar={version:"2.7.3",internalApiVersion:4},Wa=Va.views={};a.fn.fullCalendar=function(b){var c=Array.prototype.slice.call(arguments,1),d=this;return this.each(function(e,f){var g,h=a(f),i=h.data("fullCalendar");"string"==typeof b?i&&a.isFunction(i[b])&&(g=i[b].apply(i,c),e||(d=g),"destroy"===b&&h.removeData("fullCalendar")):i||(i=new yb(h,b),h.data("fullCalendar",i),i.render())}),d};var Xa=["header","buttonText","buttonIcons","themeButtonIcons"];Va.intersectRanges=K,Va.applyAll=aa,Va.debounce=ja,Va.isInt=ha,Va.htmlEscape=ca,Va.cssToStr=ea,Va.proxy=ia,Va.capitaliseFirstLetter=fa,Va.getOuterRect=n,Va.getClientRect=o,Va.getContentRect=p,Va.getScrollbarWidths=q;var Ya=null;Va.preventDefault=z,Va.intersectRects=C,Va.parseFieldSpecs=G,Va.compareByFieldSpecs=H,Va.compareByFieldSpec=I,Va.flexibleCompare=J,Va.computeIntervalUnit=O,Va.divideRangeByDuration=Q,Va.divideDurationByDuration=R,Va.multiplyDuration=S,Va.durationHasTime=T;var Za=["sun","mon","tue","wed","thu","fri","sat"],$a=["year","month","week","day","hour","minute","second","millisecond"];Va.log=function(){var a=window.console;return a&&a.log?a.log.apply(a,arguments):void 0},Va.warn=function(){var a=window.console;return a&&a.warn?a.warn.apply(a,arguments):Va.log.apply(Va,arguments)};var _a,ab,bb,cb={}.hasOwnProperty,db=/^\s*\d{4}-\d\d$/,eb=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/,fb=b.fn,gb=a.extend({},fb);Va.moment=function(){return ka(arguments)},Va.moment.utc=function(){var a=ka(arguments,!0);return a.hasTime()&&a.utc(),a},Va.moment.parseZone=function(){return ka(arguments,!0,!0)},fb.clone=function(){var a=gb.clone.apply(this,arguments);return ma(this,a),this._fullCalendar&&(a._fullCalendar=!0),a},fb.week=fb.weeks=function(a){var b=(this._locale||this._lang)._fullCalendar_weekCalc;return null==a&&"function"==typeof b?b(this):"ISO"===b?gb.isoWeek.apply(this,arguments):gb.week.apply(this,arguments)},fb.time=function(a){if(!this._fullCalendar)return gb.time.apply(this,arguments);if(null==a)return b.duration({hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()});this._ambigTime=!1,b.isDuration(a)||b.isMoment(a)||(a=b.duration(a));var c=0;return b.isDuration(a)&&(c=24*Math.floor(a.asDays())),this.hours(c+a.hours()).minutes(a.minutes()).seconds(a.seconds()).milliseconds(a.milliseconds())},fb.stripTime=function(){var a;return this._ambigTime||(a=this.toArray(),this.utc(),ab(this,a.slice(0,3)),this._ambigTime=!0,this._ambigZone=!0),this},fb.hasTime=function(){return!this._ambigTime},fb.stripZone=function(){var a,b;return this._ambigZone||(a=this.toArray(),b=this._ambigTime,this.utc(),ab(this,a),this._ambigTime=b||!1,this._ambigZone=!0),this},fb.hasZone=function(){return!this._ambigZone},fb.local=function(){var a=this.toArray(),b=this._ambigZone;return gb.local.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,b&&bb(this,a),this},fb.utc=function(){return gb.utc.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,this},a.each(["zone","utcOffset"],function(a,b){gb[b]&&(fb[b]=function(a){return null!=a&&(this._ambigTime=!1,this._ambigZone=!1),gb[b].apply(this,arguments)})}),fb.format=function(){return this._fullCalendar&&arguments[0]?pa(this,arguments[0]):this._ambigTime?oa(this,"YYYY-MM-DD"):this._ambigZone?oa(this,"YYYY-MM-DD[T]HH:mm:ss"):gb.format.apply(this,arguments)},fb.toISOString=function(){return this._ambigTime?oa(this,"YYYY-MM-DD"):this._ambigZone?oa(this,"YYYY-MM-DD[T]HH:mm:ss"):gb.toISOString.apply(this,arguments)},fb.isWithin=function(a,b){var c=la([this,a,b]);return c[0]>=c[1]&&c[0]<c[2]},fb.isSame=function(a,b){var c;return this._fullCalendar?b?(c=la([this,a],!0),gb.isSame.call(c[0],c[1],b)):(a=Va.moment.parseZone(a),gb.isSame.call(this,a)&&Boolean(this._ambigTime)===Boolean(a._ambigTime)&&Boolean(this._ambigZone)===Boolean(a._ambigZone)):gb.isSame.apply(this,arguments)},a.each(["isBefore","isAfter"],function(a,b){fb[b]=function(a,c){var d;return this._fullCalendar?(d=la([this,a]),gb[b].call(d[0],d[1],c)):gb[b].apply(this,arguments)}}),_a="_d"in b()&&"updateOffset"in b,ab=_a?function(a,c){a._d.setTime(Date.UTC.apply(Date,c)),b.updateOffset(a,!1)}:na,bb=_a?function(a,c){a._d.setTime(+new Date(c[0]||0,c[1]||0,c[2]||0,c[3]||0,c[4]||0,c[5]||0,c[6]||0)),b.updateOffset(a,!1)}:na;var hb={t:function(a){return oa(a,"a").charAt(0)},T:function(a){return oa(a,"A").charAt(0)}};Va.formatRange=sa;var ib={Y:"year",M:"month",D:"day",d:"day",A:"second",a:"second",T:"second",t:"second",H:"second",h:"second",m:"second",s:"second"},jb={};Va.Class=xa,xa.extend=function(){var a,b,c=arguments.length;for(a=0;c>a;a++)b=arguments[a],c-1>a&&za(this,b);return ya(this,b||{})},xa.mixin=function(a){za(this,a)};var kb=Va.EmitterMixin={on:function(b,c){var d=function(a,b){return c.apply(b.context||this,b.args||[])};return c.guid||(c.guid=a.guid++),d.guid=c.guid,a(this).on(b,d),this},off:function(b,c){return a(this).off(b,c),this},trigger:function(b){var c=Array.prototype.slice.call(arguments,1);return a(this).triggerHandler(b,{args:c}),this},triggerWith:function(b,c,d){return a(this).triggerHandler(b,{context:c,args:d}),this}},lb=Va.ListenerMixin=function(){var b=0,c={listenerId:null,listenTo:function(b,c,d){if("object"==typeof c)for(var e in c)c.hasOwnProperty(e)&&this.listenTo(b,e,c[e]);else"string"==typeof c&&b.on(c+"."+this.getListenerNamespace(),a.proxy(d,this))},stopListeningTo:function(a,b){a.off((b||"")+"."+this.getListenerNamespace())},getListenerNamespace:function(){return null==this.listenerId&&(this.listenerId=b++),"_listener"+this.listenerId}};return c}(),mb={isIgnoringMouse:!1,delayUnignoreMouse:null,initMouseIgnoring:function(a){this.delayUnignoreMouse=ja(ia(this,"unignoreMouse"),a||1e3)},tempIgnoreMouse:function(){this.isIgnoringMouse=!0,this.delayUnignoreMouse()},unignoreMouse:function(){this.isIgnoringMouse=!1; -}},nb=xa.extend(lb,{isHidden:!0,options:null,el:null,margin:10,constructor:function(a){this.options=a||{}},show:function(){this.isHidden&&(this.el||this.render(),this.el.show(),this.position(),this.isHidden=!1,this.trigger("show"))},hide:function(){this.isHidden||(this.el.hide(),this.isHidden=!0,this.trigger("hide"))},render:function(){var b=this,c=this.options;this.el=a('<div class="fc-popover"/>').addClass(c.className||"").css({top:0,left:0}).append(c.content).appendTo(c.parentEl),this.el.on("click",".fc-close",function(){b.hide()}),c.autoHide&&this.listenTo(a(document),"mousedown",this.documentMousedown)},documentMousedown:function(b){this.el&&!a(b.target).closest(this.el).length&&this.hide()},removeElement:function(){this.hide(),this.el&&(this.el.remove(),this.el=null),this.stopListeningTo(a(document),"mousedown")},position:function(){var b,c,d,e,f,g=this.options,h=this.el.offsetParent().offset(),i=this.el.outerWidth(),j=this.el.outerHeight(),k=a(window),l=m(this.el);e=g.top||0,f=void 0!==g.left?g.left:void 0!==g.right?g.right-i:0,l.is(window)||l.is(document)?(l=k,b=0,c=0):(d=l.offset(),b=d.top,c=d.left),b+=k.scrollTop(),c+=k.scrollLeft(),g.viewportConstrain!==!1&&(e=Math.min(e,b+l.outerHeight()-j-this.margin),e=Math.max(e,b+this.margin),f=Math.min(f,c+l.outerWidth()-i-this.margin),f=Math.max(f,c+this.margin)),this.el.css({top:e-h.top,left:f-h.left})},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1))}}),ob=Va.CoordCache=xa.extend({els:null,forcedOffsetParentEl:null,origin:null,boundingRect:null,isHorizontal:!1,isVertical:!1,lefts:null,rights:null,tops:null,bottoms:null,constructor:function(b){this.els=a(b.els),this.isHorizontal=b.isHorizontal,this.isVertical=b.isVertical,this.forcedOffsetParentEl=b.offsetParent?a(b.offsetParent):null},build:function(){var a=this.forcedOffsetParentEl||this.els.eq(0).offsetParent();this.origin=a.offset(),this.boundingRect=this.queryBoundingRect(),this.isHorizontal&&this.buildElHorizontals(),this.isVertical&&this.buildElVerticals()},clear:function(){this.origin=null,this.boundingRect=null,this.lefts=null,this.rights=null,this.tops=null,this.bottoms=null},ensureBuilt:function(){this.origin||this.build()},queryBoundingRect:function(){var a=m(this.els.eq(0));return a.is(document)?void 0:o(a)},buildElHorizontals:function(){var b=[],c=[];this.els.each(function(d,e){var f=a(e),g=f.offset().left,h=f.outerWidth();b.push(g),c.push(g+h)}),this.lefts=b,this.rights=c},buildElVerticals:function(){var b=[],c=[];this.els.each(function(d,e){var f=a(e),g=f.offset().top,h=f.outerHeight();b.push(g),c.push(g+h)}),this.tops=b,this.bottoms=c},getHorizontalIndex:function(a){this.ensureBuilt();var b,c=this.boundingRect,d=this.lefts,e=this.rights,f=d.length;if(!c||a>=c.left&&a<c.right)for(b=0;f>b;b++)if(a>=d[b]&&a<e[b])return b},getVerticalIndex:function(a){this.ensureBuilt();var b,c=this.boundingRect,d=this.tops,e=this.bottoms,f=d.length;if(!c||a>=c.top&&a<c.bottom)for(b=0;f>b;b++)if(a>=d[b]&&a<e[b])return b},getLeftOffset:function(a){return this.ensureBuilt(),this.lefts[a]},getLeftPosition:function(a){return this.ensureBuilt(),this.lefts[a]-this.origin.left},getRightOffset:function(a){return this.ensureBuilt(),this.rights[a]},getRightPosition:function(a){return this.ensureBuilt(),this.rights[a]-this.origin.left},getWidth:function(a){return this.ensureBuilt(),this.rights[a]-this.lefts[a]},getTopOffset:function(a){return this.ensureBuilt(),this.tops[a]},getTopPosition:function(a){return this.ensureBuilt(),this.tops[a]-this.origin.top},getBottomOffset:function(a){return this.ensureBuilt(),this.bottoms[a]},getBottomPosition:function(a){return this.ensureBuilt(),this.bottoms[a]-this.origin.top},getHeight:function(a){return this.ensureBuilt(),this.bottoms[a]-this.tops[a]}}),pb=Va.DragListener=xa.extend(lb,mb,{options:null,subjectEl:null,subjectHref:null,originX:null,originY:null,scrollEl:null,isInteracting:!1,isDistanceSurpassed:!1,isDelayEnded:!1,isDragging:!1,isTouch:!1,delay:null,delayTimeoutId:null,minDistance:null,handleTouchScrollProxy:null,constructor:function(a){this.options=a||{},this.handleTouchScrollProxy=ia(this,"handleTouchScroll"),this.initMouseIgnoring(500)},startInteraction:function(b,c){var d=x(b);if("mousedown"===b.type){if(this.isIgnoringMouse)return;if(!u(b))return;b.preventDefault()}this.isInteracting||(c=c||{},this.delay=ba(c.delay,this.options.delay,0),this.minDistance=ba(c.distance,this.options.distance,0),this.subjectEl=this.options.subjectEl,this.isInteracting=!0,this.isTouch=d,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,this.originX=v(b),this.originY=w(b),this.scrollEl=m(a(b.target)),this.bindHandlers(),this.initAutoScroll(),this.handleInteractionStart(b),this.startDelay(b),this.minDistance||this.handleDistanceSurpassed(b))},handleInteractionStart:function(a){this.trigger("interactionStart",a)},endInteraction:function(a,b){this.isInteracting&&(this.endDrag(a),this.delayTimeoutId&&(clearTimeout(this.delayTimeoutId),this.delayTimeoutId=null),this.destroyAutoScroll(),this.unbindHandlers(),this.isInteracting=!1,this.handleInteractionEnd(a,b),this.isTouch&&this.tempIgnoreMouse())},handleInteractionEnd:function(a,b){this.trigger("interactionEnd",a,b||!1)},bindHandlers:function(){var b=this,c=1;this.isTouch?(this.listenTo(a(document),{touchmove:this.handleTouchMove,touchend:this.endInteraction,touchcancel:this.endInteraction,touchstart:function(a){c?c--:b.endInteraction(a,!0)}}),!A(this.handleTouchScrollProxy)&&this.scrollEl&&this.listenTo(this.scrollEl,"scroll",this.handleTouchScroll)):this.listenTo(a(document),{mousemove:this.handleMouseMove,mouseup:this.endInteraction}),this.listenTo(a(document),{selectstart:z,contextmenu:z})},unbindHandlers:function(){this.stopListeningTo(a(document)),B(this.handleTouchScrollProxy),this.scrollEl&&this.stopListeningTo(this.scrollEl,"scroll")},startDrag:function(a,b){this.startInteraction(a,b),this.isDragging||(this.isDragging=!0,this.handleDragStart(a))},handleDragStart:function(a){this.trigger("dragStart",a),this.initHrefHack()},handleMove:function(a){var b,c=v(a)-this.originX,d=w(a)-this.originY,e=this.minDistance;this.isDistanceSurpassed||(b=c*c+d*d,b>=e*e&&this.handleDistanceSurpassed(a)),this.isDragging&&this.handleDrag(c,d,a)},handleDrag:function(a,b,c){this.trigger("drag",a,b,c),this.updateAutoScroll(c)},endDrag:function(a){this.isDragging&&(this.isDragging=!1,this.handleDragEnd(a))},handleDragEnd:function(a){this.trigger("dragEnd",a),this.destroyHrefHack()},startDelay:function(a){var b=this;this.delay?this.delayTimeoutId=setTimeout(function(){b.handleDelayEnd(a)},this.delay):this.handleDelayEnd(a)},handleDelayEnd:function(a){this.isDelayEnded=!0,this.isDistanceSurpassed&&this.startDrag(a)},handleDistanceSurpassed:function(a){this.isDistanceSurpassed=!0,this.isDelayEnded&&this.startDrag(a)},handleTouchMove:function(a){this.isDragging&&a.preventDefault(),this.handleMove(a)},handleMouseMove:function(a){this.handleMove(a)},handleTouchScroll:function(a){this.isDragging||this.endInteraction(a,!0)},initHrefHack:function(){var a=this.subjectEl;(this.subjectHref=a?a.attr("href"):null)&&a.removeAttr("href")},destroyHrefHack:function(){var a=this.subjectEl,b=this.subjectHref;setTimeout(function(){b&&a.attr("href",b)},0)},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1)),this["_"+a]&&this["_"+a].apply(this,Array.prototype.slice.call(arguments,1))}});pb.mixin({isAutoScroll:!1,scrollBounds:null,scrollTopVel:null,scrollLeftVel:null,scrollIntervalId:null,scrollSensitivity:30,scrollSpeed:200,scrollIntervalMs:50,initAutoScroll:function(){var a=this.scrollEl;this.isAutoScroll=this.options.scroll&&a&&!a.is(window)&&!a.is(document),this.isAutoScroll&&this.listenTo(a,"scroll",ja(this.handleDebouncedScroll,100))},destroyAutoScroll:function(){this.endAutoScroll(),this.isAutoScroll&&this.stopListeningTo(this.scrollEl,"scroll")},computeScrollBounds:function(){this.isAutoScroll&&(this.scrollBounds=n(this.scrollEl))},updateAutoScroll:function(a){var b,c,d,e,f=this.scrollSensitivity,g=this.scrollBounds,h=0,i=0;g&&(b=(f-(w(a)-g.top))/f,c=(f-(g.bottom-w(a)))/f,d=(f-(v(a)-g.left))/f,e=(f-(g.right-v(a)))/f,b>=0&&1>=b?h=b*this.scrollSpeed*-1:c>=0&&1>=c&&(h=c*this.scrollSpeed),d>=0&&1>=d?i=d*this.scrollSpeed*-1:e>=0&&1>=e&&(i=e*this.scrollSpeed)),this.setScrollVel(h,i)},setScrollVel:function(a,b){this.scrollTopVel=a,this.scrollLeftVel=b,this.constrainScrollVel(),!this.scrollTopVel&&!this.scrollLeftVel||this.scrollIntervalId||(this.scrollIntervalId=setInterval(ia(this,"scrollIntervalFunc"),this.scrollIntervalMs))},constrainScrollVel:function(){var a=this.scrollEl;this.scrollTopVel<0?a.scrollTop()<=0&&(this.scrollTopVel=0):this.scrollTopVel>0&&a.scrollTop()+a[0].clientHeight>=a[0].scrollHeight&&(this.scrollTopVel=0),this.scrollLeftVel<0?a.scrollLeft()<=0&&(this.scrollLeftVel=0):this.scrollLeftVel>0&&a.scrollLeft()+a[0].clientWidth>=a[0].scrollWidth&&(this.scrollLeftVel=0)},scrollIntervalFunc:function(){var a=this.scrollEl,b=this.scrollIntervalMs/1e3;this.scrollTopVel&&a.scrollTop(a.scrollTop()+this.scrollTopVel*b),this.scrollLeftVel&&a.scrollLeft(a.scrollLeft()+this.scrollLeftVel*b),this.constrainScrollVel(),this.scrollTopVel||this.scrollLeftVel||this.endAutoScroll()},endAutoScroll:function(){this.scrollIntervalId&&(clearInterval(this.scrollIntervalId),this.scrollIntervalId=null,this.handleScrollEnd())},handleDebouncedScroll:function(){this.scrollIntervalId||this.handleScrollEnd()},handleScrollEnd:function(){}});var qb=pb.extend({component:null,origHit:null,hit:null,coordAdjust:null,constructor:function(a,b){pb.call(this,b),this.component=a},handleInteractionStart:function(a){var b,c,d,e=this.subjectEl;this.computeCoords(),a?(c={left:v(a),top:w(a)},d=c,e&&(b=n(e),d=D(d,b)),this.origHit=this.queryHit(d.left,d.top),e&&this.options.subjectCenter&&(this.origHit&&(b=C(this.origHit,b)||b),d=E(b)),this.coordAdjust=F(d,c)):(this.origHit=null,this.coordAdjust=null),pb.prototype.handleInteractionStart.apply(this,arguments)},computeCoords:function(){this.component.prepareHits(),this.computeScrollBounds()},handleDragStart:function(a){var b;pb.prototype.handleDragStart.apply(this,arguments),b=this.queryHit(v(a),w(a)),b&&this.handleHitOver(b)},handleDrag:function(a,b,c){var d;pb.prototype.handleDrag.apply(this,arguments),d=this.queryHit(v(c),w(c)),Aa(d,this.hit)||(this.hit&&this.handleHitOut(),d&&this.handleHitOver(d))},handleDragEnd:function(){this.handleHitDone(),pb.prototype.handleDragEnd.apply(this,arguments)},handleHitOver:function(a){var b=Aa(a,this.origHit);this.hit=a,this.trigger("hitOver",this.hit,b,this.origHit)},handleHitOut:function(){this.hit&&(this.trigger("hitOut",this.hit),this.handleHitDone(),this.hit=null)},handleHitDone:function(){this.hit&&this.trigger("hitDone",this.hit)},handleInteractionEnd:function(){pb.prototype.handleInteractionEnd.apply(this,arguments),this.origHit=null,this.hit=null,this.component.releaseHits()},handleScrollEnd:function(){pb.prototype.handleScrollEnd.apply(this,arguments),this.computeCoords()},queryHit:function(a,b){return this.coordAdjust&&(a+=this.coordAdjust.left,b+=this.coordAdjust.top),this.component.queryHit(a,b)}}),rb=xa.extend(lb,{options:null,sourceEl:null,el:null,parentEl:null,top0:null,left0:null,y0:null,x0:null,topDelta:null,leftDelta:null,isFollowing:!1,isHidden:!1,isAnimating:!1,constructor:function(b,c){this.options=c=c||{},this.sourceEl=b,this.parentEl=c.parentEl?a(c.parentEl):b.parent()},start:function(b){this.isFollowing||(this.isFollowing=!0,this.y0=w(b),this.x0=v(b),this.topDelta=0,this.leftDelta=0,this.isHidden||this.updatePosition(),x(b)?this.listenTo(a(document),"touchmove",this.handleMove):this.listenTo(a(document),"mousemove",this.handleMove))},stop:function(b,c){function d(){this.isAnimating=!1,e.removeElement(),this.top0=this.left0=null,c&&c()}var e=this,f=this.options.revertDuration;this.isFollowing&&!this.isAnimating&&(this.isFollowing=!1,this.stopListeningTo(a(document)),b&&f&&!this.isHidden?(this.isAnimating=!0,this.el.animate({top:this.top0,left:this.left0},{duration:f,complete:d})):d())},getEl:function(){var a=this.el;return a||(this.sourceEl.width(),a=this.el=this.sourceEl.clone().addClass(this.options.additionalClass||"").css({position:"absolute",visibility:"",display:this.isHidden?"none":"",margin:0,right:"auto",bottom:"auto",width:this.sourceEl.width(),height:this.sourceEl.height(),opacity:this.options.opacity||"",zIndex:this.options.zIndex}),a.addClass("fc-unselectable"),a.appendTo(this.parentEl)),a},removeElement:function(){this.el&&(this.el.remove(),this.el=null)},updatePosition:function(){var a,b;this.getEl(),null===this.top0&&(this.sourceEl.width(),a=this.sourceEl.offset(),b=this.el.offsetParent().offset(),this.top0=a.top-b.top,this.left0=a.left-b.left),this.el.css({top:this.top0+this.topDelta,left:this.left0+this.leftDelta})},handleMove:function(a){this.topDelta=w(a)-this.y0,this.leftDelta=v(a)-this.x0,this.isHidden||this.updatePosition()},hide:function(){this.isHidden||(this.isHidden=!0,this.el&&this.el.hide())},show:function(){this.isHidden&&(this.isHidden=!1,this.updatePosition(),this.getEl().show())}}),sb=Va.Grid=xa.extend(lb,mb,{view:null,isRTL:null,start:null,end:null,el:null,elsByFill:null,eventTimeFormat:null,displayEventTime:null,displayEventEnd:null,minResizeDuration:null,largeUnit:null,dayDragListener:null,segDragListener:null,segResizeListener:null,externalDragListener:null,constructor:function(a){this.view=a,this.isRTL=a.opt("isRTL"),this.elsByFill={},this.dayDragListener=this.buildDayDragListener(),this.initMouseIgnoring()},computeEventTimeFormat:function(){return this.view.opt("smallTimeFormat")},computeDisplayEventTime:function(){return!0},computeDisplayEventEnd:function(){return!0},setRange:function(a){this.start=a.start.clone(),this.end=a.end.clone(),this.rangeUpdated(),this.processRangeOptions()},rangeUpdated:function(){},processRangeOptions:function(){var a,b,c=this.view;this.eventTimeFormat=c.opt("eventTimeFormat")||c.opt("timeFormat")||this.computeEventTimeFormat(),a=c.opt("displayEventTime"),null==a&&(a=this.computeDisplayEventTime()),b=c.opt("displayEventEnd"),null==b&&(b=this.computeDisplayEventEnd()),this.displayEventTime=a,this.displayEventEnd=b},spanToSegs:function(a){},diffDates:function(a,b){return this.largeUnit?N(a,b,this.largeUnit):L(a,b)},prepareHits:function(){},releaseHits:function(){},queryHit:function(a,b){},getHitSpan:function(a){},getHitEl:function(a){},setElement:function(a){this.el=a,y(a),this.bindDayHandler("touchstart",this.dayTouchStart),this.bindDayHandler("mousedown",this.dayMousedown),this.bindSegHandlers(),this.bindGlobalHandlers()},bindDayHandler:function(b,c){var d=this;this.el.on(b,function(b){return a(b.target).is(".fc-event-container *, .fc-more")||a(b.target).closest(".fc-popover").length?void 0:c.call(d,b)})},removeElement:function(){this.unbindGlobalHandlers(),this.clearDragListeners(),this.el.remove()},renderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},bindGlobalHandlers:function(){this.listenTo(a(document),{dragstart:this.externalDragStart,sortstart:this.externalDragStart})},unbindGlobalHandlers:function(){this.stopListeningTo(a(document))},dayMousedown:function(a){this.isIgnoringMouse||this.dayDragListener.startInteraction(a,{})},dayTouchStart:function(a){var b=this.view;(b.isSelected||b.selectedEvent)&&this.tempIgnoreMouse(),this.dayDragListener.startInteraction(a,{delay:this.view.opt("longPressDelay")})},buildDayDragListener:function(){var a,b,c=this,d=this.view,e=d.opt("selectable"),f=new qb(this,{scroll:d.opt("dragScroll"),interactionStart:function(){a=f.origHit},dragStart:function(){d.unselect()},hitOver:function(d,f,h){h&&(f||(a=null),e&&(b=c.computeSelection(c.getHitSpan(h),c.getHitSpan(d)),b?c.renderSelection(b):b===!1&&g()))},hitOut:function(){a=null,b=null,c.unrenderSelection(),h()},interactionEnd:function(e,f){f||(a&&!c.isIgnoringMouse&&d.triggerDayClick(c.getHitSpan(a),c.getHitEl(a),e),b&&d.reportSelection(b,e),h())}});return f},clearDragListeners:function(){this.dayDragListener.endInteraction(),this.segDragListener&&this.segDragListener.endInteraction(),this.segResizeListener&&this.segResizeListener.endInteraction(),this.externalDragListener&&this.externalDragListener.endInteraction()},renderEventLocationHelper:function(a,b){var c=this.fabricateHelperEvent(a,b);return this.renderHelper(c,b)},fabricateHelperEvent:function(a,b){var c=b?X(b.event):{};return c.start=a.start.clone(),c.end=a.end?a.end.clone():null,c.allDay=null,this.view.calendar.normalizeEventDates(c),c.className=(c.className||[]).concat("fc-helper"),b||(c.editable=!1),c},renderHelper:function(a,b){},unrenderHelper:function(){},renderSelection:function(a){this.renderHighlight(a)},unrenderSelection:function(){this.unrenderHighlight()},computeSelection:function(a,b){var c=this.computeSelectionSpan(a,b);return c&&!this.view.calendar.isSelectionSpanAllowed(c)?!1:c},computeSelectionSpan:function(a,b){var c=[a.start,a.end,b.start,b.end];return c.sort(ga),{start:c[0].clone(),end:c[3].clone()}},renderHighlight:function(a){this.renderFill("highlight",this.spanToSegs(a))},unrenderHighlight:function(){this.unrenderFill("highlight")},highlightSegClasses:function(){return["fc-highlight"]},renderBusinessHours:function(){},unrenderBusinessHours:function(){},getNowIndicatorUnit:function(){},renderNowIndicator:function(a){},unrenderNowIndicator:function(){},renderFill:function(a,b){},unrenderFill:function(a){var b=this.elsByFill[a];b&&(b.remove(),delete this.elsByFill[a])},renderFillSegEls:function(b,c){var d,e=this,f=this[b+"SegEl"],g="",h=[];if(c.length){for(d=0;d<c.length;d++)g+=this.fillSegHtml(b,c[d]);a(g).each(function(b,d){var g=c[b],i=a(d);f&&(i=f.call(e,g,i)),i&&(i=a(i),i.is(e.fillSegTag)&&(g.el=i,h.push(g)))})}return h},fillSegTag:"div",fillSegHtml:function(a,b){var c=this[a+"SegClasses"],d=this[a+"SegCss"],e=c?c.call(this,b):[],f=ea(d?d.call(this,b):{});return"<"+this.fillSegTag+(e.length?' class="'+e.join(" ")+'"':"")+(f?' style="'+f+'"':"")+" />"},getDayClasses:function(a){var b=this.view,c=b.calendar.getNow(),d=["fc-"+Za[a.day()]];return 1==b.intervalDuration.as("months")&&a.month()!=b.intervalStart.month()&&d.push("fc-other-month"),a.isSame(c,"day")?d.push("fc-today",b.highlightStateClass):c>a?d.push("fc-past"):d.push("fc-future"),d}});sb.mixin({mousedOverSeg:null,isDraggingSeg:!1,isResizingSeg:!1,isDraggingExternal:!1,segs:null,renderEvents:function(a){var b,c=[],d=[];for(b=0;b<a.length;b++)(Ca(a[b])?c:d).push(a[b]);this.segs=[].concat(this.renderBgEvents(c),this.renderFgEvents(d))},renderBgEvents:function(a){var b=this.eventsToSegs(a);return this.renderBgSegs(b)||b},renderFgEvents:function(a){var b=this.eventsToSegs(a);return this.renderFgSegs(b)||b},unrenderEvents:function(){this.handleSegMouseout(),this.clearDragListeners(),this.unrenderFgSegs(),this.unrenderBgSegs(),this.segs=null},getEventSegs:function(){return this.segs||[]},renderFgSegs:function(a){},unrenderFgSegs:function(){},renderFgSegEls:function(b,c){var d,e=this.view,f="",g=[];if(b.length){for(d=0;d<b.length;d++)f+=this.fgSegHtml(b[d],c);a(f).each(function(c,d){var f=b[c],h=e.resolveEventEl(f.event,a(d));h&&(h.data("fc-seg",f),f.el=h,g.push(f))})}return g},fgSegHtml:function(a,b){},renderBgSegs:function(a){return this.renderFill("bgEvent",a)},unrenderBgSegs:function(){this.unrenderFill("bgEvent")},bgEventSegEl:function(a,b){return this.view.resolveEventEl(a.event,b)},bgEventSegClasses:function(a){var b=a.event,c=b.source||{};return["fc-bgevent"].concat(b.className,c.className||[])},bgEventSegCss:function(a){return{"background-color":this.getSegSkinCss(a)["background-color"]}},businessHoursSegClasses:function(a){return["fc-nonbusiness","fc-bgevent"]},bindSegHandlers:function(){this.bindSegHandler("touchstart",this.handleSegTouchStart),this.bindSegHandler("touchend",this.handleSegTouchEnd),this.bindSegHandler("mouseenter",this.handleSegMouseover),this.bindSegHandler("mouseleave",this.handleSegMouseout),this.bindSegHandler("mousedown",this.handleSegMousedown),this.bindSegHandler("click",this.handleSegClick)},bindSegHandler:function(b,c){var d=this;this.el.on(b,".fc-event-container > *",function(b){var e=a(this).data("fc-seg");return!e||d.isDraggingSeg||d.isResizingSeg?void 0:c.call(d,e,b)})},handleSegClick:function(a,b){return this.view.trigger("eventClick",a.el[0],a.event,b)},handleSegMouseover:function(a,b){this.isIgnoringMouse||this.mousedOverSeg||(this.mousedOverSeg=a,a.el.addClass("fc-allow-mouse-resize"),this.view.trigger("eventMouseover",a.el[0],a.event,b))},handleSegMouseout:function(a,b){b=b||{},this.mousedOverSeg&&(a=a||this.mousedOverSeg,this.mousedOverSeg=null,a.el.removeClass("fc-allow-mouse-resize"),this.view.trigger("eventMouseout",a.el[0],a.event,b))},handleSegMousedown:function(a,b){var c=this.startSegResize(a,b,{distance:5});!c&&this.view.isEventDraggable(a.event)&&this.buildSegDragListener(a).startInteraction(b,{distance:5})},handleSegTouchStart:function(a,b){var c,d=this.view,e=a.event,f=d.isEventSelected(e),g=d.isEventDraggable(e),h=d.isEventResizable(e),i=!1;f&&h&&(i=this.startSegResize(a,b)),i||!g&&!h||(c=g?this.buildSegDragListener(a):this.buildSegSelectListener(a),c.startInteraction(b,{delay:f?0:this.view.opt("longPressDelay")})),this.tempIgnoreMouse()},handleSegTouchEnd:function(a,b){this.tempIgnoreMouse()},startSegResize:function(b,c,d){return a(c.target).is(".fc-resizer")?(this.buildSegResizeListener(b,a(c.target).is(".fc-start-resizer")).startInteraction(c,d),!0):!1},buildSegDragListener:function(a){var b,c,d,e=this,f=this.view,i=f.calendar,j=a.el,k=a.event;if(this.segDragListener)return this.segDragListener;var l=this.segDragListener=new qb(f,{scroll:f.opt("dragScroll"),subjectEl:j,subjectCenter:!0,interactionStart:function(d){b=!1,c=new rb(a.el,{additionalClass:"fc-dragging",parentEl:f.el,opacity:l.isTouch?null:f.opt("dragOpacity"),revertDuration:f.opt("dragRevertDuration"),zIndex:2}),c.hide(),c.start(d)},dragStart:function(c){l.isTouch&&!f.isEventSelected(k)&&f.selectEvent(k),b=!0,e.handleSegMouseout(a,c),e.segDragStart(a,c),f.hideEvent(k)},hitOver:function(b,h,j){var m;a.hit&&(j=a.hit),d=e.computeEventDrop(j.component.getHitSpan(j),b.component.getHitSpan(b),k),d&&!i.isEventSpanAllowed(e.eventToSpan(d),k)&&(g(),d=null),d&&(m=f.renderDrag(d,a))?(m.addClass("fc-dragging"),l.isTouch||e.applyDragOpacity(m),c.hide()):c.show(),h&&(d=null)},hitOut:function(){f.unrenderDrag(),c.show(),d=null},hitDone:function(){h()},interactionEnd:function(g){c.stop(!d,function(){b&&(f.unrenderDrag(),f.showEvent(k),e.segDragStop(a,g)),d&&f.reportEventDrop(k,d,this.largeUnit,j,g)}),e.segDragListener=null}});return l},buildSegSelectListener:function(a){var b=this,c=this.view,d=a.event;if(this.segDragListener)return this.segDragListener;var e=this.segDragListener=new pb({dragStart:function(a){e.isTouch&&!c.isEventSelected(d)&&c.selectEvent(d)},interactionEnd:function(a){b.segDragListener=null}});return e},segDragStart:function(a,b){this.isDraggingSeg=!0,this.view.trigger("eventDragStart",a.el[0],a.event,b,{})},segDragStop:function(a,b){this.isDraggingSeg=!1,this.view.trigger("eventDragStop",a.el[0],a.event,b,{})},computeEventDrop:function(a,b,c){var d,e,f=this.view.calendar,g=a.start,h=b.start;return g.hasTime()===h.hasTime()?(d=this.diffDates(h,g),c.allDay&&T(d)?(e={start:c.start.clone(),end:f.getEventEnd(c),allDay:!1},f.normalizeEventTimes(e)):e={start:c.start.clone(),end:c.end?c.end.clone():null,allDay:c.allDay},e.start.add(d),e.end&&e.end.add(d)):e={start:h.clone(),end:null,allDay:!h.hasTime()},e},applyDragOpacity:function(a){var b=this.view.opt("dragOpacity");null!=b&&a.each(function(a,c){c.style.opacity=b})},externalDragStart:function(b,c){var d,e,f=this.view;f.opt("droppable")&&(d=a((c?c.item:null)||b.target),e=f.opt("dropAccept"),(a.isFunction(e)?e.call(d[0],d):d.is(e))&&(this.isDraggingExternal||this.listenToExternalDrag(d,b,c)))},listenToExternalDrag:function(a,b,c){var d,e=this,f=this.view.calendar,i=Ha(a),j=e.externalDragListener=new qb(this,{interactionStart:function(){e.isDraggingExternal=!0},hitOver:function(a){d=e.computeExternalDrop(a.component.getHitSpan(a),i),d&&!f.isExternalSpanAllowed(e.eventToSpan(d),d,i.eventProps)&&(g(),d=null),d&&e.renderDrag(d)},hitOut:function(){d=null},hitDone:function(){h(),e.unrenderDrag()},interactionEnd:function(b){d&&e.view.reportExternalDrop(i,d,a,b,c),e.isDraggingExternal=!1,e.externalDragListener=null}});j.startDrag(b)},computeExternalDrop:function(a,b){var c=this.view.calendar,d={start:c.applyTimezone(a.start),end:null};return b.startTime&&!d.start.hasTime()&&d.start.time(b.startTime),b.duration&&(d.end=d.start.clone().add(b.duration)),d},renderDrag:function(a,b){},unrenderDrag:function(){},buildSegResizeListener:function(a,b){var c,d,e=this,f=this.view,i=f.calendar,j=a.el,k=a.event,l=i.getEventEnd(k),m=this.segResizeListener=new qb(this,{scroll:f.opt("dragScroll"),subjectEl:j,interactionStart:function(){c=!1},dragStart:function(b){c=!0,e.handleSegMouseout(a,b),e.segResizeStart(a,b)},hitOver:function(c,h,j){var m=e.getHitSpan(j),n=e.getHitSpan(c);d=b?e.computeEventStartResize(m,n,k):e.computeEventEndResize(m,n,k),d&&(i.isEventSpanAllowed(e.eventToSpan(d),k)?d.start.isSame(k.start)&&d.end.isSame(l)&&(d=null):(g(),d=null)),d&&(f.hideEvent(k),e.renderEventResize(d,a))},hitOut:function(){d=null},hitDone:function(){e.unrenderEventResize(),f.showEvent(k),h()},interactionEnd:function(b){c&&e.segResizeStop(a,b),d&&f.reportEventResize(k,d,this.largeUnit,j,b),e.segResizeListener=null}});return m},segResizeStart:function(a,b){this.isResizingSeg=!0,this.view.trigger("eventResizeStart",a.el[0],a.event,b,{})},segResizeStop:function(a,b){this.isResizingSeg=!1,this.view.trigger("eventResizeStop",a.el[0],a.event,b,{})},computeEventStartResize:function(a,b,c){return this.computeEventResize("start",a,b,c)},computeEventEndResize:function(a,b,c){return this.computeEventResize("end",a,b,c)},computeEventResize:function(a,b,c,d){var e,f,g=this.view.calendar,h=this.diffDates(c[a],b[a]);return e={start:d.start.clone(),end:g.getEventEnd(d),allDay:d.allDay},e.allDay&&T(h)&&(e.allDay=!1,g.normalizeEventTimes(e)),e[a].add(h),e.start.isBefore(e.end)||(f=this.minResizeDuration||(d.allDay?g.defaultAllDayEventDuration:g.defaultTimedEventDuration),"start"==a?e.start=e.end.clone().subtract(f):e.end=e.start.clone().add(f)),e},renderEventResize:function(a,b){},unrenderEventResize:function(){},getEventTimeText:function(a,b,c){return null==b&&(b=this.eventTimeFormat),null==c&&(c=this.displayEventEnd),this.displayEventTime&&a.start.hasTime()?c&&a.end?this.view.formatRange(a,b):a.start.format(b):""},getSegClasses:function(a,b,c){var d=this.view,e=a.event,f=["fc-event",a.isStart?"fc-start":"fc-not-start",a.isEnd?"fc-end":"fc-not-end"].concat(e.className,e.source?e.source.className:[]);return b&&f.push("fc-draggable"),c&&f.push("fc-resizable"),d.isEventSelected(e)&&f.push("fc-selected"),f},getSegSkinCss:function(a){var b=a.event,c=this.view,d=b.source||{},e=b.color,f=d.color,g=c.opt("eventColor");return{"background-color":b.backgroundColor||e||d.backgroundColor||f||c.opt("eventBackgroundColor")||g,"border-color":b.borderColor||e||d.borderColor||f||c.opt("eventBorderColor")||g,color:b.textColor||d.textColor||c.opt("eventTextColor")}},eventToSegs:function(a){return this.eventsToSegs([a])},eventToSpan:function(a){return this.eventToSpans(a)[0]},eventToSpans:function(a){var b=this.eventToRange(a);return this.eventRangeToSpans(b,a)},eventsToSegs:function(b,c){var d=this,e=Fa(b),f=[];return a.each(e,function(a,b){var e,g=[];for(e=0;e<b.length;e++)g.push(d.eventToRange(b[e]));if(Da(b[0]))for(g=d.invertRanges(g),e=0;e<g.length;e++)f.push.apply(f,d.eventRangeToSegs(g[e],b[0],c));else for(e=0;e<g.length;e++)f.push.apply(f,d.eventRangeToSegs(g[e],b[e],c))}),f},eventToRange:function(a){return{start:a.start.clone().stripZone(),end:(a.end?a.end.clone():this.view.calendar.getDefaultEventEnd(null!=a.allDay?a.allDay:!a.start.hasTime(),a.start)).stripZone()}},eventRangeToSegs:function(a,b,c){var d,e=this.eventRangeToSpans(a,b),f=[];for(d=0;d<e.length;d++)f.push.apply(f,this.eventSpanToSegs(e[d],b,c));return f},eventRangeToSpans:function(b,c){return[a.extend({},b)]},eventSpanToSegs:function(a,b,c){var d,e,f=c?c(a):this.spanToSegs(a);for(d=0;d<f.length;d++)e=f[d],e.event=b,e.eventStartMS=+a.start,e.eventDurationMS=a.end-a.start;return f},invertRanges:function(a){var b,c,d=this.view,e=d.start.clone(),f=d.end.clone(),g=[],h=e;for(a.sort(Ga),b=0;b<a.length;b++)c=a[b],c.start>h&&g.push({start:h,end:c.start}),h=c.end;return f>h&&g.push({start:h,end:f}),g},sortEventSegs:function(a){a.sort(ia(this,"compareEventSegs"))},compareEventSegs:function(a,b){return a.eventStartMS-b.eventStartMS||b.eventDurationMS-a.eventDurationMS||b.event.allDay-a.event.allDay||H(a.event,b.event,this.view.eventOrderSpecs)}}),Va.isBgEvent=Ca,Va.dataAttrPrefix="";var tb=Va.DayTableMixin={breakOnWeeks:!1,dayDates:null,dayIndices:null,daysPerRow:null,rowCnt:null,colCnt:null,colHeadFormat:null,updateDayTable:function(){for(var a,b,c,d=this.view,e=this.start.clone(),f=-1,g=[],h=[];e.isBefore(this.end);)d.isHiddenDay(e)?g.push(f+.5):(f++,g.push(f),h.push(e.clone())),e.add(1,"days");if(this.breakOnWeeks){for(b=h[0].day(),a=1;a<h.length&&h[a].day()!=b;a++);c=Math.ceil(h.length/a)}else c=1,a=h.length;this.dayDates=h,this.dayIndices=g,this.daysPerRow=a,this.rowCnt=c,this.updateDayTableCols()},updateDayTableCols:function(){this.colCnt=this.computeColCnt(),this.colHeadFormat=this.view.opt("columnFormat")||this.computeColHeadFormat()},computeColCnt:function(){return this.daysPerRow},getCellDate:function(a,b){return this.dayDates[this.getCellDayIndex(a,b)].clone()},getCellRange:function(a,b){var c=this.getCellDate(a,b),d=c.clone().add(1,"days");return{start:c,end:d}},getCellDayIndex:function(a,b){return a*this.daysPerRow+this.getColDayIndex(b)},getColDayIndex:function(a){return this.isRTL?this.colCnt-1-a:a},getDateDayIndex:function(a){var b=this.dayIndices,c=a.diff(this.start,"days");return 0>c?b[0]-1:c>=b.length?b[b.length-1]+1:b[c]},computeColHeadFormat:function(){return this.rowCnt>1||this.colCnt>10?"ddd":this.colCnt>1?this.view.opt("dayOfMonthFormat"):"dddd"},sliceRangeByRow:function(a){var b,c,d,e,f,g=this.daysPerRow,h=this.view.computeDayRange(a),i=this.getDateDayIndex(h.start),j=this.getDateDayIndex(h.end.clone().subtract(1,"days")),k=[];for(b=0;b<this.rowCnt;b++)c=b*g,d=c+g-1,e=Math.max(i,c),f=Math.min(j,d),e=Math.ceil(e),f=Math.floor(f),f>=e&&k.push({row:b,firstRowDayIndex:e-c,lastRowDayIndex:f-c,isStart:e===i,isEnd:f===j});return k},sliceRangeByDay:function(a){var b,c,d,e,f,g,h=this.daysPerRow,i=this.view.computeDayRange(a),j=this.getDateDayIndex(i.start),k=this.getDateDayIndex(i.end.clone().subtract(1,"days")),l=[];for(b=0;b<this.rowCnt;b++)for(c=b*h,d=c+h-1,e=c;d>=e;e++)f=Math.max(j,e),g=Math.min(k,e),f=Math.ceil(f),g=Math.floor(g),g>=f&&l.push({row:b,firstRowDayIndex:f-c,lastRowDayIndex:g-c,isStart:f===j,isEnd:g===k});return l},renderHeadHtml:function(){var a=this.view;return'<div class="fc-row '+a.widgetHeaderClass+'"><table><thead>'+this.renderHeadTrHtml()+"</thead></table></div>"},renderHeadIntroHtml:function(){return this.renderIntroHtml()},renderHeadTrHtml:function(){return"<tr>"+(this.isRTL?"":this.renderHeadIntroHtml())+this.renderHeadDateCellsHtml()+(this.isRTL?this.renderHeadIntroHtml():"")+"</tr>"},renderHeadDateCellsHtml:function(){var a,b,c=[];for(a=0;a<this.colCnt;a++)b=this.getCellDate(0,a),c.push(this.renderHeadDateCellHtml(b));return c.join("")},renderHeadDateCellHtml:function(a,b,c){var d=this.view;return'<th class="fc-day-header '+d.widgetHeaderClass+" fc-"+Za[a.day()]+'"'+(1==this.rowCnt?' data-date="'+a.format("YYYY-MM-DD")+'"':"")+(b>1?' colspan="'+b+'"':"")+(c?" "+c:"")+">"+ca(a.format(this.colHeadFormat))+"</th>"},renderBgTrHtml:function(a){return"<tr>"+(this.isRTL?"":this.renderBgIntroHtml(a))+this.renderBgCellsHtml(a)+(this.isRTL?this.renderBgIntroHtml(a):"")+"</tr>"; -},renderBgIntroHtml:function(a){return this.renderIntroHtml()},renderBgCellsHtml:function(a){var b,c,d=[];for(b=0;b<this.colCnt;b++)c=this.getCellDate(a,b),d.push(this.renderBgCellHtml(c));return d.join("")},renderBgCellHtml:function(a,b){var c=this.view,d=this.getDayClasses(a);return d.unshift("fc-day",c.widgetContentClass),'<td class="'+d.join(" ")+'" data-date="'+a.format("YYYY-MM-DD")+'"'+(b?" "+b:"")+"></td>"},renderIntroHtml:function(){},bookendCells:function(a){var b=this.renderIntroHtml();b&&(this.isRTL?a.append(b):a.prepend(b))}},ub=Va.DayGrid=sb.extend(tb,{numbersVisible:!1,bottomCoordPadding:0,rowEls:null,cellEls:null,helperEls:null,rowCoordCache:null,colCoordCache:null,renderDates:function(a){var b,c,d=this.view,e=this.rowCnt,f=this.colCnt,g="";for(b=0;e>b;b++)g+=this.renderDayRowHtml(b,a);for(this.el.html(g),this.rowEls=this.el.find(".fc-row"),this.cellEls=this.el.find(".fc-day"),this.rowCoordCache=new ob({els:this.rowEls,isVertical:!0}),this.colCoordCache=new ob({els:this.cellEls.slice(0,this.colCnt),isHorizontal:!0}),b=0;e>b;b++)for(c=0;f>c;c++)d.trigger("dayRender",null,this.getCellDate(b,c),this.getCellEl(b,c))},unrenderDates:function(){this.removeSegPopover()},renderBusinessHours:function(){var a=this.view.calendar.getBusinessHoursEvents(!0),b=this.eventsToSegs(a);this.renderFill("businessHours",b,"bgevent")},renderDayRowHtml:function(a,b){var c=this.view,d=["fc-row","fc-week",c.widgetContentClass];return b&&d.push("fc-rigid"),'<div class="'+d.join(" ")+'"><div class="fc-bg"><table>'+this.renderBgTrHtml(a)+'</table></div><div class="fc-content-skeleton"><table>'+(this.numbersVisible?"<thead>"+this.renderNumberTrHtml(a)+"</thead>":"")+"</table></div></div>"},renderNumberTrHtml:function(a){return"<tr>"+(this.isRTL?"":this.renderNumberIntroHtml(a))+this.renderNumberCellsHtml(a)+(this.isRTL?this.renderNumberIntroHtml(a):"")+"</tr>"},renderNumberIntroHtml:function(a){return this.renderIntroHtml()},renderNumberCellsHtml:function(a){var b,c,d=[];for(b=0;b<this.colCnt;b++)c=this.getCellDate(a,b),d.push(this.renderNumberCellHtml(c));return d.join("")},renderNumberCellHtml:function(a){var b;return this.view.dayNumbersVisible?(b=this.getDayClasses(a),b.unshift("fc-day-number"),'<td class="'+b.join(" ")+'" data-date="'+a.format()+'">'+a.date()+"</td>"):"<td/>"},computeEventTimeFormat:function(){return this.view.opt("extraSmallTimeFormat")},computeDisplayEventEnd:function(){return 1==this.colCnt},rangeUpdated:function(){this.updateDayTable()},spanToSegs:function(a){var b,c,d=this.sliceRangeByRow(a);for(b=0;b<d.length;b++)c=d[b],this.isRTL?(c.leftCol=this.daysPerRow-1-c.lastRowDayIndex,c.rightCol=this.daysPerRow-1-c.firstRowDayIndex):(c.leftCol=c.firstRowDayIndex,c.rightCol=c.lastRowDayIndex);return d},prepareHits:function(){this.colCoordCache.build(),this.rowCoordCache.build(),this.rowCoordCache.bottoms[this.rowCnt-1]+=this.bottomCoordPadding},releaseHits:function(){this.colCoordCache.clear(),this.rowCoordCache.clear()},queryHit:function(a,b){var c=this.colCoordCache.getHorizontalIndex(a),d=this.rowCoordCache.getVerticalIndex(b);return null!=d&&null!=c?this.getCellHit(d,c):void 0},getHitSpan:function(a){return this.getCellRange(a.row,a.col)},getHitEl:function(a){return this.getCellEl(a.row,a.col)},getCellHit:function(a,b){return{row:a,col:b,component:this,left:this.colCoordCache.getLeftOffset(b),right:this.colCoordCache.getRightOffset(b),top:this.rowCoordCache.getTopOffset(a),bottom:this.rowCoordCache.getBottomOffset(a)}},getCellEl:function(a,b){return this.cellEls.eq(a*this.colCnt+b)},renderDrag:function(a,b){return this.renderHighlight(this.eventToSpan(a)),b&&!b.el.closest(this.el).length?this.renderEventLocationHelper(a,b):void 0},unrenderDrag:function(){this.unrenderHighlight(),this.unrenderHelper()},renderEventResize:function(a,b){return this.renderHighlight(this.eventToSpan(a)),this.renderEventLocationHelper(a,b)},unrenderEventResize:function(){this.unrenderHighlight(),this.unrenderHelper()},renderHelper:function(b,c){var d,e=[],f=this.eventToSegs(b);return f=this.renderFgSegEls(f),d=this.renderSegRows(f),this.rowEls.each(function(b,f){var g,h=a(f),i=a('<div class="fc-helper-skeleton"><table/></div>');g=c&&c.row===b?c.el.position().top:h.find(".fc-content-skeleton tbody").position().top,i.css("top",g).find("table").append(d[b].tbodyEl),h.append(i),e.push(i[0])}),this.helperEls=a(e)},unrenderHelper:function(){this.helperEls&&(this.helperEls.remove(),this.helperEls=null)},fillSegTag:"td",renderFill:function(b,c,d){var e,f,g,h=[];for(c=this.renderFillSegEls(b,c),e=0;e<c.length;e++)f=c[e],g=this.renderFillRow(b,f,d),this.rowEls.eq(f.row).append(g),h.push(g[0]);return this.elsByFill[b]=a(h),c},renderFillRow:function(b,c,d){var e,f,g=this.colCnt,h=c.leftCol,i=c.rightCol+1;return d=d||b.toLowerCase(),e=a('<div class="fc-'+d+'-skeleton"><table><tr/></table></div>'),f=e.find("tr"),h>0&&f.append('<td colspan="'+h+'"/>'),f.append(c.el.attr("colspan",i-h)),g>i&&f.append('<td colspan="'+(g-i)+'"/>'),this.bookendCells(f),e}});ub.mixin({rowStructs:null,unrenderEvents:function(){this.removeSegPopover(),sb.prototype.unrenderEvents.apply(this,arguments)},getEventSegs:function(){return sb.prototype.getEventSegs.call(this).concat(this.popoverSegs||[])},renderBgSegs:function(b){var c=a.grep(b,function(a){return a.event.allDay});return sb.prototype.renderBgSegs.call(this,c)},renderFgSegs:function(b){var c;return b=this.renderFgSegEls(b),c=this.rowStructs=this.renderSegRows(b),this.rowEls.each(function(b,d){a(d).find(".fc-content-skeleton > table").append(c[b].tbodyEl)}),b},unrenderFgSegs:function(){for(var a,b=this.rowStructs||[];a=b.pop();)a.tbodyEl.remove();this.rowStructs=null},renderSegRows:function(a){var b,c,d=[];for(b=this.groupSegRows(a),c=0;c<b.length;c++)d.push(this.renderSegRow(c,b[c]));return d},fgSegHtml:function(a,b){var c,d,e=this.view,f=a.event,g=e.isEventDraggable(f),h=!b&&f.allDay&&a.isStart&&e.isEventResizableFromStart(f),i=!b&&f.allDay&&a.isEnd&&e.isEventResizableFromEnd(f),j=this.getSegClasses(a,g,h||i),k=ea(this.getSegSkinCss(a)),l="";return j.unshift("fc-day-grid-event","fc-h-event"),a.isStart&&(c=this.getEventTimeText(f),c&&(l='<span class="fc-time">'+ca(c)+"</span>")),d='<span class="fc-title">'+(ca(f.title||"")||" ")+"</span>",'<a class="'+j.join(" ")+'"'+(f.url?' href="'+ca(f.url)+'"':"")+(k?' style="'+k+'"':"")+'><div class="fc-content">'+(this.isRTL?d+" "+l:l+" "+d)+"</div>"+(h?'<div class="fc-resizer fc-start-resizer" />':"")+(i?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},renderSegRow:function(b,c){function d(b){for(;b>g;)k=(r[e-1]||[])[g],k?k.attr("rowspan",parseInt(k.attr("rowspan")||1,10)+1):(k=a("<td/>"),h.append(k)),q[e][g]=k,r[e][g]=k,g++}var e,f,g,h,i,j,k,l=this.colCnt,m=this.buildSegLevels(c),n=Math.max(1,m.length),o=a("<tbody/>"),p=[],q=[],r=[];for(e=0;n>e;e++){if(f=m[e],g=0,h=a("<tr/>"),p.push([]),q.push([]),r.push([]),f)for(i=0;i<f.length;i++){for(j=f[i],d(j.leftCol),k=a('<td class="fc-event-container"/>').append(j.el),j.leftCol!=j.rightCol?k.attr("colspan",j.rightCol-j.leftCol+1):r[e][g]=k;g<=j.rightCol;)q[e][g]=k,p[e][g]=j,g++;h.append(k)}d(l),this.bookendCells(h),o.append(h)}return{row:b,tbodyEl:o,cellMatrix:q,segMatrix:p,segLevels:m,segs:c}},buildSegLevels:function(a){var b,c,d,e=[];for(this.sortEventSegs(a),b=0;b<a.length;b++){for(c=a[b],d=0;d<e.length&&Ia(c,e[d]);d++);c.level=d,(e[d]||(e[d]=[])).push(c)}for(d=0;d<e.length;d++)e[d].sort(Ja);return e},groupSegRows:function(a){var b,c=[];for(b=0;b<this.rowCnt;b++)c.push([]);for(b=0;b<a.length;b++)c[a[b].row].push(a[b]);return c}}),ub.mixin({segPopover:null,popoverSegs:null,removeSegPopover:function(){this.segPopover&&this.segPopover.hide()},limitRows:function(a){var b,c,d=this.rowStructs||[];for(b=0;b<d.length;b++)this.unlimitRow(b),c=a?"number"==typeof a?a:this.computeRowLevelLimit(b):!1,c!==!1&&this.limitRow(b,c)},computeRowLevelLimit:function(b){function c(b,c){f=Math.max(f,a(c).outerHeight())}var d,e,f,g=this.rowEls.eq(b),h=g.height(),i=this.rowStructs[b].tbodyEl.children();for(d=0;d<i.length;d++)if(e=i.eq(d).removeClass("fc-limited"),f=0,e.find("> td > :first-child").each(c),e.position().top+f>h)return d;return!1},limitRow:function(b,c){function d(d){for(;d>w;)j=t.getCellSegs(b,w,c),j.length&&(m=f[c-1][w],s=t.renderMoreLink(b,w,j),r=a("<div/>").append(s),m.append(r),v.push(r[0])),w++}var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t=this,u=this.rowStructs[b],v=[],w=0;if(c&&c<u.segLevels.length){for(e=u.segLevels[c-1],f=u.cellMatrix,g=u.tbodyEl.children().slice(c).addClass("fc-limited").get(),h=0;h<e.length;h++){for(i=e[h],d(i.leftCol),l=[],k=0;w<=i.rightCol;)j=this.getCellSegs(b,w,c),l.push(j),k+=j.length,w++;if(k){for(m=f[c-1][i.leftCol],n=m.attr("rowspan")||1,o=[],p=0;p<l.length;p++)q=a('<td class="fc-more-cell"/>').attr("rowspan",n),j=l[p],s=this.renderMoreLink(b,i.leftCol+p,[i].concat(j)),r=a("<div/>").append(s),q.append(r),o.push(q[0]),v.push(q[0]);m.addClass("fc-limited").after(a(o)),g.push(m[0])}}d(this.colCnt),u.moreEls=a(v),u.limitedEls=a(g)}},unlimitRow:function(a){var b=this.rowStructs[a];b.moreEls&&(b.moreEls.remove(),b.moreEls=null),b.limitedEls&&(b.limitedEls.removeClass("fc-limited"),b.limitedEls=null)},renderMoreLink:function(b,c,d){var e=this,f=this.view;return a('<a class="fc-more"/>').text(this.getMoreLinkText(d.length)).on("click",function(g){var h=f.opt("eventLimitClick"),i=e.getCellDate(b,c),j=a(this),k=e.getCellEl(b,c),l=e.getCellSegs(b,c),m=e.resliceDaySegs(l,i),n=e.resliceDaySegs(d,i);"function"==typeof h&&(h=f.trigger("eventLimitClick",null,{date:i,dayEl:k,moreEl:j,segs:m,hiddenSegs:n},g)),"popover"===h?e.showSegPopover(b,c,j,m):"string"==typeof h&&f.calendar.zoomTo(i,h)})},showSegPopover:function(a,b,c,d){var e,f,g=this,h=this.view,i=c.parent();e=1==this.rowCnt?h.el:this.rowEls.eq(a),f={className:"fc-more-popover",content:this.renderSegPopoverContent(a,b,d),parentEl:this.el,top:e.offset().top,autoHide:!0,viewportConstrain:h.opt("popoverViewportConstrain"),hide:function(){g.segPopover.removeElement(),g.segPopover=null,g.popoverSegs=null}},this.isRTL?f.right=i.offset().left+i.outerWidth()+1:f.left=i.offset().left-1,this.segPopover=new nb(f),this.segPopover.show()},renderSegPopoverContent:function(b,c,d){var e,f=this.view,g=f.opt("theme"),h=this.getCellDate(b,c).format(f.opt("dayPopoverFormat")),i=a('<div class="fc-header '+f.widgetHeaderClass+'"><span class="fc-close '+(g?"ui-icon ui-icon-closethick":"fc-icon fc-icon-x")+'"></span><span class="fc-title">'+ca(h)+'</span><div class="fc-clear"/></div><div class="fc-body '+f.widgetContentClass+'"><div class="fc-event-container"></div></div>'),j=i.find(".fc-event-container");for(d=this.renderFgSegEls(d,!0),this.popoverSegs=d,e=0;e<d.length;e++)this.prepareHits(),d[e].hit=this.getCellHit(b,c),this.releaseHits(),j.append(d[e].el);return i},resliceDaySegs:function(b,c){var d=a.map(b,function(a){return a.event}),e=c.clone(),f=e.clone().add(1,"days"),g={start:e,end:f};return b=this.eventsToSegs(d,function(a){var b=K(a,g);return b?[b]:[]}),this.sortEventSegs(b),b},getMoreLinkText:function(a){var b=this.view.opt("eventLimitText");return"function"==typeof b?b(a):"+"+a+" "+b},getCellSegs:function(a,b,c){for(var d,e=this.rowStructs[a].segMatrix,f=c||0,g=[];f<e.length;)d=e[f][b],d&&g.push(d),f++;return g}});var vb=Va.TimeGrid=sb.extend(tb,{slotDuration:null,snapDuration:null,snapsPerSlot:null,minTime:null,maxTime:null,labelFormat:null,labelInterval:null,colEls:null,slatContainerEl:null,slatEls:null,nowIndicatorEls:null,colCoordCache:null,slatCoordCache:null,constructor:function(){sb.apply(this,arguments),this.processOptions()},renderDates:function(){this.el.html(this.renderHtml()),this.colEls=this.el.find(".fc-day"),this.slatContainerEl=this.el.find(".fc-slats"),this.slatEls=this.slatContainerEl.find("tr"),this.colCoordCache=new ob({els:this.colEls,isHorizontal:!0}),this.slatCoordCache=new ob({els:this.slatEls,isVertical:!0}),this.renderContentSkeleton()},renderHtml:function(){return'<div class="fc-bg"><table>'+this.renderBgTrHtml(0)+'</table></div><div class="fc-slats"><table>'+this.renderSlatRowHtml()+"</table></div>"},renderSlatRowHtml:function(){for(var a,c,d,e=this.view,f=this.isRTL,g="",h=b.duration(+this.minTime);h<this.maxTime;)a=this.start.clone().time(h),c=ha(R(h,this.labelInterval)),d='<td class="fc-axis fc-time '+e.widgetContentClass+'" '+e.axisStyleAttr()+">"+(c?"<span>"+ca(a.format(this.labelFormat))+"</span>":"")+"</td>",g+='<tr data-time="'+a.format("HH:mm:ss")+'"'+(c?"":' class="fc-minor"')+">"+(f?"":d)+'<td class="'+e.widgetContentClass+'"/>'+(f?d:"")+"</tr>",h.add(this.slotDuration);return g},processOptions:function(){var c,d=this.view,e=d.opt("slotDuration"),f=d.opt("snapDuration");e=b.duration(e),f=f?b.duration(f):e,this.slotDuration=e,this.snapDuration=f,this.snapsPerSlot=e/f,this.minResizeDuration=f,this.minTime=b.duration(d.opt("minTime")),this.maxTime=b.duration(d.opt("maxTime")),c=d.opt("slotLabelFormat"),a.isArray(c)&&(c=c[c.length-1]),this.labelFormat=c||d.opt("axisFormat")||d.opt("smallTimeFormat"),c=d.opt("slotLabelInterval"),this.labelInterval=c?b.duration(c):this.computeLabelInterval(e)},computeLabelInterval:function(a){var c,d,e;for(c=Mb.length-1;c>=0;c--)if(d=b.duration(Mb[c]),e=R(d,a),ha(e)&&e>1)return d;return b.duration(a)},computeEventTimeFormat:function(){return this.view.opt("noMeridiemTimeFormat")},computeDisplayEventEnd:function(){return!0},prepareHits:function(){this.colCoordCache.build(),this.slatCoordCache.build()},releaseHits:function(){this.colCoordCache.clear()},queryHit:function(a,b){var c=this.snapsPerSlot,d=this.colCoordCache,e=this.slatCoordCache,f=d.getHorizontalIndex(a),g=e.getVerticalIndex(b);if(null!=f&&null!=g){var h=e.getTopOffset(g),i=e.getHeight(g),j=(b-h)/i,k=Math.floor(j*c),l=g*c+k,m=h+k/c*i,n=h+(k+1)/c*i;return{col:f,snap:l,component:this,left:d.getLeftOffset(f),right:d.getRightOffset(f),top:m,bottom:n}}},getHitSpan:function(a){var b,c=this.getCellDate(0,a.col),d=this.computeSnapTime(a.snap);return c.time(d),b=c.clone().add(this.snapDuration),{start:c,end:b}},getHitEl:function(a){return this.colEls.eq(a.col)},rangeUpdated:function(){this.updateDayTable()},computeSnapTime:function(a){return b.duration(this.minTime+this.snapDuration*a)},spanToSegs:function(a){var b,c=this.sliceRangeByTimes(a);for(b=0;b<c.length;b++)this.isRTL?c[b].col=this.daysPerRow-1-c[b].dayIndex:c[b].col=c[b].dayIndex;return c},sliceRangeByTimes:function(a){var b,c,d,e,f=[];for(c=0;c<this.daysPerRow;c++)d=this.dayDates[c].clone(),e={start:d.clone().time(this.minTime),end:d.clone().time(this.maxTime)},b=K(a,e),b&&(b.dayIndex=c,f.push(b));return f},updateSize:function(a){this.slatCoordCache.build(),a&&this.updateSegVerticals([].concat(this.fgSegs||[],this.bgSegs||[],this.businessSegs||[]))},getTotalSlatHeight:function(){return this.slatContainerEl.outerHeight()},computeDateTop:function(a,c){return this.computeTimeTop(b.duration(a-c.clone().stripTime()))},computeTimeTop:function(a){var b,c,d=this.slatEls.length,e=(a-this.minTime)/this.slotDuration;return e=Math.max(0,e),e=Math.min(d,e),b=Math.floor(e),b=Math.min(b,d-1),c=e-b,this.slatCoordCache.getTopPosition(b)+this.slatCoordCache.getHeight(b)*c},renderDrag:function(a,b){return b?this.renderEventLocationHelper(a,b):void this.renderHighlight(this.eventToSpan(a))},unrenderDrag:function(){this.unrenderHelper(),this.unrenderHighlight()},renderEventResize:function(a,b){return this.renderEventLocationHelper(a,b)},unrenderEventResize:function(){this.unrenderHelper()},renderHelper:function(a,b){return this.renderHelperSegs(this.eventToSegs(a),b)},unrenderHelper:function(){this.unrenderHelperSegs()},renderBusinessHours:function(){var a=this.view.calendar.getBusinessHoursEvents(),b=this.eventsToSegs(a);this.renderBusinessSegs(b)},unrenderBusinessHours:function(){this.unrenderBusinessSegs()},getNowIndicatorUnit:function(){return"minute"},renderNowIndicator:function(b){var c,d=this.spanToSegs({start:b,end:b}),e=this.computeDateTop(b,b),f=[];for(c=0;c<d.length;c++)f.push(a('<div class="fc-now-indicator fc-now-indicator-line"></div>').css("top",e).appendTo(this.colContainerEls.eq(d[c].col))[0]);d.length>0&&f.push(a('<div class="fc-now-indicator fc-now-indicator-arrow"></div>').css("top",e).appendTo(this.el.find(".fc-content-skeleton"))[0]),this.nowIndicatorEls=a(f)},unrenderNowIndicator:function(){this.nowIndicatorEls&&(this.nowIndicatorEls.remove(),this.nowIndicatorEls=null)},renderSelection:function(a){this.view.opt("selectHelper")?this.renderEventLocationHelper(a):this.renderHighlight(a)},unrenderSelection:function(){this.unrenderHelper(),this.unrenderHighlight()},renderHighlight:function(a){this.renderHighlightSegs(this.spanToSegs(a))},unrenderHighlight:function(){this.unrenderHighlightSegs()}});vb.mixin({colContainerEls:null,fgContainerEls:null,bgContainerEls:null,helperContainerEls:null,highlightContainerEls:null,businessContainerEls:null,fgSegs:null,bgSegs:null,helperSegs:null,highlightSegs:null,businessSegs:null,renderContentSkeleton:function(){var b,c,d="";for(b=0;b<this.colCnt;b++)d+='<td><div class="fc-content-col"><div class="fc-event-container fc-helper-container"></div><div class="fc-event-container"></div><div class="fc-highlight-container"></div><div class="fc-bgevent-container"></div><div class="fc-business-container"></div></div></td>';c=a('<div class="fc-content-skeleton"><table><tr>'+d+"</tr></table></div>"),this.colContainerEls=c.find(".fc-content-col"),this.helperContainerEls=c.find(".fc-helper-container"),this.fgContainerEls=c.find(".fc-event-container:not(.fc-helper-container)"),this.bgContainerEls=c.find(".fc-bgevent-container"),this.highlightContainerEls=c.find(".fc-highlight-container"),this.businessContainerEls=c.find(".fc-business-container"),this.bookendCells(c.find("tr")),this.el.append(c)},renderFgSegs:function(a){return a=this.renderFgSegsIntoContainers(a,this.fgContainerEls),this.fgSegs=a,a},unrenderFgSegs:function(){this.unrenderNamedSegs("fgSegs")},renderHelperSegs:function(b,c){var d,e,f,g=[];for(b=this.renderFgSegsIntoContainers(b,this.helperContainerEls),d=0;d<b.length;d++)e=b[d],c&&c.col===e.col&&(f=c.el,e.el.css({left:f.css("left"),right:f.css("right"),"margin-left":f.css("margin-left"),"margin-right":f.css("margin-right")})),g.push(e.el[0]);return this.helperSegs=b,a(g)},unrenderHelperSegs:function(){this.unrenderNamedSegs("helperSegs")},renderBgSegs:function(a){return a=this.renderFillSegEls("bgEvent",a),this.updateSegVerticals(a),this.attachSegsByCol(this.groupSegsByCol(a),this.bgContainerEls),this.bgSegs=a,a},unrenderBgSegs:function(){this.unrenderNamedSegs("bgSegs")},renderHighlightSegs:function(a){a=this.renderFillSegEls("highlight",a),this.updateSegVerticals(a),this.attachSegsByCol(this.groupSegsByCol(a),this.highlightContainerEls),this.highlightSegs=a},unrenderHighlightSegs:function(){this.unrenderNamedSegs("highlightSegs")},renderBusinessSegs:function(a){a=this.renderFillSegEls("businessHours",a),this.updateSegVerticals(a),this.attachSegsByCol(this.groupSegsByCol(a),this.businessContainerEls),this.businessSegs=a},unrenderBusinessSegs:function(){this.unrenderNamedSegs("businessSegs")},groupSegsByCol:function(a){var b,c=[];for(b=0;b<this.colCnt;b++)c.push([]);for(b=0;b<a.length;b++)c[a[b].col].push(a[b]);return c},attachSegsByCol:function(a,b){var c,d,e;for(c=0;c<this.colCnt;c++)for(d=a[c],e=0;e<d.length;e++)b.eq(c).append(d[e].el)},unrenderNamedSegs:function(a){var b,c=this[a];if(c){for(b=0;b<c.length;b++)c[b].el.remove();this[a]=null}},renderFgSegsIntoContainers:function(a,b){var c,d;for(a=this.renderFgSegEls(a),c=this.groupSegsByCol(a),d=0;d<this.colCnt;d++)this.updateFgSegCoords(c[d]);return this.attachSegsByCol(c,b),a},fgSegHtml:function(a,b){var c,d,e,f=this.view,g=a.event,h=f.isEventDraggable(g),i=!b&&a.isStart&&f.isEventResizableFromStart(g),j=!b&&a.isEnd&&f.isEventResizableFromEnd(g),k=this.getSegClasses(a,h,i||j),l=ea(this.getSegSkinCss(a));return k.unshift("fc-time-grid-event","fc-v-event"),f.isMultiDayEvent(g)?(a.isStart||a.isEnd)&&(c=this.getEventTimeText(a),d=this.getEventTimeText(a,"LT"),e=this.getEventTimeText(a,null,!1)):(c=this.getEventTimeText(g),d=this.getEventTimeText(g,"LT"),e=this.getEventTimeText(g,null,!1)),'<a class="'+k.join(" ")+'"'+(g.url?' href="'+ca(g.url)+'"':"")+(l?' style="'+l+'"':"")+'><div class="fc-content">'+(c?'<div class="fc-time" data-start="'+ca(e)+'" data-full="'+ca(d)+'"><span>'+ca(c)+"</span></div>":"")+(g.title?'<div class="fc-title">'+ca(g.title)+"</div>":"")+'</div><div class="fc-bg"/>'+(j?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},updateSegVerticals:function(a){this.computeSegVerticals(a),this.assignSegVerticals(a)},computeSegVerticals:function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.top=this.computeDateTop(c.start,c.start),c.bottom=this.computeDateTop(c.end,c.start)},assignSegVerticals:function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.el.css(this.generateSegVerticalCss(c))},generateSegVerticalCss:function(a){return{top:a.top,bottom:-a.bottom}},updateFgSegCoords:function(a){this.computeSegVerticals(a),this.computeFgSegHorizontals(a),this.assignSegVerticals(a),this.assignFgSegHorizontals(a)},computeFgSegHorizontals:function(a){var b,c,d;if(this.sortEventSegs(a),b=Ka(a),La(b),c=b[0]){for(d=0;d<c.length;d++)Ma(c[d]);for(d=0;d<c.length;d++)this.computeFgSegForwardBack(c[d],0,0)}},computeFgSegForwardBack:function(a,b,c){var d,e=a.forwardSegs;if(void 0===a.forwardCoord)for(e.length?(this.sortForwardSegs(e),this.computeFgSegForwardBack(e[0],b+1,c),a.forwardCoord=e[0].backwardCoord):a.forwardCoord=1,a.backwardCoord=a.forwardCoord-(a.forwardCoord-c)/(b+1),d=0;d<e.length;d++)this.computeFgSegForwardBack(e[d],0,a.forwardCoord)},sortForwardSegs:function(a){a.sort(ia(this,"compareForwardSegs"))},compareForwardSegs:function(a,b){return b.forwardPressure-a.forwardPressure||(a.backwardCoord||0)-(b.backwardCoord||0)||this.compareEventSegs(a,b)},assignFgSegHorizontals:function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.el.css(this.generateFgSegHorizontalCss(c)),c.bottom-c.top<30&&c.el.addClass("fc-short")},generateFgSegHorizontalCss:function(a){var b,c,d=this.view.opt("slotEventOverlap"),e=a.backwardCoord,f=a.forwardCoord,g=this.generateSegVerticalCss(a);return d&&(f=Math.min(1,e+2*(f-e))),this.isRTL?(b=1-f,c=e):(b=e,c=1-f),g.zIndex=a.level+1,g.left=100*b+"%",g.right=100*c+"%",d&&a.forwardPressure&&(g[this.isRTL?"marginLeft":"marginRight"]=20),g}});var wb=Va.View=xa.extend(kb,lb,{type:null,name:null,title:null,calendar:null,options:null,el:null,displaying:null,isSkeletonRendered:!1,isEventsRendered:!1,start:null,end:null,intervalStart:null,intervalEnd:null,intervalDuration:null,intervalUnit:null,isRTL:!1,isSelected:!1,selectedEvent:null,eventOrderSpecs:null,widgetHeaderClass:null,widgetContentClass:null,highlightStateClass:null,nextDayThreshold:null,isHiddenDayHash:null,isNowIndicatorRendered:null,initialNowDate:null,initialNowQueriedMs:null,nowIndicatorTimeoutID:null,nowIndicatorIntervalID:null,constructor:function(a,c,d,e){this.calendar=a,this.type=this.name=c,this.options=d,this.intervalDuration=e||b.duration(1,"day"),this.nextDayThreshold=b.duration(this.opt("nextDayThreshold")),this.initThemingProps(),this.initHiddenDays(),this.isRTL=this.opt("isRTL"),this.eventOrderSpecs=G(this.opt("eventOrder")),this.initialize()},initialize:function(){},opt:function(a){return this.options[a]},trigger:function(a,b){var c=this.calendar;return c.trigger.apply(c,[a,b||this].concat(Array.prototype.slice.call(arguments,2),[this]))},setDate:function(a){this.setRange(this.computeRange(a))},setRange:function(b){a.extend(this,b),this.updateTitle()},computeRange:function(a){var b,c,d=O(this.intervalDuration),e=a.clone().startOf(d),f=e.clone().add(this.intervalDuration);return/year|month|week|day/.test(d)?(e.stripTime(),f.stripTime()):(e.hasTime()||(e=this.calendar.time(0)),f.hasTime()||(f=this.calendar.time(0))),b=e.clone(),b=this.skipHiddenDays(b),c=f.clone(),c=this.skipHiddenDays(c,-1,!0),{intervalUnit:d,intervalStart:e,intervalEnd:f,start:b,end:c}},computePrevDate:function(a){return this.massageCurrentDate(a.clone().startOf(this.intervalUnit).subtract(this.intervalDuration),-1)},computeNextDate:function(a){return this.massageCurrentDate(a.clone().startOf(this.intervalUnit).add(this.intervalDuration))},massageCurrentDate:function(a,b){return this.intervalDuration.as("days")<=1&&this.isHiddenDay(a)&&(a=this.skipHiddenDays(a,b),a.startOf("day")),a},updateTitle:function(){this.title=this.computeTitle()},computeTitle:function(){return this.formatRange({start:this.calendar.applyTimezone(this.intervalStart),end:this.calendar.applyTimezone(this.intervalEnd)},this.opt("titleFormat")||this.computeTitleFormat(),this.opt("titleRangeSeparator"))},computeTitleFormat:function(){return"year"==this.intervalUnit?"YYYY":"month"==this.intervalUnit?this.opt("monthYearFormat"):this.intervalDuration.as("days")>1?"ll":"LL"},formatRange:function(a,b,c){var d=a.end;return d.hasTime()||(d=d.clone().subtract(1)),sa(a.start,d,b,c,this.opt("isRTL"))},setElement:function(a){this.el=a,this.bindGlobalHandlers()},removeElement:function(){this.clear(),this.isSkeletonRendered&&(this.unrenderSkeleton(),this.isSkeletonRendered=!1),this.unbindGlobalHandlers(),this.el.remove()},display:function(b){var c=this,d=null;return this.displaying&&(d=this.queryScroll()),this.calendar.freezeContentHeight(),this.clear().then(function(){return c.displaying=a.when(c.displayView(b)).then(function(){c.forceScroll(c.computeInitialScroll(d)),c.calendar.unfreezeContentHeight(),c.triggerRender()})})},clear:function(){var b=this,c=this.displaying;return c?c.then(function(){return b.displaying=null,b.clearEvents(),b.clearView()}):a.when()},displayView:function(a){this.isSkeletonRendered||(this.renderSkeleton(),this.isSkeletonRendered=!0),a&&this.setDate(a),this.render&&this.render(),this.renderDates(),this.updateSize(),this.renderBusinessHours(),this.startNowIndicator()},clearView:function(){this.unselect(),this.stopNowIndicator(),this.triggerUnrender(),this.unrenderBusinessHours(),this.unrenderDates(),this.destroy&&this.destroy()},renderSkeleton:function(){},unrenderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},triggerRender:function(){this.trigger("viewRender",this,this,this.el)},triggerUnrender:function(){this.trigger("viewDestroy",this,this,this.el)},bindGlobalHandlers:function(){this.listenTo(a(document),"mousedown",this.handleDocumentMousedown),this.listenTo(a(document),"touchstart",this.processUnselect)},unbindGlobalHandlers:function(){this.stopListeningTo(a(document))},initThemingProps:function(){var a=this.opt("theme")?"ui":"fc";this.widgetHeaderClass=a+"-widget-header",this.widgetContentClass=a+"-widget-content",this.highlightStateClass=a+"-state-highlight"},renderBusinessHours:function(){},unrenderBusinessHours:function(){},startNowIndicator:function(){var a,c,d,e=this;this.opt("nowIndicator")&&(a=this.getNowIndicatorUnit(),a&&(c=ia(this,"updateNowIndicator"),this.initialNowDate=this.calendar.getNow(),this.initialNowQueriedMs=+new Date,this.renderNowIndicator(this.initialNowDate),this.isNowIndicatorRendered=!0,d=this.initialNowDate.clone().startOf(a).add(1,a)-this.initialNowDate,this.nowIndicatorTimeoutID=setTimeout(function(){e.nowIndicatorTimeoutID=null,c(),d=+b.duration(1,a),d=Math.max(100,d),e.nowIndicatorIntervalID=setInterval(c,d)},d)))},updateNowIndicator:function(){this.isNowIndicatorRendered&&(this.unrenderNowIndicator(),this.renderNowIndicator(this.initialNowDate.clone().add(new Date-this.initialNowQueriedMs)))},stopNowIndicator:function(){this.isNowIndicatorRendered&&(this.nowIndicatorTimeoutID&&(clearTimeout(this.nowIndicatorTimeoutID),this.nowIndicatorTimeoutID=null),this.nowIndicatorIntervalID&&(clearTimeout(this.nowIndicatorIntervalID),this.nowIndicatorIntervalID=null),this.unrenderNowIndicator(),this.isNowIndicatorRendered=!1)},getNowIndicatorUnit:function(){},renderNowIndicator:function(a){},unrenderNowIndicator:function(){},updateSize:function(a){var b;a&&(b=this.queryScroll()),this.updateHeight(a),this.updateWidth(a),this.updateNowIndicator(),a&&this.setScroll(b)},updateWidth:function(a){},updateHeight:function(a){var b=this.calendar;this.setHeight(b.getSuggestedViewHeight(),b.isHeightAuto())},setHeight:function(a,b){},computeInitialScroll:function(a){return 0},queryScroll:function(){},setScroll:function(a){},forceScroll:function(a){var b=this;this.setScroll(a),setTimeout(function(){b.setScroll(a)},0)},displayEvents:function(a){var b=this.queryScroll();this.clearEvents(),this.renderEvents(a),this.isEventsRendered=!0,this.setScroll(b),this.triggerEventRender()},clearEvents:function(){var a;this.isEventsRendered&&(a=this.queryScroll(),this.triggerEventUnrender(),this.destroyEvents&&this.destroyEvents(),this.unrenderEvents(),this.setScroll(a),this.isEventsRendered=!1)},renderEvents:function(a){},unrenderEvents:function(){},triggerEventRender:function(){this.renderedEventSegEach(function(a){this.trigger("eventAfterRender",a.event,a.event,a.el)}),this.trigger("eventAfterAllRender")},triggerEventUnrender:function(){this.renderedEventSegEach(function(a){this.trigger("eventDestroy",a.event,a.event,a.el)})},resolveEventEl:function(b,c){var d=this.trigger("eventRender",b,b,c);return d===!1?c=null:d&&d!==!0&&(c=a(d)),c},showEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","")},a)},hideEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","hidden")},a)},renderedEventSegEach:function(a,b){var c,d=this.getEventSegs();for(c=0;c<d.length;c++)b&&d[c].event._id!==b._id||d[c].el&&a.call(this,d[c])},getEventSegs:function(){return[]},isEventDraggable:function(a){var b=a.source||{};return ba(a.startEditable,b.startEditable,this.opt("eventStartEditable"),a.editable,b.editable,this.opt("editable"))},reportEventDrop:function(a,b,c,d,e){var f=this.calendar,g=f.mutateEvent(a,b,c),h=function(){g.undo(),f.reportEventChange()};this.triggerEventDrop(a,g.dateDelta,h,d,e),f.reportEventChange()},triggerEventDrop:function(a,b,c,d,e){this.trigger("eventDrop",d[0],a,b,c,e,{})},reportExternalDrop:function(b,c,d,e,f){var g,h,i=b.eventProps;i&&(g=a.extend({},i,c),h=this.calendar.renderEvent(g,b.stick)[0]),this.triggerExternalDrop(h,c,d,e,f)},triggerExternalDrop:function(a,b,c,d,e){this.trigger("drop",c[0],b.start,d,e),a&&this.trigger("eventReceive",null,a)},renderDrag:function(a,b){},unrenderDrag:function(){},isEventResizableFromStart:function(a){return this.opt("eventResizableFromStart")&&this.isEventResizable(a)},isEventResizableFromEnd:function(a){return this.isEventResizable(a)},isEventResizable:function(a){var b=a.source||{};return ba(a.durationEditable,b.durationEditable,this.opt("eventDurationEditable"),a.editable,b.editable,this.opt("editable"))},reportEventResize:function(a,b,c,d,e){var f=this.calendar,g=f.mutateEvent(a,b,c),h=function(){g.undo(),f.reportEventChange()};this.triggerEventResize(a,g.durationDelta,h,d,e),f.reportEventChange()},triggerEventResize:function(a,b,c,d,e){this.trigger("eventResize",d[0],a,b,c,e,{})},select:function(a,b){this.unselect(b),this.renderSelection(a),this.reportSelection(a,b)},renderSelection:function(a){},reportSelection:function(a,b){this.isSelected=!0,this.triggerSelect(a,b)},triggerSelect:function(a,b){this.trigger("select",null,this.calendar.applyTimezone(a.start),this.calendar.applyTimezone(a.end),b)},unselect:function(a){this.isSelected&&(this.isSelected=!1,this.destroySelection&&this.destroySelection(),this.unrenderSelection(),this.trigger("unselect",null,a))},unrenderSelection:function(){},selectEvent:function(a){this.selectedEvent&&this.selectedEvent===a||(this.unselectEvent(),this.renderedEventSegEach(function(a){a.el.addClass("fc-selected")},a),this.selectedEvent=a)},unselectEvent:function(){this.selectedEvent&&(this.renderedEventSegEach(function(a){a.el.removeClass("fc-selected")},this.selectedEvent),this.selectedEvent=null)},isEventSelected:function(a){return this.selectedEvent&&this.selectedEvent._id===a._id},handleDocumentMousedown:function(a){ -u(a)&&this.processUnselect(a)},processUnselect:function(a){this.processRangeUnselect(a),this.processEventUnselect(a)},processRangeUnselect:function(b){var c;this.isSelected&&this.opt("unselectAuto")&&(c=this.opt("unselectCancel"),c&&a(b.target).closest(c).length||this.unselect(b))},processEventUnselect:function(b){this.selectedEvent&&(a(b.target).closest(".fc-selected").length||this.unselectEvent())},triggerDayClick:function(a,b,c){this.trigger("dayClick",b,this.calendar.applyTimezone(a.start),c)},initHiddenDays:function(){var b,c=this.opt("hiddenDays")||[],d=[],e=0;for(this.opt("weekends")===!1&&c.push(0,6),b=0;7>b;b++)(d[b]=-1!==a.inArray(b,c))||e++;if(!e)throw"invalid hiddenDays";this.isHiddenDayHash=d},isHiddenDay:function(a){return b.isMoment(a)&&(a=a.day()),this.isHiddenDayHash[a]},skipHiddenDays:function(a,b,c){var d=a.clone();for(b=b||1;this.isHiddenDayHash[(d.day()+(c?b:0)+7)%7];)d.add(b,"days");return d},computeDayRange:function(a){var b,c=a.start.clone().stripTime(),d=a.end,e=null;return d&&(e=d.clone().stripTime(),b=+d.time(),b&&b>=this.nextDayThreshold&&e.add(1,"days")),(!d||c>=e)&&(e=c.clone().add(1,"days")),{start:c,end:e}},isMultiDayEvent:function(a){var b=this.computeDayRange(a);return b.end.diff(b.start,"days")>1}}),xb=Va.Scroller=xa.extend({el:null,scrollEl:null,overflowX:null,overflowY:null,constructor:function(a){a=a||{},this.overflowX=a.overflowX||a.overflow||"auto",this.overflowY=a.overflowY||a.overflow||"auto"},render:function(){this.el=this.renderEl(),this.applyOverflow()},renderEl:function(){return this.scrollEl=a('<div class="fc-scroller"></div>')},clear:function(){this.setHeight("auto"),this.applyOverflow()},destroy:function(){this.el.remove()},applyOverflow:function(){this.scrollEl.css({"overflow-x":this.overflowX,"overflow-y":this.overflowY})},lockOverflow:function(a){var b=this.overflowX,c=this.overflowY;a=a||this.getScrollbarWidths(),"auto"===b&&(b=a.top||a.bottom||this.scrollEl[0].scrollWidth-1>this.scrollEl[0].clientWidth?"scroll":"hidden"),"auto"===c&&(c=a.left||a.right||this.scrollEl[0].scrollHeight-1>this.scrollEl[0].clientHeight?"scroll":"hidden"),this.scrollEl.css({"overflow-x":b,"overflow-y":c})},setHeight:function(a){this.scrollEl.height(a)},getScrollTop:function(){return this.scrollEl.scrollTop()},setScrollTop:function(a){this.scrollEl.scrollTop(a)},getClientWidth:function(){return this.scrollEl[0].clientWidth},getClientHeight:function(){return this.scrollEl[0].clientHeight},getScrollbarWidths:function(){return q(this.scrollEl)}}),yb=Va.Calendar=xa.extend({dirDefaults:null,langDefaults:null,overrides:null,options:null,viewSpecCache:null,view:null,header:null,loadingLevel:0,constructor:Pa,initialize:function(){},initOptions:function(a){var b,e,f,g;a=d(a),b=a.lang,e=zb[b],e||(b=yb.defaults.lang,e=zb[b]||{}),f=ba(a.isRTL,e.isRTL,yb.defaults.isRTL),g=f?yb.rtlDefaults:{},this.dirDefaults=g,this.langDefaults=e,this.overrides=a,this.options=c([yb.defaults,g,e,a]),Qa(this.options),this.viewSpecCache={}},getViewSpec:function(a){var b=this.viewSpecCache;return b[a]||(b[a]=this.buildViewSpec(a))},getUnitViewSpec:function(b){var c,d,e;if(-1!=a.inArray(b,$a))for(c=this.header.getViewsWithButtons(),a.each(Va.views,function(a){c.push(a)}),d=0;d<c.length;d++)if(e=this.getViewSpec(c[d]),e&&e.singleUnit==b)return e},buildViewSpec:function(a){for(var d,e,f,g,h=this.overrides.views||{},i=[],j=[],k=[],l=a;l;)d=Wa[l],e=h[l],l=null,"function"==typeof d&&(d={"class":d}),d&&(i.unshift(d),j.unshift(d.defaults||{}),f=f||d.duration,l=l||d.type),e&&(k.unshift(e),f=f||e.duration,l=l||e.type);return d=W(i),d.type=a,d["class"]?(f&&(f=b.duration(f),f.valueOf()&&(d.duration=f,g=O(f),1===f.as(g)&&(d.singleUnit=g,k.unshift(h[g]||{})))),d.defaults=c(j),d.overrides=c(k),this.buildViewSpecOptions(d),this.buildViewSpecButtonText(d,a),d):!1},buildViewSpecOptions:function(a){a.options=c([yb.defaults,a.defaults,this.dirDefaults,this.langDefaults,this.overrides,a.overrides]),Qa(a.options)},buildViewSpecButtonText:function(a,b){function c(c){var d=c.buttonText||{};return d[b]||(a.singleUnit?d[a.singleUnit]:null)}a.buttonTextOverride=c(this.overrides)||a.overrides.buttonText,a.buttonTextDefault=c(this.langDefaults)||c(this.dirDefaults)||a.defaults.buttonText||c(yb.defaults)||(a.duration?this.humanizeDuration(a.duration):null)||b},instantiateView:function(a){var b=this.getViewSpec(a);return new b["class"](this,a,b.options,b.duration)},isValidViewType:function(a){return Boolean(this.getViewSpec(a))},pushLoading:function(){this.loadingLevel++||this.trigger("loading",null,!0,this.view)},popLoading:function(){--this.loadingLevel||this.trigger("loading",null,!1,this.view)},buildSelectSpan:function(a,b){var c,d=this.moment(a).stripZone();return c=b?this.moment(b).stripZone():d.hasTime()?d.clone().add(this.defaultTimedEventDuration):d.clone().add(this.defaultAllDayEventDuration),{start:d,end:c}}});yb.mixin(kb),yb.defaults={titleRangeSeparator:" — ",monthYearFormat:"MMMM YYYY",defaultTimedEventDuration:"02:00:00",defaultAllDayEventDuration:{days:1},forceEventDuration:!1,nextDayThreshold:"09:00:00",defaultView:"month",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberTitle:"W",weekNumberCalculation:"local",scrollTime:"06:00:00",lazyFetching:!0,startParam:"start",endParam:"end",timezoneParam:"timezone",timezone:!1,isRTL:!1,buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day"},buttonIcons:{prev:"left-single-arrow",next:"right-single-arrow",prevYear:"left-double-arrow",nextYear:"right-double-arrow"},theme:!1,themeButtonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e",prevYear:"seek-prev",nextYear:"seek-next"},dragOpacity:.75,dragRevertDuration:500,dragScroll:!0,unselectAuto:!0,dropAccept:"*",eventOrder:"title",eventLimit:!1,eventLimitText:"more",eventLimitClick:"popover",dayPopoverFormat:"LL",handleWindowResize:!0,windowResizeDelay:200,longPressDelay:1e3},yb.englishDefaults={dayPopoverFormat:"dddd, MMMM D"},yb.rtlDefaults={header:{left:"next,prev today",center:"",right:"title"},buttonIcons:{prev:"right-single-arrow",next:"left-single-arrow",prevYear:"right-double-arrow",nextYear:"left-double-arrow"},themeButtonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w",nextYear:"seek-prev",prevYear:"seek-next"}};var zb=Va.langs={};Va.datepickerLang=function(b,c,d){var e=zb[b]||(zb[b]={});e.isRTL=d.isRTL,e.weekNumberTitle=d.weekHeader,a.each(Ab,function(a,b){e[a]=b(d)}),a.datepicker&&(a.datepicker.regional[c]=a.datepicker.regional[b]=d,a.datepicker.regional.en=a.datepicker.regional[""],a.datepicker.setDefaults(d))},Va.lang=function(b,d){var e,f;e=zb[b]||(zb[b]={}),d&&(e=zb[b]=c([e,d])),f=Ra(b),a.each(Bb,function(a,b){null==e[a]&&(e[a]=b(f,e))}),yb.defaults.lang=b};var Ab={buttonText:function(a){return{prev:da(a.prevText),next:da(a.nextText),today:da(a.currentText)}},monthYearFormat:function(a){return a.showMonthAfterYear?"YYYY["+a.yearSuffix+"] MMMM":"MMMM YYYY["+a.yearSuffix+"]"}},Bb={dayOfMonthFormat:function(a,b){var c=a.longDateFormat("l");return c=c.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g,""),b.isRTL?c+=" ddd":c="ddd "+c,c},mediumTimeFormat:function(a){return a.longDateFormat("LT").replace(/\s*a$/i,"a")},smallTimeFormat:function(a){return a.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"a")},extraSmallTimeFormat:function(a){return a.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"t")},hourFormat:function(a){return a.longDateFormat("LT").replace(":mm","").replace(/(\Wmm)$/,"").replace(/\s*a$/i,"a")},noMeridiemTimeFormat:function(a){return a.longDateFormat("LT").replace(/\s*a$/i,"")}},Cb={smallDayDateFormat:function(a){return a.isRTL?"D dd":"dd D"},weekFormat:function(a){return a.isRTL?"w[ "+a.weekNumberTitle+"]":"["+a.weekNumberTitle+" ]w"},smallWeekFormat:function(a){return a.isRTL?"w["+a.weekNumberTitle+"]":"["+a.weekNumberTitle+"]w"}};Va.lang("en",yb.englishDefaults),Va.sourceNormalizers=[],Va.sourceFetchers=[];var Db={dataType:"json",cache:!1},Eb=1;yb.prototype.normalizeEvent=function(a){},yb.prototype.getPeerEvents=function(a,b){var c,d,e=this.getEventCache(),f=[];for(c=0;c<e.length;c++)d=e[c],b&&b._id===d._id||f.push(d);return f};var Fb=Va.BasicView=wb.extend({scroller:null,dayGridClass:ub,dayGrid:null,dayNumbersVisible:!1,weekNumbersVisible:!1,weekNumberWidth:null,headContainerEl:null,headRowEl:null,initialize:function(){this.dayGrid=this.instantiateDayGrid(),this.scroller=new xb({overflowX:"hidden",overflowY:"auto"})},instantiateDayGrid:function(){var a=this.dayGridClass.extend(Gb);return new a(this)},setRange:function(a){wb.prototype.setRange.call(this,a),this.dayGrid.breakOnWeeks=/year|month|week/.test(this.intervalUnit),this.dayGrid.setRange(a)},computeRange:function(a){var b=wb.prototype.computeRange.call(this,a);return/year|month/.test(b.intervalUnit)&&(b.start.startOf("week"),b.start=this.skipHiddenDays(b.start),b.end.weekday()&&(b.end.add(1,"week").startOf("week"),b.end=this.skipHiddenDays(b.end,-1,!0))),b},renderDates:function(){this.dayNumbersVisible=this.dayGrid.rowCnt>1,this.weekNumbersVisible=this.opt("weekNumbers"),this.dayGrid.numbersVisible=this.dayNumbersVisible||this.weekNumbersVisible,this.el.addClass("fc-basic-view").html(this.renderSkeletonHtml()),this.renderHead(),this.scroller.render();var b=this.scroller.el.addClass("fc-day-grid-container"),c=a('<div class="fc-day-grid" />').appendTo(b);this.el.find(".fc-body > tr > td").append(b),this.dayGrid.setElement(c),this.dayGrid.renderDates(this.hasRigidRows())},renderHead:function(){this.headContainerEl=this.el.find(".fc-head-container").html(this.dayGrid.renderHeadHtml()),this.headRowEl=this.headContainerEl.find(".fc-row")},unrenderDates:function(){this.dayGrid.unrenderDates(),this.dayGrid.removeElement(),this.scroller.destroy()},renderBusinessHours:function(){this.dayGrid.renderBusinessHours()},renderSkeletonHtml:function(){return'<table><thead class="fc-head"><tr><td class="fc-head-container '+this.widgetHeaderClass+'"></td></tr></thead><tbody class="fc-body"><tr><td class="'+this.widgetContentClass+'"></td></tr></tbody></table>'},weekNumberStyleAttr:function(){return null!==this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},hasRigidRows:function(){var a=this.opt("eventLimit");return a&&"number"!=typeof a},updateWidth:function(){this.weekNumbersVisible&&(this.weekNumberWidth=k(this.el.find(".fc-week-number")))},setHeight:function(a,b){var c,d,g=this.opt("eventLimit");this.scroller.clear(),f(this.headRowEl),this.dayGrid.removeSegPopover(),g&&"number"==typeof g&&this.dayGrid.limitRows(g),c=this.computeScrollerHeight(a),this.setGridHeight(c,b),g&&"number"!=typeof g&&this.dayGrid.limitRows(g),b||(this.scroller.setHeight(c),d=this.scroller.getScrollbarWidths(),(d.left||d.right)&&(e(this.headRowEl,d),c=this.computeScrollerHeight(a),this.scroller.setHeight(c)),this.scroller.lockOverflow(d))},computeScrollerHeight:function(a){return a-l(this.el,this.scroller.el)},setGridHeight:function(a,b){b?j(this.dayGrid.rowEls):i(this.dayGrid.rowEls,a,!0)},queryScroll:function(){return this.scroller.getScrollTop()},setScroll:function(a){this.scroller.setScrollTop(a)},prepareHits:function(){this.dayGrid.prepareHits()},releaseHits:function(){this.dayGrid.releaseHits()},queryHit:function(a,b){return this.dayGrid.queryHit(a,b)},getHitSpan:function(a){return this.dayGrid.getHitSpan(a)},getHitEl:function(a){return this.dayGrid.getHitEl(a)},renderEvents:function(a){this.dayGrid.renderEvents(a),this.updateHeight()},getEventSegs:function(){return this.dayGrid.getEventSegs()},unrenderEvents:function(){this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return this.dayGrid.renderDrag(a,b)},unrenderDrag:function(){this.dayGrid.unrenderDrag()},renderSelection:function(a){this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.dayGrid.unrenderSelection()}}),Gb={renderHeadIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?'<th class="fc-week-number '+a.widgetHeaderClass+'" '+a.weekNumberStyleAttr()+"><span>"+ca(a.opt("weekNumberTitle"))+"</span></th>":""},renderNumberIntroHtml:function(a){var b=this.view;return b.weekNumbersVisible?'<td class="fc-week-number" '+b.weekNumberStyleAttr()+"><span>"+this.getCellDate(a,0).format("w")+"</span></td>":""},renderBgIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?'<td class="fc-week-number '+a.widgetContentClass+'" '+a.weekNumberStyleAttr()+"></td>":""},renderIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?'<td class="fc-week-number" '+a.weekNumberStyleAttr()+"></td>":""}},Hb=Va.MonthView=Fb.extend({computeRange:function(a){var b,c=Fb.prototype.computeRange.call(this,a);return this.isFixedWeeks()&&(b=Math.ceil(c.end.diff(c.start,"weeks",!0)),c.end.add(6-b,"weeks")),c},setGridHeight:function(a,b){b=b||"variable"===this.opt("weekMode"),b&&(a*=this.rowCnt/6),i(this.dayGrid.rowEls,a,!b)},isFixedWeeks:function(){var a=this.opt("weekMode");return a?"fixed"===a:this.opt("fixedWeekCount")}});Wa.basic={"class":Fb},Wa.basicDay={type:"basic",duration:{days:1}},Wa.basicWeek={type:"basic",duration:{weeks:1}},Wa.month={"class":Hb,duration:{months:1},defaults:{fixedWeekCount:!0}};var Ib=Va.AgendaView=wb.extend({scroller:null,timeGridClass:vb,timeGrid:null,dayGridClass:ub,dayGrid:null,axisWidth:null,headContainerEl:null,noScrollRowEls:null,bottomRuleEl:null,initialize:function(){this.timeGrid=this.instantiateTimeGrid(),this.opt("allDaySlot")&&(this.dayGrid=this.instantiateDayGrid()),this.scroller=new xb({overflowX:"hidden",overflowY:"auto"})},instantiateTimeGrid:function(){var a=this.timeGridClass.extend(Jb);return new a(this)},instantiateDayGrid:function(){var a=this.dayGridClass.extend(Kb);return new a(this)},setRange:function(a){wb.prototype.setRange.call(this,a),this.timeGrid.setRange(a),this.dayGrid&&this.dayGrid.setRange(a)},renderDates:function(){this.el.addClass("fc-agenda-view").html(this.renderSkeletonHtml()),this.renderHead(),this.scroller.render();var b=this.scroller.el.addClass("fc-time-grid-container"),c=a('<div class="fc-time-grid" />').appendTo(b);this.el.find(".fc-body > tr > td").append(b),this.timeGrid.setElement(c),this.timeGrid.renderDates(),this.bottomRuleEl=a('<hr class="fc-divider '+this.widgetHeaderClass+'"/>').appendTo(this.timeGrid.el),this.dayGrid&&(this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.renderDates(),this.dayGrid.bottomCoordPadding=this.dayGrid.el.next("hr").outerHeight()),this.noScrollRowEls=this.el.find(".fc-row:not(.fc-scroller *)")},renderHead:function(){this.headContainerEl=this.el.find(".fc-head-container").html(this.timeGrid.renderHeadHtml())},unrenderDates:function(){this.timeGrid.unrenderDates(),this.timeGrid.removeElement(),this.dayGrid&&(this.dayGrid.unrenderDates(),this.dayGrid.removeElement()),this.scroller.destroy()},renderSkeletonHtml:function(){return'<table><thead class="fc-head"><tr><td class="fc-head-container '+this.widgetHeaderClass+'"></td></tr></thead><tbody class="fc-body"><tr><td class="'+this.widgetContentClass+'">'+(this.dayGrid?'<div class="fc-day-grid"/><hr class="fc-divider '+this.widgetHeaderClass+'"/>':"")+"</td></tr></tbody></table>"},axisStyleAttr:function(){return null!==this.axisWidth?'style="width:'+this.axisWidth+'px"':""},renderBusinessHours:function(){this.timeGrid.renderBusinessHours(),this.dayGrid&&this.dayGrid.renderBusinessHours()},unrenderBusinessHours:function(){this.timeGrid.unrenderBusinessHours(),this.dayGrid&&this.dayGrid.unrenderBusinessHours()},getNowIndicatorUnit:function(){return this.timeGrid.getNowIndicatorUnit()},renderNowIndicator:function(a){this.timeGrid.renderNowIndicator(a)},unrenderNowIndicator:function(){this.timeGrid.unrenderNowIndicator()},updateSize:function(a){this.timeGrid.updateSize(a),wb.prototype.updateSize.call(this,a)},updateWidth:function(){this.axisWidth=k(this.el.find(".fc-axis"))},setHeight:function(a,b){var c,d,g;this.bottomRuleEl.hide(),this.scroller.clear(),f(this.noScrollRowEls),this.dayGrid&&(this.dayGrid.removeSegPopover(),c=this.opt("eventLimit"),c&&"number"!=typeof c&&(c=Lb),c&&this.dayGrid.limitRows(c)),b||(d=this.computeScrollerHeight(a),this.scroller.setHeight(d),g=this.scroller.getScrollbarWidths(),(g.left||g.right)&&(e(this.noScrollRowEls,g),d=this.computeScrollerHeight(a),this.scroller.setHeight(d)),this.scroller.lockOverflow(g),this.timeGrid.getTotalSlatHeight()<d&&this.bottomRuleEl.show())},computeScrollerHeight:function(a){return a-l(this.el,this.scroller.el)},computeInitialScroll:function(){var a=b.duration(this.opt("scrollTime")),c=this.timeGrid.computeTimeTop(a);return c=Math.ceil(c),c&&c++,c},queryScroll:function(){return this.scroller.getScrollTop()},setScroll:function(a){this.scroller.setScrollTop(a)},prepareHits:function(){this.timeGrid.prepareHits(),this.dayGrid&&this.dayGrid.prepareHits()},releaseHits:function(){this.timeGrid.releaseHits(),this.dayGrid&&this.dayGrid.releaseHits()},queryHit:function(a,b){var c=this.timeGrid.queryHit(a,b);return!c&&this.dayGrid&&(c=this.dayGrid.queryHit(a,b)),c},getHitSpan:function(a){return a.component.getHitSpan(a)},getHitEl:function(a){return a.component.getHitEl(a)},renderEvents:function(a){var b,c,d=[],e=[],f=[];for(c=0;c<a.length;c++)a[c].allDay?d.push(a[c]):e.push(a[c]);b=this.timeGrid.renderEvents(e),this.dayGrid&&(f=this.dayGrid.renderEvents(d)),this.updateHeight()},getEventSegs:function(){return this.timeGrid.getEventSegs().concat(this.dayGrid?this.dayGrid.getEventSegs():[])},unrenderEvents:function(){this.timeGrid.unrenderEvents(),this.dayGrid&&this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return a.start.hasTime()?this.timeGrid.renderDrag(a,b):this.dayGrid?this.dayGrid.renderDrag(a,b):void 0},unrenderDrag:function(){this.timeGrid.unrenderDrag(),this.dayGrid&&this.dayGrid.unrenderDrag()},renderSelection:function(a){a.start.hasTime()||a.end.hasTime()?this.timeGrid.renderSelection(a):this.dayGrid&&this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.timeGrid.unrenderSelection(),this.dayGrid&&this.dayGrid.unrenderSelection()}}),Jb={renderHeadIntroHtml:function(){var a,b=this.view;return b.opt("weekNumbers")?(a=this.start.format(b.opt("smallWeekFormat")),'<th class="fc-axis fc-week-number '+b.widgetHeaderClass+'" '+b.axisStyleAttr()+"><span>"+ca(a)+"</span></th>"):'<th class="fc-axis '+b.widgetHeaderClass+'" '+b.axisStyleAttr()+"></th>"},renderBgIntroHtml:function(){var a=this.view;return'<td class="fc-axis '+a.widgetContentClass+'" '+a.axisStyleAttr()+"></td>"},renderIntroHtml:function(){var a=this.view;return'<td class="fc-axis" '+a.axisStyleAttr()+"></td>"}},Kb={renderBgIntroHtml:function(){var a=this.view;return'<td class="fc-axis '+a.widgetContentClass+'" '+a.axisStyleAttr()+"><span>"+(a.opt("allDayHtml")||ca(a.opt("allDayText")))+"</span></td>"},renderIntroHtml:function(){var a=this.view;return'<td class="fc-axis" '+a.axisStyleAttr()+"></td>"}},Lb=5,Mb=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}];return Wa.agenda={"class":Ib,defaults:{allDaySlot:!0,allDayText:"all-day",slotDuration:"00:30:00",minTime:"00:00:00",maxTime:"24:00:00",slotEventOverlap:!0}},Wa.agendaDay={type:"agenda",duration:{days:1}},Wa.agendaWeek={type:"agenda",duration:{weeks:1}},Va}); \ No newline at end of file +!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("moment")):a(jQuery,moment)}(function(a,b){function c(a){return W(a,Ya)}function d(b){var c,d={views:b.views||{}};return a.each(b,function(b,e){"views"!=b&&(a.isPlainObject(e)&&!/(time|duration|interval)$/i.test(b)&&-1==a.inArray(b,Ya)?(c=null,a.each(e,function(a,e){/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(a)?(d.views[a]||(d.views[a]={}),d.views[a][b]=e):(c||(c={}),c[a]=e)}),c&&(d[b]=c)):d[b]=e)}),d}function e(a,b){b.left&&a.css({"border-left-width":1,"margin-left":b.left-1}),b.right&&a.css({"border-right-width":1,"margin-right":b.right-1})}function f(a){a.css({"margin-left":"","margin-right":"","border-left-width":"","border-right-width":""})}function g(){a("body").addClass("fc-not-allowed")}function h(){a("body").removeClass("fc-not-allowed")}function i(b,c,d){var e=Math.floor(c/b.length),f=Math.floor(c-e*(b.length-1)),g=[],h=[],i=[],k=0;j(b),b.each(function(c,d){var j=c===b.length-1?f:e,l=a(d).outerHeight(!0);j>l?(g.push(d),h.push(l),i.push(a(d).height())):k+=l}),d&&(c-=k,e=Math.floor(c/g.length),f=Math.floor(c-e*(g.length-1))),a(g).each(function(b,c){var d=b===g.length-1?f:e,j=h[b],k=i[b],l=d-(j-k);d>j&&a(c).height(l)})}function j(a){a.height("")}function k(b){var c=0;return b.find("> span").each(function(b,d){var e=a(d).outerWidth();e>c&&(c=e)}),c++,b.width(c),c}function l(a,b){var c,d=a.add(b);return d.css({position:"relative",left:-1}),c=a.outerHeight()-b.outerHeight(),d.css({position:"",left:""}),c}function m(b){var c=b.css("position"),d=b.parents().filter(function(){var b=a(this);return/(auto|scroll)/.test(b.css("overflow")+b.css("overflow-y")+b.css("overflow-x"))}).eq(0);return"fixed"!==c&&d.length?d:a(b[0].ownerDocument||document)}function n(a,b){var c=a.offset(),d=c.left-(b?b.left:0),e=c.top-(b?b.top:0);return{left:d,right:d+a.outerWidth(),top:e,bottom:e+a.outerHeight()}}function o(a,b){var c=a.offset(),d=q(a),e=c.left+t(a,"border-left-width")+d.left-(b?b.left:0),f=c.top+t(a,"border-top-width")+d.top-(b?b.top:0);return{left:e,right:e+a[0].clientWidth,top:f,bottom:f+a[0].clientHeight}}function p(a,b){var c=a.offset(),d=c.left+t(a,"border-left-width")+t(a,"padding-left")-(b?b.left:0),e=c.top+t(a,"border-top-width")+t(a,"padding-top")-(b?b.top:0);return{left:d,right:d+a.width(),top:e,bottom:e+a.height()}}function q(a){var b=a.innerWidth()-a[0].clientWidth,c={left:0,right:0,top:0,bottom:a.innerHeight()-a[0].clientHeight};return r()&&"rtl"==a.css("direction")?c.left=b:c.right=b,c}function r(){return null===Za&&(Za=s()),Za}function s(){var b=a("<div><div/></div>").css({position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}).appendTo("body"),c=b.children(),d=c.offset().left>b.offset().left;return b.remove(),d}function t(a,b){return parseFloat(a.css(b))||0}function u(a){return 1==a.which&&!a.ctrlKey}function v(a){if(void 0!==a.pageX)return a.pageX;var b=a.originalEvent.touches;return b?b[0].pageX:void 0}function w(a){if(void 0!==a.pageY)return a.pageY;var b=a.originalEvent.touches;return b?b[0].pageY:void 0}function x(a){return/^touch/.test(a.type)}function y(a){a.addClass("fc-unselectable").on("selectstart",z)}function z(a){a.preventDefault()}function A(a){return window.addEventListener?(window.addEventListener("scroll",a,!0),!0):!1}function B(a){return window.removeEventListener?(window.removeEventListener("scroll",a,!0),!0):!1}function C(a,b){var c={left:Math.max(a.left,b.left),right:Math.min(a.right,b.right),top:Math.max(a.top,b.top),bottom:Math.min(a.bottom,b.bottom)};return c.left<c.right&&c.top<c.bottom?c:!1}function D(a,b){return{left:Math.min(Math.max(a.left,b.left),b.right),top:Math.min(Math.max(a.top,b.top),b.bottom)}}function E(a){return{left:(a.left+a.right)/2,top:(a.top+a.bottom)/2}}function F(a,b){return{left:a.left-b.left,top:a.top-b.top}}function G(b){var c,d,e=[],f=[];for("string"==typeof b?f=b.split(/\s*,\s*/):"function"==typeof b?f=[b]:a.isArray(b)&&(f=b),c=0;c<f.length;c++)d=f[c],"string"==typeof d?e.push("-"==d.charAt(0)?{field:d.substring(1),order:-1}:{field:d,order:1}):"function"==typeof d&&e.push({func:d});return e}function H(a,b,c){var d,e;for(d=0;d<c.length;d++)if(e=I(a,b,c[d]))return e;return 0}function I(a,b,c){return c.func?c.func(a,b):J(a[c.field],b[c.field])*(c.order||1)}function J(b,c){return b||c?null==c?-1:null==b?1:"string"===a.type(b)||"string"===a.type(c)?String(b).localeCompare(String(c)):b-c:0}function K(a,b){var c,d,e,f,g=a.start,h=a.end,i=b.start,j=b.end;return h>i&&j>g?(g>=i?(c=g.clone(),e=!0):(c=i.clone(),e=!1),j>=h?(d=h.clone(),f=!0):(d=j.clone(),f=!1),{start:c,end:d,isStart:e,isEnd:f}):void 0}function L(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days"),ms:a.time()-c.time()})}function M(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days")})}function N(a,c,d){return b.duration(Math.round(a.diff(c,d,!0)),d)}function O(a,b){var c,d,e;for(c=0;c<_a.length&&(d=_a[c],e=P(d,a,b),!(e>=1&&ha(e)));c++);return d}function P(a,c,d){return null!=d?d.diff(c,a,!0):b.isDuration(c)?c.as(a):c.end.diff(c.start,a,!0)}function Q(a,b,c){var d;return T(c)?(b-a)/c:(d=c.asMonths(),Math.abs(d)>=1&&ha(d)?b.diff(a,"months",!0)/d:b.diff(a,"days",!0)/c.asDays())}function R(a,b){var c,d;return T(a)||T(b)?a/b:(c=a.asMonths(),d=b.asMonths(),Math.abs(c)>=1&&ha(c)&&Math.abs(d)>=1&&ha(d)?c/d:a.asDays()/b.asDays())}function S(a,c){var d;return T(a)?b.duration(a*c):(d=a.asMonths(),Math.abs(d)>=1&&ha(d)?b.duration({months:d*c}):b.duration({days:a.asDays()*c}))}function T(a){return Boolean(a.hours()||a.minutes()||a.seconds()||a.milliseconds())}function U(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function V(a){return/^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(a)}function W(a,b){var c,d,e,f,g,h,i={};if(b)for(c=0;c<b.length;c++){for(d=b[c],e=[],f=a.length-1;f>=0;f--)if(g=a[f][d],"object"==typeof g)e.unshift(g);else if(void 0!==g){i[d]=g;break}e.length&&(i[d]=W(e))}for(c=a.length-1;c>=0;c--){h=a[c];for(d in h)d in i||(i[d]=h[d])}return i}function X(a){var b=function(){};return b.prototype=a,new b}function Y(a,b){for(var c in a)$(a,c)&&(b[c]=a[c])}function Z(a,b){var c,d,e=["constructor","toString","valueOf"];for(c=0;c<e.length;c++)d=e[c],a[d]!==Object.prototype[d]&&(b[d]=a[d])}function $(a,b){return db.call(a,b)}function _(b){return/undefined|null|boolean|number|string/.test(a.type(b))}function aa(b,c,d){if(a.isFunction(b)&&(b=[b]),b){var e,f;for(e=0;e<b.length;e++)f=b[e].apply(c,d)||f;return f}}function ba(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]}function ca(a){return(a+"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"<br />")}function da(a){return a.replace(/&.*?;/g,"")}function ea(b){var c=[];return a.each(b,function(a,b){null!=b&&c.push(a+":"+b)}),c.join(";")}function fa(a){return a.charAt(0).toUpperCase()+a.slice(1)}function ga(a,b){return a-b}function ha(a){return a%1===0}function ia(a,b){var c=a[b];return function(){return c.apply(a,arguments)}}function ja(a,b,c){var d,e,f,g,h,i=function(){var j=+new Date-g;b>j?d=setTimeout(i,b-j):(d=null,c||(h=a.apply(f,e),f=e=null))};return function(){f=this,e=arguments,g=+new Date;var j=c&&!d;return d||(d=setTimeout(i,b)),j&&(h=a.apply(f,e),f=e=null),h}}function ka(b,c){return b&&b.then&&"resolved"!==b.state()?c?b.then(c):void 0:a.when(c())}function la(c,d,e){var f,g,h,i,j=c[0],k=1==c.length&&"string"==typeof j;return b.isMoment(j)?(i=b.apply(null,c),na(j,i)):U(j)||void 0===j?i=b.apply(null,c):(f=!1,g=!1,k?eb.test(j)?(j+="-01",c=[j],f=!0,g=!0):(h=fb.exec(j))&&(f=!h[5],g=!0):a.isArray(j)&&(g=!0),i=d||f?b.utc.apply(b,c):b.apply(null,c),f?(i._ambigTime=!0,i._ambigZone=!0):e&&(g?i._ambigZone=!0:k&&(i.utcOffset?i.utcOffset(j):i.zone(j)))),i._fullCalendar=!0,i}function ma(a,c){var d,e,f=!1,g=!1,h=a.length,i=[];for(d=0;h>d;d++)e=a[d],b.isMoment(e)||(e=Wa.moment.parseZone(e)),f=f||e._ambigTime,g=g||e._ambigZone,i.push(e);for(d=0;h>d;d++)e=i[d],c||!f||e._ambigTime?g&&!e._ambigZone&&(i[d]=e.clone().stripZone()):i[d]=e.clone().stripTime();return i}function na(a,b){a._ambigTime?b._ambigTime=!0:b._ambigTime&&(b._ambigTime=!1),a._ambigZone?b._ambigZone=!0:b._ambigZone&&(b._ambigZone=!1)}function oa(a,b){a.year(b[0]||0).month(b[1]||0).date(b[2]||0).hours(b[3]||0).minutes(b[4]||0).seconds(b[5]||0).milliseconds(b[6]||0)}function pa(a,b){return hb.format.call(a,b)}function qa(a,b){return ra(a,wa(b))}function ra(a,b){var c,d="";for(c=0;c<b.length;c++)d+=sa(a,b[c]);return d}function sa(a,b){var c,d;return"string"==typeof b?b:(c=b.token)?ib[c]?ib[c](a):pa(a,c):b.maybe&&(d=ra(a,b.maybe),d.match(/[1-9]/))?d:""}function ta(a,b,c,d,e){var f;return a=Wa.moment.parseZone(a),b=Wa.moment.parseZone(b),f=(a.localeData||a.lang).call(a),c=f.longDateFormat(c)||c,d=d||" - ",ua(a,b,wa(c),d,e)}function ua(a,b,c,d,e){var f,g,h,i,j=a.clone().stripZone(),k=b.clone().stripZone(),l="",m="",n="",o="",p="";for(g=0;g<c.length&&(f=va(a,b,j,k,c[g]),f!==!1);g++)l+=f;for(h=c.length-1;h>g&&(f=va(a,b,j,k,c[h]),f!==!1);h--)m=f+m;for(i=g;h>=i;i++)n+=sa(a,c[i]),o+=sa(b,c[i]);return(n||o)&&(p=e?o+d+n:n+d+o),l+p+m}function va(a,b,c,d,e){var f,g;return"string"==typeof e?e:(f=e.token)&&(g=jb[f.charAt(0)],g&&c.isSame(d,g))?pa(a,f):!1}function wa(a){return a in kb?kb[a]:kb[a]=xa(a)}function xa(a){for(var b,c=[],d=/\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;b=d.exec(a);)b[1]?c.push(b[1]):b[2]?c.push({maybe:xa(b[2])}):b[3]?c.push({token:b[3]}):b[5]&&c.push(b[5]);return c}function ya(){}function za(a,b){var c;return $(b,"constructor")&&(c=b.constructor),"function"!=typeof c&&(c=b.constructor=function(){a.apply(this,arguments)}),c.prototype=X(a.prototype),Y(b,c.prototype),Z(b,c.prototype),Y(a,c),c}function Aa(a,b){Y(b,a.prototype)}function Ba(a,b){return a||b?a&&b?a.component===b.component&&Ca(a,b)&&Ca(b,a):!1:!0}function Ca(a,b){for(var c in a)if(!/^(component|left|right|top|bottom)$/.test(c)&&a[c]!==b[c])return!1;return!0}function Da(a){var b=Fa(a);return"background"===b||"inverse-background"===b}function Ea(a){return"inverse-background"===Fa(a)}function Fa(a){return ba((a.source||{}).rendering,a.rendering)}function Ga(a){var b,c,d={};for(b=0;b<a.length;b++)c=a[b],(d[c._id]||(d[c._id]=[])).push(c);return d}function Ha(a,b){return a.start-b.start}function Ia(c){var d,e,f,g,h=Wa.dataAttrPrefix;return h&&(h+="-"),d=c.data(h+"event")||null,d&&(d="object"==typeof d?a.extend({},d):{},e=d.start,null==e&&(e=d.time),f=d.duration,g=d.stick,delete d.start,delete d.time,delete d.duration,delete d.stick),null==e&&(e=c.data(h+"start")),null==e&&(e=c.data(h+"time")),null==f&&(f=c.data(h+"duration")),null==g&&(g=c.data(h+"stick")),e=null!=e?b.duration(e):null,f=null!=f?b.duration(f):null,g=Boolean(g),{eventProps:d,startTime:e,duration:f,stick:g}}function Ja(a,b){var c,d;for(c=0;c<b.length;c++)if(d=b[c],d.leftCol<=a.rightCol&&d.rightCol>=a.leftCol)return!0;return!1}function Ka(a,b){return a.leftCol-b.leftCol}function La(a){var b,c,d,e=[];for(b=0;b<a.length;b++){for(c=a[b],d=0;d<e.length&&Oa(c,e[d]).length;d++);c.level=d,(e[d]||(e[d]=[])).push(c)}return e}function Ma(a){var b,c,d,e,f;for(b=0;b<a.length;b++)for(c=a[b],d=0;d<c.length;d++)for(e=c[d],e.forwardSegs=[],f=b+1;f<a.length;f++)Oa(e,a[f],e.forwardSegs)}function Na(a){var b,c,d=a.forwardSegs,e=0;if(void 0===a.forwardPressure){for(b=0;b<d.length;b++)c=d[b],Na(c),e=Math.max(e,1+c.forwardPressure);a.forwardPressure=e}}function Oa(a,b,c){c=c||[];for(var d=0;d<b.length;d++)Pa(a,b[d])&&c.push(b[d]);return c}function Pa(a,b){return a.bottom>b.top&&a.top<b.bottom}function Qa(c,d){function e(){T?h()&&(k(),i()):f()}function f(){U=O.theme?"ui":"fc",c.addClass("fc"),O.isRTL?c.addClass("fc-rtl"):c.addClass("fc-ltr"),O.theme?c.addClass("ui-widget"):c.addClass("fc-unthemed"),T=a("<div class='fc-view-container'/>").prependTo(c),R=N.header=new Ta(N,O),S=R.render(),S&&c.prepend(S),i(O.defaultView),O.handleWindowResize&&(Y=ja(m,O.windowResizeDelay),a(window).resize(Y))}function g(){V&&V.removeElement(),R.removeElement(),T.remove(),c.removeClass("fc fc-ltr fc-rtl fc-unthemed ui-widget"),Y&&a(window).unbind("resize",Y)}function h(){return c.is(":visible")}function i(b){da++,V&&b&&V.type!==b&&(R.deactivateButton(V.type),H(),V.removeElement(),V=N.view=null),!V&&b&&(V=N.view=ca[b]||(ca[b]=N.instantiateView(b)),V.setElement(a("<div class='fc-view fc-"+b+"-view' />").appendTo(T)),R.activateButton(b)),V&&(Z=V.massageCurrentDate(Z),V.displaying&&Z.isWithin(V.intervalStart,V.intervalEnd)||h()&&(V.display(Z),I(),u(),v(),q())),I(),da--}function j(a){return h()?(a&&l(),da++,V.updateSize(!0),da--,!0):void 0}function k(){h()&&l()}function l(){W="number"==typeof O.contentHeight?O.contentHeight:"number"==typeof O.height?O.height-(S?S.outerHeight(!0):0):Math.round(T.width()/Math.max(O.aspectRatio,.5))}function m(a){!da&&a.target===window&&V.start&&j(!0)&&V.trigger("windowResize",ba)}function n(){r()}function o(a){aa(N.getEventSourcesByMatchArray(a))}function p(){h()&&(H(),V.displayEvents(ea),I())}function q(){!O.lazyFetching||$(V.start,V.end)?r():p()}function r(){_(V.start,V.end)}function s(a){ea=a,p()}function t(){p()}function u(){R.updateTitle(V.title)}function v(){var a=N.getNow();a.isWithin(V.intervalStart,V.intervalEnd)?R.disableButton("today"):R.enableButton("today")}function w(a,b){V.select(N.buildSelectSpan.apply(N,arguments))}function x(){V&&V.unselect()}function y(){Z=V.computePrevDate(Z),i()}function z(){Z=V.computeNextDate(Z),i()}function A(){Z.add(-1,"years"),i()}function B(){Z.add(1,"years"),i()}function C(){Z=N.getNow(),i()}function D(a){Z=N.moment(a).stripZone(),i()}function E(a){Z.add(b.duration(a)),i()}function F(a,b){var c;b=b||"day",c=N.getViewSpec(b)||N.getUnitViewSpec(b),Z=a.clone(),i(c?c.type:null)}function G(){return N.applyTimezone(Z)}function H(){T.css({width:"100%",height:T.height(),overflow:"hidden"})}function I(){T.css({width:"",height:"",overflow:""})}function J(){return N}function K(){return V}function L(a,b){return void 0===b?O[a]:void("height"!=a&&"contentHeight"!=a&&"aspectRatio"!=a||(O[a]=b,j(!0)))}function M(a,b){var c=Array.prototype.slice.call(arguments,2);return b=b||ba,this.triggerWith(a,b,c),O[a]?O[a].apply(b,c):void 0}var N=this;N.initOptions(d||{});var O=this.options;N.render=e,N.destroy=g,N.refetchEvents=n,N.refetchEventSources=o,N.reportEvents=s,N.reportEventChange=t,N.rerenderEvents=p,N.changeView=i,N.select=w,N.unselect=x,N.prev=y,N.next=z,N.prevYear=A,N.nextYear=B,N.today=C,N.gotoDate=D,N.incrementDate=E,N.zoomTo=F,N.getDate=G,N.getCalendar=J,N.getView=K,N.option=L,N.trigger=M;var P=X(Sa(O.lang));if(O.monthNames&&(P._months=O.monthNames),O.monthNamesShort&&(P._monthsShort=O.monthNamesShort),O.dayNames&&(P._weekdays=O.dayNames),O.dayNamesShort&&(P._weekdaysShort=O.dayNamesShort),null!=O.firstDay){var Q=X(P._week);Q.dow=O.firstDay,P._week=Q}P._fullCalendar_weekCalc=function(a){return"function"==typeof a?a:"local"===a?a:"iso"===a||"ISO"===a?"ISO":void 0}(O.weekNumberCalculation),N.defaultAllDayEventDuration=b.duration(O.defaultAllDayEventDuration),N.defaultTimedEventDuration=b.duration(O.defaultTimedEventDuration),N.moment=function(){var a;return"local"===O.timezone?(a=Wa.moment.apply(null,arguments),a.hasTime()&&a.local()):a="UTC"===O.timezone?Wa.moment.utc.apply(null,arguments):Wa.moment.parseZone.apply(null,arguments),"_locale"in a?a._locale=P:a._lang=P,a},N.getIsAmbigTimezone=function(){return"local"!==O.timezone&&"UTC"!==O.timezone},N.applyTimezone=function(a){if(!a.hasTime())return a.clone();var b,c=N.moment(a.toArray()),d=a.time()-c.time();return d&&(b=c.clone().add(d),a.time()-b.time()===0&&(c=b)),c},N.getNow=function(){var a=O.now;return"function"==typeof a&&(a=a()),N.moment(a).stripZone()},N.getEventEnd=function(a){return a.end?a.end.clone():N.getDefaultEventEnd(a.allDay,a.start)},N.getDefaultEventEnd=function(a,b){var c=b.clone();return a?c.stripTime().add(N.defaultAllDayEventDuration):c.add(N.defaultTimedEventDuration),N.getIsAmbigTimezone()&&c.stripZone(),c},N.humanizeDuration=function(a){return(a.locale||a.lang).call(a,O.lang).humanize()},Ua.call(N,O);var R,S,T,U,V,W,Y,Z,$=N.isFetchNeeded,_=N.fetchEvents,aa=N.fetchEventSources,ba=c[0],ca={},da=0,ea=[];Z=null!=O.defaultDate?N.moment(O.defaultDate).stripZone():N.getNow(),N.getSuggestedViewHeight=function(){return void 0===W&&k(),W},N.isHeightAuto=function(){return"auto"===O.contentHeight||"auto"===O.height},N.freezeContentHeight=H,N.unfreezeContentHeight=I,N.initialize()}function Ra(b){a.each(Db,function(a,c){null==b[a]&&(b[a]=c(b))})}function Sa(a){var c=b.localeData||b.langData;return c.call(b,a)||c.call(b,"en")}function Ta(b,c){function d(){var b=c.header;return n=c.theme?"ui":"fc",b?o=a("<div class='fc-toolbar'/>").append(f("left")).append(f("right")).append(f("center")).append('<div class="fc-clear"/>'):void 0}function e(){o.remove(),o=a()}function f(d){var e=a('<div class="fc-'+d+'"/>'),f=c.header[d];return f&&a.each(f.split(" "),function(d){var f,g=a(),h=!0;a.each(this.split(","),function(d,e){var f,i,j,k,l,m,o,q,r,s;"title"==e?(g=g.add(a("<h2> </h2>")),h=!1):((f=(b.options.customButtons||{})[e])?(j=function(a){f.click&&f.click.call(s[0],a)},k="",l=f.text):(i=b.getViewSpec(e))?(j=function(){b.changeView(e)},p.push(e),k=i.buttonTextOverride,l=i.buttonTextDefault):b[e]&&(j=function(){b[e]()},k=(b.overrides.buttonText||{})[e],l=c.buttonText[e]),j&&(m=f?f.themeIcon:c.themeButtonIcons[e],o=f?f.icon:c.buttonIcons[e],q=k?ca(k):m&&c.theme?"<span class='ui-icon ui-icon-"+m+"'></span>":o&&!c.theme?"<span class='fc-icon fc-icon-"+o+"'></span>":ca(l),r=["fc-"+e+"-button",n+"-button",n+"-state-default"],s=a('<button type="button" class="'+r.join(" ")+'">'+q+"</button>").click(function(a){s.hasClass(n+"-state-disabled")||(j(a),(s.hasClass(n+"-state-active")||s.hasClass(n+"-state-disabled"))&&s.removeClass(n+"-state-hover"))}).mousedown(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-down")}).mouseup(function(){s.removeClass(n+"-state-down")}).hover(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-hover")},function(){s.removeClass(n+"-state-hover").removeClass(n+"-state-down")}),g=g.add(s)))}),h&&g.first().addClass(n+"-corner-left").end().last().addClass(n+"-corner-right").end(),g.length>1?(f=a("<div/>"),h&&f.addClass("fc-button-group"),f.append(g),e.append(f)):e.append(g)}),e}function g(a){o.find("h2").text(a)}function h(a){o.find(".fc-"+a+"-button").addClass(n+"-state-active")}function i(a){o.find(".fc-"+a+"-button").removeClass(n+"-state-active")}function j(a){o.find(".fc-"+a+"-button").prop("disabled",!0).addClass(n+"-state-disabled")}function k(a){o.find(".fc-"+a+"-button").prop("disabled",!1).removeClass(n+"-state-disabled")}function l(){return p}var m=this;m.render=d,m.removeElement=e,m.updateTitle=g,m.activateButton=h,m.deactivateButton=i,m.disableButton=j,m.enableButton=k,m.getViewsWithButtons=l;var n,o=a(),p=[]}function Ua(c){function d(a,b){return!W||W>a||b>X}function e(a,b){W=a,X=b,f($,"reset")}function f(a,b){var c,d;for("reset"===b?da=[]:"add"!==b&&(da=v(da,a)),c=0;c<a.length;c++)d=a[c],"pending"!==d._status&&ca++,d._fetchId=(d._fetchId||0)+1,d._status="pending";for(c=0;c<a.length;c++)d=a[c],g(d,d._fetchId)}function g(b,c){j(b,function(d){var e,f,g,h=a.isArray(b.events);if(c===b._fetchId&&"rejected"!==b._status){if(b._status="resolved",d)for(e=0;e<d.length;e++)f=d[e],g=h?f:C(f,b),g&&da.push.apply(da,G(g));i()}})}function h(a){var b="pending"===a._status;a._status="rejected",b&&i()}function i(){ca--,ca||Y(da)}function j(b,d){var e,f,g=Wa.sourceFetchers;for(e=0;e<g.length;e++){if(f=g[e].call(U,b,W.clone(),X.clone(),c.timezone,d),f===!0)return;if("object"==typeof f)return void j(f,d)}var h=b.events;if(h)a.isFunction(h)?(U.pushLoading(),h.call(U,W.clone(),X.clone(),c.timezone,function(a){d(a),U.popLoading()})):a.isArray(h)?d(h):d();else{var i=b.url;if(i){var k,l=b.success,m=b.error,n=b.complete;k=a.isFunction(b.data)?b.data():b.data;var o=a.extend({},k||{}),p=ba(b.startParam,c.startParam),q=ba(b.endParam,c.endParam),r=ba(b.timezoneParam,c.timezoneParam);p&&(o[p]=W.format()),q&&(o[q]=X.format()),c.timezone&&"local"!=c.timezone&&(o[r]=c.timezone),U.pushLoading(),a.ajax(a.extend({},Eb,b,{data:o,success:function(b){b=b||[];var c=aa(l,this,arguments);a.isArray(c)&&(b=c),d(b)},error:function(){aa(m,this,arguments),d()},complete:function(){aa(n,this,arguments),U.popLoading()}}))}else d()}}function k(a){var b=l(a);b&&($.push(b),f([b],"add"))}function l(b){var c,d,e=Wa.sourceNormalizers;if(a.isFunction(b)||a.isArray(b)?c={events:b}:"string"==typeof b?c={url:b}:"object"==typeof b&&(c=a.extend({},b)),c){for(c.className?"string"==typeof c.className&&(c.className=c.className.split(/\s+/)):c.className=[],a.isArray(c.events)&&(c.origArray=c.events,c.events=a.map(c.events,function(a){return C(a,c)})),d=0;d<e.length;d++)e[d].call(U,c);return c}}function m(a){o(s(a))}function n(a){null==a?o($,!0):o(r(a))}function o(b,c){var d;for(d=0;d<b.length;d++)h(b[d]);c?($=[],da=[]):($=a.grep($,function(a){for(d=0;d<b.length;d++)if(a===b[d])return!1;return!0}),da=v(da,b)),Y(da)}function p(){return $.slice(1)}function q(b){return a.grep($,function(a){return a.id&&a.id===b})[0]}function r(b){b?a.isArray(b)||(b=[b]):b=[];var c,d=[];for(c=0;c<b.length;c++)d.push.apply(d,s(b[c]));return d}function s(b){var c,d;for(c=0;c<$.length;c++)if(d=$[c],d===b)return[d];return d=q(b),d?[d]:a.grep($,function(a){return t(b,a)})}function t(a,b){return a&&b&&u(a)==u(b)}function u(a){return("object"==typeof a?a.origArray||a.googleCalendarId||a.url||a.events:null)||a}function v(b,c){return a.grep(b,function(a){for(var b=0;b<c.length;b++)if(a.source===c[b])return!1;return!0})}function w(a){a.start=U.moment(a.start),a.end?a.end=U.moment(a.end):a.end=null,H(a,x(a)),Y(da)}function x(b){var c={};return a.each(b,function(a,b){y(a)&&void 0!==b&&_(b)&&(c[a]=b)}),c}function y(a){return!/^_|^(id|allDay|start|end)$/.test(a)}function z(a,b){var c,d,e,f=C(a);if(f){for(c=G(f),d=0;d<c.length;d++)e=c[d],e.source||(b&&(Z.events.push(e),e.source=Z),da.push(e));return Y(da),c}return[]}function A(b){var c,d;for(null==b?b=function(){return!0}:a.isFunction(b)||(c=b+"",b=function(a){return a._id==c}),da=a.grep(da,b,!0),d=0;d<$.length;d++)a.isArray($[d].events)&&($[d].events=a.grep($[d].events,b,!0));Y(da)}function B(b){return a.isFunction(b)?a.grep(da,b):null!=b?(b+="",a.grep(da,function(a){return a._id==b})):da}function C(d,e){var f,g,h,i={};if(c.eventDataTransform&&(d=c.eventDataTransform(d)),e&&e.eventDataTransform&&(d=e.eventDataTransform(d)),a.extend(i,d),e&&(i.source=e),i._id=d._id||(void 0===d.id?"_fc"+Fb++:d.id+""),d.className?"string"==typeof d.className?i.className=d.className.split(/\s+/):i.className=d.className:i.className=[],f=d.start||d.date,g=d.end,V(f)&&(f=b.duration(f)),V(g)&&(g=b.duration(g)),d.dow||b.isDuration(f)||b.isDuration(g))i.start=f?b.duration(f):null,i.end=g?b.duration(g):null,i._recurring=!0;else{if(f&&(f=U.moment(f),!f.isValid()))return!1;g&&(g=U.moment(g),g.isValid()||(g=null)),h=d.allDay,void 0===h&&(h=ba(e?e.allDayDefault:void 0,c.allDayDefault)),D(f,g,h,i)}return U.normalizeEvent(i),i}function D(a,b,c,d){d.start=a,d.end=b,d.allDay=c,E(d),Va(d)}function E(a){F(a),a.end&&!a.end.isAfter(a.start)&&(a.end=null),a.end||(c.forceEventDuration?a.end=U.getDefaultEventEnd(a.allDay,a.start):a.end=null)}function F(a){null==a.allDay&&(a.allDay=!(a.start.hasTime()||a.end&&a.end.hasTime())),a.allDay?(a.start.stripTime(),a.end&&a.end.stripTime()):(a.start.hasTime()||(a.start=U.applyTimezone(a.start.time(0))),a.end&&!a.end.hasTime()&&(a.end=U.applyTimezone(a.end.time(0))))}function G(b,c,d){var e,f,g,h,i,j,k,l,m,n=[];if(c=c||W,d=d||X,b)if(b._recurring){if(f=b.dow)for(e={},g=0;g<f.length;g++)e[f[g]]=!0;for(h=c.clone().stripTime();h.isBefore(d);)e&&!e[h.day()]||(i=b.start,j=b.end,k=h.clone(),l=null,i&&(k=k.time(i)),j&&(l=h.clone().time(j)),m=a.extend({},b),D(k,l,!i&&!j,m),n.push(m)),h.add(1,"days")}else n.push(b);return n}function H(b,c,d){function e(a,b){return d?N(a,b,d):c.allDay?M(a,b):L(a,b)}var f,g,h,i,j,k,l={};return c=c||{},c.start||(c.start=b.start.clone()),void 0===c.end&&(c.end=b.end?b.end.clone():null),null==c.allDay&&(c.allDay=b.allDay),E(c),f={start:b._start.clone(),end:b._end?b._end.clone():U.getDefaultEventEnd(b._allDay,b._start),allDay:c.allDay},E(f),g=null!==b._end&&null===c.end,h=e(c.start,f.start),c.end?(i=e(c.end,f.end),j=i.subtract(h)):j=null,a.each(c,function(a,b){y(a)&&void 0!==b&&(l[a]=b)}),k=I(B(b._id),g,c.allDay,h,j,l),{dateDelta:h,durationDelta:j,undo:k}}function I(b,c,d,e,f,g){var h=U.getIsAmbigTimezone(),i=[];return e&&!e.valueOf()&&(e=null),f&&!f.valueOf()&&(f=null),a.each(b,function(b,j){var k,l;k={start:j.start.clone(),end:j.end?j.end.clone():null,allDay:j.allDay},a.each(g,function(a){k[a]=j[a]}),l={start:j._start,end:j._end,allDay:d},E(l),c?l.end=null:f&&!l.end&&(l.end=U.getDefaultEventEnd(l.allDay,l.start)),e&&(l.start.add(e),l.end&&l.end.add(e)),f&&l.end.add(f),h&&!l.allDay&&(e||f)&&(l.start.stripZone(),l.end&&l.end.stripZone()),a.extend(j,g,l),Va(j),i.push(function(){a.extend(j,k),Va(j)})}),function(){for(var a=0;a<i.length;a++)i[a]()}}function J(b){var d,e=c.businessHours,f={className:"fc-nonbusiness",start:"09:00",end:"17:00",dow:[1,2,3,4,5],rendering:"inverse-background"},g=U.getView();return e&&(d=a.extend({},f,"object"==typeof e?e:{})),d?(b&&(d.start=null,d.end=null),G(C(d),g.start,g.end)):[]}function K(a,b){var d=b.source||{},e=ba(b.constraint,d.constraint,c.eventConstraint),f=ba(b.overlap,d.overlap,c.eventOverlap);return Q(a,e,f,b)}function O(b,c,d){var e,f;return d&&(e=a.extend({},d,c),f=G(C(e))[0]),f?K(b,f):P(b)}function P(a){return Q(a,c.selectConstraint,c.selectOverlap)}function Q(a,b,c,d){var e,f,g,h,i,j;if(null!=b){for(e=R(b),f=!1,h=0;h<e.length;h++)if(S(e[h],a)){f=!0;break}if(!f)return!1}for(g=U.getPeerEvents(a,d),h=0;h<g.length;h++)if(i=g[h],T(i,a)){if(c===!1)return!1;if("function"==typeof c&&!c(i,d))return!1;if(d){if(j=ba(i.overlap,(i.source||{}).overlap),j===!1)return!1;if("function"==typeof j&&!j(d,i))return!1}}return!0}function R(a){return"businessHours"===a?J():"object"==typeof a?G(C(a)):B(a)}function S(a,b){var c=a.start.clone().stripZone(),d=U.getEventEnd(a).stripZone();return b.start>=c&&b.end<=d}function T(a,b){var c=a.start.clone().stripZone(),d=U.getEventEnd(a).stripZone();return b.start<d&&b.end>c}var U=this;U.isFetchNeeded=d,U.fetchEvents=e,U.fetchEventSources=f,U.getEventSources=p,U.getEventSourceById=q,U.getEventSourcesByMatchArray=r,U.getEventSourcesByMatch=s,U.addEventSource=k,U.removeEventSource=m,U.removeEventSources=n,U.updateEvent=w,U.renderEvent=z,U.removeEvents=A,U.clientEvents=B,U.mutateEvent=H,U.normalizeEventDates=E,U.normalizeEventTimes=F;var W,X,Y=U.reportEvents,Z={events:[]},$=[Z],ca=0,da=[];a.each((c.events?[c.events]:[]).concat(c.eventSources||[]),function(a,b){var c=l(b);c&&$.push(c)}),U.getBusinessHoursEvents=J,U.isEventSpanAllowed=K,U.isExternalSpanAllowed=O,U.isSelectionSpanAllowed=P,U.getEventCache=function(){return da}}function Va(a){a._allDay=a.allDay,a._start=a.start.clone(),a._end=a.end?a.end.clone():null}var Wa=a.fullCalendar={version:"2.8.0",internalApiVersion:4},Xa=Wa.views={};a.fn.fullCalendar=function(b){var c=Array.prototype.slice.call(arguments,1),d=this;return this.each(function(e,f){var g,h=a(f),i=h.data("fullCalendar");"string"==typeof b?i&&a.isFunction(i[b])&&(g=i[b].apply(i,c),e||(d=g),"destroy"===b&&h.removeData("fullCalendar")):i||(i=new zb(h,b),h.data("fullCalendar",i),i.render())}),d};var Ya=["header","buttonText","buttonIcons","themeButtonIcons"];Wa.intersectRanges=K,Wa.applyAll=aa,Wa.debounce=ja,Wa.isInt=ha,Wa.htmlEscape=ca,Wa.cssToStr=ea,Wa.proxy=ia,Wa.capitaliseFirstLetter=fa,Wa.getOuterRect=n,Wa.getClientRect=o,Wa.getContentRect=p,Wa.getScrollbarWidths=q;var Za=null;Wa.preventDefault=z,Wa.intersectRects=C,Wa.parseFieldSpecs=G,Wa.compareByFieldSpecs=H,Wa.compareByFieldSpec=I,Wa.flexibleCompare=J,Wa.computeIntervalUnit=O,Wa.divideRangeByDuration=Q,Wa.divideDurationByDuration=R,Wa.multiplyDuration=S,Wa.durationHasTime=T;var $a=["sun","mon","tue","wed","thu","fri","sat"],_a=["year","month","week","day","hour","minute","second","millisecond"];Wa.log=function(){var a=window.console;return a&&a.log?a.log.apply(a,arguments):void 0},Wa.warn=function(){var a=window.console;return a&&a.warn?a.warn.apply(a,arguments):Wa.log.apply(Wa,arguments)};var ab,bb,cb,db={}.hasOwnProperty,eb=/^\s*\d{4}-\d\d$/,fb=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/,gb=b.fn,hb=a.extend({},gb);Wa.moment=function(){return la(arguments)},Wa.moment.utc=function(){var a=la(arguments,!0);return a.hasTime()&&a.utc(),a},Wa.moment.parseZone=function(){return la(arguments,!0,!0)},gb.clone=function(){var a=hb.clone.apply(this,arguments);return na(this,a),this._fullCalendar&&(a._fullCalendar=!0),a},gb.week=gb.weeks=function(a){var b=(this._locale||this._lang)._fullCalendar_weekCalc;return null==a&&"function"==typeof b?b(this):"ISO"===b?hb.isoWeek.apply(this,arguments):hb.week.apply(this,arguments)},gb.time=function(a){if(!this._fullCalendar)return hb.time.apply(this,arguments);if(null==a)return b.duration({hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()});this._ambigTime=!1,b.isDuration(a)||b.isMoment(a)||(a=b.duration(a));var c=0;return b.isDuration(a)&&(c=24*Math.floor(a.asDays())),this.hours(c+a.hours()).minutes(a.minutes()).seconds(a.seconds()).milliseconds(a.milliseconds())},gb.stripTime=function(){var a;return this._ambigTime||(a=this.toArray(),this.utc(),bb(this,a.slice(0,3)),this._ambigTime=!0,this._ambigZone=!0),this},gb.hasTime=function(){return!this._ambigTime},gb.stripZone=function(){var a,b;return this._ambigZone||(a=this.toArray(),b=this._ambigTime,this.utc(),bb(this,a),this._ambigTime=b||!1,this._ambigZone=!0),this},gb.hasZone=function(){return!this._ambigZone},gb.local=function(){var a=this.toArray(),b=this._ambigZone;return hb.local.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,b&&cb(this,a),this},gb.utc=function(){return hb.utc.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,this},a.each(["zone","utcOffset"],function(a,b){hb[b]&&(gb[b]=function(a){return null!=a&&(this._ambigTime=!1,this._ambigZone=!1),hb[b].apply(this,arguments)})}),gb.format=function(){return this._fullCalendar&&arguments[0]?qa(this,arguments[0]):this._ambigTime?pa(this,"YYYY-MM-DD"):this._ambigZone?pa(this,"YYYY-MM-DD[T]HH:mm:ss"):hb.format.apply(this,arguments)},gb.toISOString=function(){return this._ambigTime?pa(this,"YYYY-MM-DD"):this._ambigZone?pa(this,"YYYY-MM-DD[T]HH:mm:ss"):hb.toISOString.apply(this,arguments)},gb.isWithin=function(a,b){var c=ma([this,a,b]);return c[0]>=c[1]&&c[0]<c[2]},gb.isSame=function(a,b){var c;return this._fullCalendar?b?(c=ma([this,a],!0),hb.isSame.call(c[0],c[1],b)):(a=Wa.moment.parseZone(a),hb.isSame.call(this,a)&&Boolean(this._ambigTime)===Boolean(a._ambigTime)&&Boolean(this._ambigZone)===Boolean(a._ambigZone)):hb.isSame.apply(this,arguments)},a.each(["isBefore","isAfter"],function(a,b){gb[b]=function(a,c){var d;return this._fullCalendar?(d=ma([this,a]),hb[b].call(d[0],d[1],c)):hb[b].apply(this,arguments)}}),ab="_d"in b()&&"updateOffset"in b,bb=ab?function(a,c){a._d.setTime(Date.UTC.apply(Date,c)),b.updateOffset(a,!1)}:oa,cb=ab?function(a,c){a._d.setTime(+new Date(c[0]||0,c[1]||0,c[2]||0,c[3]||0,c[4]||0,c[5]||0,c[6]||0)),b.updateOffset(a,!1)}:oa;var ib={t:function(a){return pa(a,"a").charAt(0)},T:function(a){return pa(a,"A").charAt(0)}};Wa.formatRange=ta;var jb={Y:"year",M:"month",D:"day",d:"day",A:"second",a:"second",T:"second",t:"second",H:"second",h:"second",m:"second",s:"second"},kb={};Wa.Class=ya,ya.extend=function(){var a,b,c=arguments.length;for(a=0;c>a;a++)b=arguments[a],c-1>a&&Aa(this,b);return za(this,b||{}); +},ya.mixin=function(a){Aa(this,a)};var lb=Wa.EmitterMixin={on:function(b,c){var d=function(a,b){return c.apply(b.context||this,b.args||[])};return c.guid||(c.guid=a.guid++),d.guid=c.guid,a(this).on(b,d),this},off:function(b,c){return a(this).off(b,c),this},trigger:function(b){var c=Array.prototype.slice.call(arguments,1);return a(this).triggerHandler(b,{args:c}),this},triggerWith:function(b,c,d){return a(this).triggerHandler(b,{context:c,args:d}),this}},mb=Wa.ListenerMixin=function(){var b=0,c={listenerId:null,listenTo:function(b,c,d){if("object"==typeof c)for(var e in c)c.hasOwnProperty(e)&&this.listenTo(b,e,c[e]);else"string"==typeof c&&b.on(c+"."+this.getListenerNamespace(),a.proxy(d,this))},stopListeningTo:function(a,b){a.off((b||"")+"."+this.getListenerNamespace())},getListenerNamespace:function(){return null==this.listenerId&&(this.listenerId=b++),"_listener"+this.listenerId}};return c}(),nb={isIgnoringMouse:!1,delayUnignoreMouse:null,initMouseIgnoring:function(a){this.delayUnignoreMouse=ja(ia(this,"unignoreMouse"),a||1e3)},tempIgnoreMouse:function(){this.isIgnoringMouse=!0,this.delayUnignoreMouse()},unignoreMouse:function(){this.isIgnoringMouse=!1}},ob=ya.extend(mb,{isHidden:!0,options:null,el:null,margin:10,constructor:function(a){this.options=a||{}},show:function(){this.isHidden&&(this.el||this.render(),this.el.show(),this.position(),this.isHidden=!1,this.trigger("show"))},hide:function(){this.isHidden||(this.el.hide(),this.isHidden=!0,this.trigger("hide"))},render:function(){var b=this,c=this.options;this.el=a('<div class="fc-popover"/>').addClass(c.className||"").css({top:0,left:0}).append(c.content).appendTo(c.parentEl),this.el.on("click",".fc-close",function(){b.hide()}),c.autoHide&&this.listenTo(a(document),"mousedown",this.documentMousedown)},documentMousedown:function(b){this.el&&!a(b.target).closest(this.el).length&&this.hide()},removeElement:function(){this.hide(),this.el&&(this.el.remove(),this.el=null),this.stopListeningTo(a(document),"mousedown")},position:function(){var b,c,d,e,f,g=this.options,h=this.el.offsetParent().offset(),i=this.el.outerWidth(),j=this.el.outerHeight(),k=a(window),l=m(this.el);e=g.top||0,f=void 0!==g.left?g.left:void 0!==g.right?g.right-i:0,l.is(window)||l.is(document)?(l=k,b=0,c=0):(d=l.offset(),b=d.top,c=d.left),b+=k.scrollTop(),c+=k.scrollLeft(),g.viewportConstrain!==!1&&(e=Math.min(e,b+l.outerHeight()-j-this.margin),e=Math.max(e,b+this.margin),f=Math.min(f,c+l.outerWidth()-i-this.margin),f=Math.max(f,c+this.margin)),this.el.css({top:e-h.top,left:f-h.left})},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1))}}),pb=Wa.CoordCache=ya.extend({els:null,forcedOffsetParentEl:null,origin:null,boundingRect:null,isHorizontal:!1,isVertical:!1,lefts:null,rights:null,tops:null,bottoms:null,constructor:function(b){this.els=a(b.els),this.isHorizontal=b.isHorizontal,this.isVertical=b.isVertical,this.forcedOffsetParentEl=b.offsetParent?a(b.offsetParent):null},build:function(){var a=this.forcedOffsetParentEl||this.els.eq(0).offsetParent();this.origin=a.offset(),this.boundingRect=this.queryBoundingRect(),this.isHorizontal&&this.buildElHorizontals(),this.isVertical&&this.buildElVerticals()},clear:function(){this.origin=null,this.boundingRect=null,this.lefts=null,this.rights=null,this.tops=null,this.bottoms=null},ensureBuilt:function(){this.origin||this.build()},queryBoundingRect:function(){var a=m(this.els.eq(0));return a.is(document)?void 0:o(a)},buildElHorizontals:function(){var b=[],c=[];this.els.each(function(d,e){var f=a(e),g=f.offset().left,h=f.outerWidth();b.push(g),c.push(g+h)}),this.lefts=b,this.rights=c},buildElVerticals:function(){var b=[],c=[];this.els.each(function(d,e){var f=a(e),g=f.offset().top,h=f.outerHeight();b.push(g),c.push(g+h)}),this.tops=b,this.bottoms=c},getHorizontalIndex:function(a){this.ensureBuilt();var b,c=this.boundingRect,d=this.lefts,e=this.rights,f=d.length;if(!c||a>=c.left&&a<c.right)for(b=0;f>b;b++)if(a>=d[b]&&a<e[b])return b},getVerticalIndex:function(a){this.ensureBuilt();var b,c=this.boundingRect,d=this.tops,e=this.bottoms,f=d.length;if(!c||a>=c.top&&a<c.bottom)for(b=0;f>b;b++)if(a>=d[b]&&a<e[b])return b},getLeftOffset:function(a){return this.ensureBuilt(),this.lefts[a]},getLeftPosition:function(a){return this.ensureBuilt(),this.lefts[a]-this.origin.left},getRightOffset:function(a){return this.ensureBuilt(),this.rights[a]},getRightPosition:function(a){return this.ensureBuilt(),this.rights[a]-this.origin.left},getWidth:function(a){return this.ensureBuilt(),this.rights[a]-this.lefts[a]},getTopOffset:function(a){return this.ensureBuilt(),this.tops[a]},getTopPosition:function(a){return this.ensureBuilt(),this.tops[a]-this.origin.top},getBottomOffset:function(a){return this.ensureBuilt(),this.bottoms[a]},getBottomPosition:function(a){return this.ensureBuilt(),this.bottoms[a]-this.origin.top},getHeight:function(a){return this.ensureBuilt(),this.bottoms[a]-this.tops[a]}}),qb=Wa.DragListener=ya.extend(mb,nb,{options:null,subjectEl:null,subjectHref:null,originX:null,originY:null,scrollEl:null,isInteracting:!1,isDistanceSurpassed:!1,isDelayEnded:!1,isDragging:!1,isTouch:!1,delay:null,delayTimeoutId:null,minDistance:null,handleTouchScrollProxy:null,constructor:function(a){this.options=a||{},this.handleTouchScrollProxy=ia(this,"handleTouchScroll"),this.initMouseIgnoring(500)},startInteraction:function(b,c){var d=x(b);if("mousedown"===b.type){if(this.isIgnoringMouse)return;if(!u(b))return;b.preventDefault()}this.isInteracting||(c=c||{},this.delay=ba(c.delay,this.options.delay,0),this.minDistance=ba(c.distance,this.options.distance,0),this.subjectEl=this.options.subjectEl,this.isInteracting=!0,this.isTouch=d,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,this.originX=v(b),this.originY=w(b),this.scrollEl=m(a(b.target)),this.bindHandlers(),this.initAutoScroll(),this.handleInteractionStart(b),this.startDelay(b),this.minDistance||this.handleDistanceSurpassed(b))},handleInteractionStart:function(a){this.trigger("interactionStart",a)},endInteraction:function(a,b){this.isInteracting&&(this.endDrag(a),this.delayTimeoutId&&(clearTimeout(this.delayTimeoutId),this.delayTimeoutId=null),this.destroyAutoScroll(),this.unbindHandlers(),this.isInteracting=!1,this.handleInteractionEnd(a,b),this.isTouch&&this.tempIgnoreMouse())},handleInteractionEnd:function(a,b){this.trigger("interactionEnd",a,b||!1)},bindHandlers:function(){var b=this,c=1;this.isTouch?(this.listenTo(a(document),{touchmove:this.handleTouchMove,touchend:this.endInteraction,touchcancel:this.endInteraction,touchstart:function(a){c?c--:b.endInteraction(a,!0)}}),!A(this.handleTouchScrollProxy)&&this.scrollEl&&this.listenTo(this.scrollEl,"scroll",this.handleTouchScroll)):this.listenTo(a(document),{mousemove:this.handleMouseMove,mouseup:this.endInteraction}),this.listenTo(a(document),{selectstart:z,contextmenu:z})},unbindHandlers:function(){this.stopListeningTo(a(document)),B(this.handleTouchScrollProxy),this.scrollEl&&this.stopListeningTo(this.scrollEl,"scroll")},startDrag:function(a,b){this.startInteraction(a,b),this.isDragging||(this.isDragging=!0,this.handleDragStart(a))},handleDragStart:function(a){this.trigger("dragStart",a),this.initHrefHack()},handleMove:function(a){var b,c=v(a)-this.originX,d=w(a)-this.originY,e=this.minDistance;this.isDistanceSurpassed||(b=c*c+d*d,b>=e*e&&this.handleDistanceSurpassed(a)),this.isDragging&&this.handleDrag(c,d,a)},handleDrag:function(a,b,c){this.trigger("drag",a,b,c),this.updateAutoScroll(c)},endDrag:function(a){this.isDragging&&(this.isDragging=!1,this.handleDragEnd(a))},handleDragEnd:function(a){this.trigger("dragEnd",a),this.destroyHrefHack()},startDelay:function(a){var b=this;this.delay?this.delayTimeoutId=setTimeout(function(){b.handleDelayEnd(a)},this.delay):this.handleDelayEnd(a)},handleDelayEnd:function(a){this.isDelayEnded=!0,this.isDistanceSurpassed&&this.startDrag(a)},handleDistanceSurpassed:function(a){this.isDistanceSurpassed=!0,this.isDelayEnded&&this.startDrag(a)},handleTouchMove:function(a){this.isDragging&&a.preventDefault(),this.handleMove(a)},handleMouseMove:function(a){this.handleMove(a)},handleTouchScroll:function(a){this.isDragging||this.endInteraction(a,!0)},initHrefHack:function(){var a=this.subjectEl;(this.subjectHref=a?a.attr("href"):null)&&a.removeAttr("href")},destroyHrefHack:function(){var a=this.subjectEl,b=this.subjectHref;setTimeout(function(){b&&a.attr("href",b)},0)},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1)),this["_"+a]&&this["_"+a].apply(this,Array.prototype.slice.call(arguments,1))}});qb.mixin({isAutoScroll:!1,scrollBounds:null,scrollTopVel:null,scrollLeftVel:null,scrollIntervalId:null,scrollSensitivity:30,scrollSpeed:200,scrollIntervalMs:50,initAutoScroll:function(){var a=this.scrollEl;this.isAutoScroll=this.options.scroll&&a&&!a.is(window)&&!a.is(document),this.isAutoScroll&&this.listenTo(a,"scroll",ja(this.handleDebouncedScroll,100))},destroyAutoScroll:function(){this.endAutoScroll(),this.isAutoScroll&&this.stopListeningTo(this.scrollEl,"scroll")},computeScrollBounds:function(){this.isAutoScroll&&(this.scrollBounds=n(this.scrollEl))},updateAutoScroll:function(a){var b,c,d,e,f=this.scrollSensitivity,g=this.scrollBounds,h=0,i=0;g&&(b=(f-(w(a)-g.top))/f,c=(f-(g.bottom-w(a)))/f,d=(f-(v(a)-g.left))/f,e=(f-(g.right-v(a)))/f,b>=0&&1>=b?h=b*this.scrollSpeed*-1:c>=0&&1>=c&&(h=c*this.scrollSpeed),d>=0&&1>=d?i=d*this.scrollSpeed*-1:e>=0&&1>=e&&(i=e*this.scrollSpeed)),this.setScrollVel(h,i)},setScrollVel:function(a,b){this.scrollTopVel=a,this.scrollLeftVel=b,this.constrainScrollVel(),!this.scrollTopVel&&!this.scrollLeftVel||this.scrollIntervalId||(this.scrollIntervalId=setInterval(ia(this,"scrollIntervalFunc"),this.scrollIntervalMs))},constrainScrollVel:function(){var a=this.scrollEl;this.scrollTopVel<0?a.scrollTop()<=0&&(this.scrollTopVel=0):this.scrollTopVel>0&&a.scrollTop()+a[0].clientHeight>=a[0].scrollHeight&&(this.scrollTopVel=0),this.scrollLeftVel<0?a.scrollLeft()<=0&&(this.scrollLeftVel=0):this.scrollLeftVel>0&&a.scrollLeft()+a[0].clientWidth>=a[0].scrollWidth&&(this.scrollLeftVel=0)},scrollIntervalFunc:function(){var a=this.scrollEl,b=this.scrollIntervalMs/1e3;this.scrollTopVel&&a.scrollTop(a.scrollTop()+this.scrollTopVel*b),this.scrollLeftVel&&a.scrollLeft(a.scrollLeft()+this.scrollLeftVel*b),this.constrainScrollVel(),this.scrollTopVel||this.scrollLeftVel||this.endAutoScroll()},endAutoScroll:function(){this.scrollIntervalId&&(clearInterval(this.scrollIntervalId),this.scrollIntervalId=null,this.handleScrollEnd())},handleDebouncedScroll:function(){this.scrollIntervalId||this.handleScrollEnd()},handleScrollEnd:function(){}});var rb=qb.extend({component:null,origHit:null,hit:null,coordAdjust:null,constructor:function(a,b){qb.call(this,b),this.component=a},handleInteractionStart:function(a){var b,c,d,e=this.subjectEl;this.computeCoords(),a?(c={left:v(a),top:w(a)},d=c,e&&(b=n(e),d=D(d,b)),this.origHit=this.queryHit(d.left,d.top),e&&this.options.subjectCenter&&(this.origHit&&(b=C(this.origHit,b)||b),d=E(b)),this.coordAdjust=F(d,c)):(this.origHit=null,this.coordAdjust=null),qb.prototype.handleInteractionStart.apply(this,arguments)},computeCoords:function(){this.component.prepareHits(),this.computeScrollBounds()},handleDragStart:function(a){var b;qb.prototype.handleDragStart.apply(this,arguments),b=this.queryHit(v(a),w(a)),b&&this.handleHitOver(b)},handleDrag:function(a,b,c){var d;qb.prototype.handleDrag.apply(this,arguments),d=this.queryHit(v(c),w(c)),Ba(d,this.hit)||(this.hit&&this.handleHitOut(),d&&this.handleHitOver(d))},handleDragEnd:function(){this.handleHitDone(),qb.prototype.handleDragEnd.apply(this,arguments)},handleHitOver:function(a){var b=Ba(a,this.origHit);this.hit=a,this.trigger("hitOver",this.hit,b,this.origHit)},handleHitOut:function(){this.hit&&(this.trigger("hitOut",this.hit),this.handleHitDone(),this.hit=null)},handleHitDone:function(){this.hit&&this.trigger("hitDone",this.hit)},handleInteractionEnd:function(){qb.prototype.handleInteractionEnd.apply(this,arguments),this.origHit=null,this.hit=null,this.component.releaseHits()},handleScrollEnd:function(){qb.prototype.handleScrollEnd.apply(this,arguments),this.computeCoords()},queryHit:function(a,b){return this.coordAdjust&&(a+=this.coordAdjust.left,b+=this.coordAdjust.top),this.component.queryHit(a,b)}}),sb=ya.extend(mb,{options:null,sourceEl:null,el:null,parentEl:null,top0:null,left0:null,y0:null,x0:null,topDelta:null,leftDelta:null,isFollowing:!1,isHidden:!1,isAnimating:!1,constructor:function(b,c){this.options=c=c||{},this.sourceEl=b,this.parentEl=c.parentEl?a(c.parentEl):b.parent()},start:function(b){this.isFollowing||(this.isFollowing=!0,this.y0=w(b),this.x0=v(b),this.topDelta=0,this.leftDelta=0,this.isHidden||this.updatePosition(),x(b)?this.listenTo(a(document),"touchmove",this.handleMove):this.listenTo(a(document),"mousemove",this.handleMove))},stop:function(b,c){function d(){this.isAnimating=!1,e.removeElement(),this.top0=this.left0=null,c&&c()}var e=this,f=this.options.revertDuration;this.isFollowing&&!this.isAnimating&&(this.isFollowing=!1,this.stopListeningTo(a(document)),b&&f&&!this.isHidden?(this.isAnimating=!0,this.el.animate({top:this.top0,left:this.left0},{duration:f,complete:d})):d())},getEl:function(){var a=this.el;return a||(this.sourceEl.width(),a=this.el=this.sourceEl.clone().addClass(this.options.additionalClass||"").css({position:"absolute",visibility:"",display:this.isHidden?"none":"",margin:0,right:"auto",bottom:"auto",width:this.sourceEl.width(),height:this.sourceEl.height(),opacity:this.options.opacity||"",zIndex:this.options.zIndex}),a.addClass("fc-unselectable"),a.appendTo(this.parentEl)),a},removeElement:function(){this.el&&(this.el.remove(),this.el=null)},updatePosition:function(){var a,b;this.getEl(),null===this.top0&&(this.sourceEl.width(),a=this.sourceEl.offset(),b=this.el.offsetParent().offset(),this.top0=a.top-b.top,this.left0=a.left-b.left),this.el.css({top:this.top0+this.topDelta,left:this.left0+this.leftDelta})},handleMove:function(a){this.topDelta=w(a)-this.y0,this.leftDelta=v(a)-this.x0,this.isHidden||this.updatePosition()},hide:function(){this.isHidden||(this.isHidden=!0,this.el&&this.el.hide())},show:function(){this.isHidden&&(this.isHidden=!1,this.updatePosition(),this.getEl().show())}}),tb=Wa.Grid=ya.extend(mb,nb,{view:null,isRTL:null,start:null,end:null,el:null,elsByFill:null,eventTimeFormat:null,displayEventTime:null,displayEventEnd:null,minResizeDuration:null,largeUnit:null,dayDragListener:null,segDragListener:null,segResizeListener:null,externalDragListener:null,constructor:function(a){this.view=a,this.isRTL=a.opt("isRTL"),this.elsByFill={},this.dayDragListener=this.buildDayDragListener(),this.initMouseIgnoring()},computeEventTimeFormat:function(){return this.view.opt("smallTimeFormat")},computeDisplayEventTime:function(){return!0},computeDisplayEventEnd:function(){return!0},setRange:function(a){this.start=a.start.clone(),this.end=a.end.clone(),this.rangeUpdated(),this.processRangeOptions()},rangeUpdated:function(){},processRangeOptions:function(){var a,b,c=this.view;this.eventTimeFormat=c.opt("eventTimeFormat")||c.opt("timeFormat")||this.computeEventTimeFormat(),a=c.opt("displayEventTime"),null==a&&(a=this.computeDisplayEventTime()),b=c.opt("displayEventEnd"),null==b&&(b=this.computeDisplayEventEnd()),this.displayEventTime=a,this.displayEventEnd=b},spanToSegs:function(a){},diffDates:function(a,b){return this.largeUnit?N(a,b,this.largeUnit):L(a,b)},prepareHits:function(){},releaseHits:function(){},queryHit:function(a,b){},getHitSpan:function(a){},getHitEl:function(a){},setElement:function(a){this.el=a,y(a),this.bindDayHandler("touchstart",this.dayTouchStart),this.bindDayHandler("mousedown",this.dayMousedown),this.bindSegHandlers(),this.bindGlobalHandlers()},bindDayHandler:function(b,c){var d=this;this.el.on(b,function(b){return a(b.target).is(".fc-event-container *, .fc-more")||a(b.target).closest(".fc-popover").length?void 0:c.call(d,b)})},removeElement:function(){this.unbindGlobalHandlers(),this.clearDragListeners(),this.el.remove()},renderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},bindGlobalHandlers:function(){this.listenTo(a(document),{dragstart:this.externalDragStart,sortstart:this.externalDragStart})},unbindGlobalHandlers:function(){this.stopListeningTo(a(document))},dayMousedown:function(a){this.isIgnoringMouse||this.dayDragListener.startInteraction(a,{})},dayTouchStart:function(a){var b=this.view;(b.isSelected||b.selectedEvent)&&this.tempIgnoreMouse(),this.dayDragListener.startInteraction(a,{delay:this.view.opt("longPressDelay")})},buildDayDragListener:function(){var a,b,c=this,d=this.view,e=d.opt("selectable"),f=new rb(this,{scroll:d.opt("dragScroll"),interactionStart:function(){a=f.origHit},dragStart:function(){d.unselect()},hitOver:function(d,f,h){h&&(f||(a=null),e&&(b=c.computeSelection(c.getHitSpan(h),c.getHitSpan(d)),b?c.renderSelection(b):b===!1&&g()))},hitOut:function(){a=null,b=null,c.unrenderSelection(),h()},interactionEnd:function(e,f){f||(a&&!c.isIgnoringMouse&&d.triggerDayClick(c.getHitSpan(a),c.getHitEl(a),e),b&&d.reportSelection(b,e),h())}});return f},clearDragListeners:function(){this.dayDragListener.endInteraction(),this.segDragListener&&this.segDragListener.endInteraction(),this.segResizeListener&&this.segResizeListener.endInteraction(),this.externalDragListener&&this.externalDragListener.endInteraction()},renderEventLocationHelper:function(a,b){var c=this.fabricateHelperEvent(a,b);return this.renderHelper(c,b)},fabricateHelperEvent:function(a,b){var c=b?X(b.event):{};return c.start=a.start.clone(),c.end=a.end?a.end.clone():null,c.allDay=null,this.view.calendar.normalizeEventDates(c),c.className=(c.className||[]).concat("fc-helper"),b||(c.editable=!1),c},renderHelper:function(a,b){},unrenderHelper:function(){},renderSelection:function(a){this.renderHighlight(a)},unrenderSelection:function(){this.unrenderHighlight()},computeSelection:function(a,b){var c=this.computeSelectionSpan(a,b);return c&&!this.view.calendar.isSelectionSpanAllowed(c)?!1:c},computeSelectionSpan:function(a,b){var c=[a.start,a.end,b.start,b.end];return c.sort(ga),{start:c[0].clone(),end:c[3].clone()}},renderHighlight:function(a){this.renderFill("highlight",this.spanToSegs(a))},unrenderHighlight:function(){this.unrenderFill("highlight")},highlightSegClasses:function(){return["fc-highlight"]},renderBusinessHours:function(){},unrenderBusinessHours:function(){},getNowIndicatorUnit:function(){},renderNowIndicator:function(a){},unrenderNowIndicator:function(){},renderFill:function(a,b){},unrenderFill:function(a){var b=this.elsByFill[a];b&&(b.remove(),delete this.elsByFill[a])},renderFillSegEls:function(b,c){var d,e=this,f=this[b+"SegEl"],g="",h=[];if(c.length){for(d=0;d<c.length;d++)g+=this.fillSegHtml(b,c[d]);a(g).each(function(b,d){var g=c[b],i=a(d);f&&(i=f.call(e,g,i)),i&&(i=a(i),i.is(e.fillSegTag)&&(g.el=i,h.push(g)))})}return h},fillSegTag:"div",fillSegHtml:function(a,b){var c=this[a+"SegClasses"],d=this[a+"SegCss"],e=c?c.call(this,b):[],f=ea(d?d.call(this,b):{});return"<"+this.fillSegTag+(e.length?' class="'+e.join(" ")+'"':"")+(f?' style="'+f+'"':"")+" />"},getDayClasses:function(a){var b=this.view,c=b.calendar.getNow(),d=["fc-"+$a[a.day()]];return 1==b.intervalDuration.as("months")&&a.month()!=b.intervalStart.month()&&d.push("fc-other-month"),a.isSame(c,"day")?d.push("fc-today",b.highlightStateClass):c>a?d.push("fc-past"):d.push("fc-future"),d}});tb.mixin({mousedOverSeg:null,isDraggingSeg:!1,isResizingSeg:!1,isDraggingExternal:!1,segs:null,renderEvents:function(a){var b,c=[],d=[];for(b=0;b<a.length;b++)(Da(a[b])?c:d).push(a[b]);this.segs=[].concat(this.renderBgEvents(c),this.renderFgEvents(d))},renderBgEvents:function(a){var b=this.eventsToSegs(a);return this.renderBgSegs(b)||b},renderFgEvents:function(a){var b=this.eventsToSegs(a);return this.renderFgSegs(b)||b},unrenderEvents:function(){this.handleSegMouseout(),this.clearDragListeners(),this.unrenderFgSegs(),this.unrenderBgSegs(),this.segs=null},getEventSegs:function(){return this.segs||[]},renderFgSegs:function(a){},unrenderFgSegs:function(){},renderFgSegEls:function(b,c){var d,e=this.view,f="",g=[];if(b.length){for(d=0;d<b.length;d++)f+=this.fgSegHtml(b[d],c);a(f).each(function(c,d){var f=b[c],h=e.resolveEventEl(f.event,a(d));h&&(h.data("fc-seg",f),f.el=h,g.push(f))})}return g},fgSegHtml:function(a,b){},renderBgSegs:function(a){return this.renderFill("bgEvent",a)},unrenderBgSegs:function(){this.unrenderFill("bgEvent")},bgEventSegEl:function(a,b){return this.view.resolveEventEl(a.event,b)},bgEventSegClasses:function(a){var b=a.event,c=b.source||{};return["fc-bgevent"].concat(b.className,c.className||[])},bgEventSegCss:function(a){return{"background-color":this.getSegSkinCss(a)["background-color"]}},businessHoursSegClasses:function(a){return["fc-nonbusiness","fc-bgevent"]},bindSegHandlers:function(){this.bindSegHandler("touchstart",this.handleSegTouchStart),this.bindSegHandler("touchend",this.handleSegTouchEnd),this.bindSegHandler("mouseenter",this.handleSegMouseover),this.bindSegHandler("mouseleave",this.handleSegMouseout),this.bindSegHandler("mousedown",this.handleSegMousedown),this.bindSegHandler("click",this.handleSegClick)},bindSegHandler:function(b,c){var d=this;this.el.on(b,".fc-event-container > *",function(b){var e=a(this).data("fc-seg");return!e||d.isDraggingSeg||d.isResizingSeg?void 0:c.call(d,e,b)})},handleSegClick:function(a,b){return this.view.trigger("eventClick",a.el[0],a.event,b)},handleSegMouseover:function(a,b){this.isIgnoringMouse||this.mousedOverSeg||(this.mousedOverSeg=a,a.el.addClass("fc-allow-mouse-resize"),this.view.trigger("eventMouseover",a.el[0],a.event,b))},handleSegMouseout:function(a,b){b=b||{},this.mousedOverSeg&&(a=a||this.mousedOverSeg,this.mousedOverSeg=null,a.el.removeClass("fc-allow-mouse-resize"),this.view.trigger("eventMouseout",a.el[0],a.event,b))},handleSegMousedown:function(a,b){var c=this.startSegResize(a,b,{distance:5});!c&&this.view.isEventDraggable(a.event)&&this.buildSegDragListener(a).startInteraction(b,{distance:5})},handleSegTouchStart:function(a,b){var c,d=this.view,e=a.event,f=d.isEventSelected(e),g=d.isEventDraggable(e),h=d.isEventResizable(e),i=!1;f&&h&&(i=this.startSegResize(a,b)),i||!g&&!h||(c=g?this.buildSegDragListener(a):this.buildSegSelectListener(a),c.startInteraction(b,{delay:f?0:this.view.opt("longPressDelay")})),this.tempIgnoreMouse()},handleSegTouchEnd:function(a,b){this.tempIgnoreMouse()},startSegResize:function(b,c,d){return a(c.target).is(".fc-resizer")?(this.buildSegResizeListener(b,a(c.target).is(".fc-start-resizer")).startInteraction(c,d),!0):!1},buildSegDragListener:function(a){var b,c,d,e=this,f=this.view,i=f.calendar,j=a.el,k=a.event;if(this.segDragListener)return this.segDragListener;var l=this.segDragListener=new rb(f,{scroll:f.opt("dragScroll"),subjectEl:j,subjectCenter:!0,interactionStart:function(d){b=!1,c=new sb(a.el,{additionalClass:"fc-dragging",parentEl:f.el,opacity:l.isTouch?null:f.opt("dragOpacity"),revertDuration:f.opt("dragRevertDuration"),zIndex:2}),c.hide(),c.start(d)},dragStart:function(c){l.isTouch&&!f.isEventSelected(k)&&f.selectEvent(k),b=!0,e.handleSegMouseout(a,c),e.segDragStart(a,c),f.hideEvent(k)},hitOver:function(b,h,j){var m;a.hit&&(j=a.hit),d=e.computeEventDrop(j.component.getHitSpan(j),b.component.getHitSpan(b),k),d&&!i.isEventSpanAllowed(e.eventToSpan(d),k)&&(g(),d=null),d&&(m=f.renderDrag(d,a))?(m.addClass("fc-dragging"),l.isTouch||e.applyDragOpacity(m),c.hide()):c.show(),h&&(d=null)},hitOut:function(){f.unrenderDrag(),c.show(),d=null},hitDone:function(){h()},interactionEnd:function(g){c.stop(!d,function(){b&&(f.unrenderDrag(),f.showEvent(k),e.segDragStop(a,g)),d&&f.reportEventDrop(k,d,this.largeUnit,j,g)}),e.segDragListener=null}});return l},buildSegSelectListener:function(a){var b=this,c=this.view,d=a.event;if(this.segDragListener)return this.segDragListener;var e=this.segDragListener=new qb({dragStart:function(a){e.isTouch&&!c.isEventSelected(d)&&c.selectEvent(d)},interactionEnd:function(a){b.segDragListener=null}});return e},segDragStart:function(a,b){this.isDraggingSeg=!0,this.view.trigger("eventDragStart",a.el[0],a.event,b,{})},segDragStop:function(a,b){this.isDraggingSeg=!1,this.view.trigger("eventDragStop",a.el[0],a.event,b,{})},computeEventDrop:function(a,b,c){var d,e,f=this.view.calendar,g=a.start,h=b.start;return g.hasTime()===h.hasTime()?(d=this.diffDates(h,g),c.allDay&&T(d)?(e={start:c.start.clone(),end:f.getEventEnd(c),allDay:!1},f.normalizeEventTimes(e)):e={start:c.start.clone(),end:c.end?c.end.clone():null,allDay:c.allDay},e.start.add(d),e.end&&e.end.add(d)):e={start:h.clone(),end:null,allDay:!h.hasTime()},e},applyDragOpacity:function(a){var b=this.view.opt("dragOpacity");null!=b&&a.each(function(a,c){c.style.opacity=b})},externalDragStart:function(b,c){var d,e,f=this.view;f.opt("droppable")&&(d=a((c?c.item:null)||b.target),e=f.opt("dropAccept"),(a.isFunction(e)?e.call(d[0],d):d.is(e))&&(this.isDraggingExternal||this.listenToExternalDrag(d,b,c)))},listenToExternalDrag:function(a,b,c){var d,e=this,f=this.view.calendar,i=Ia(a),j=e.externalDragListener=new rb(this,{interactionStart:function(){e.isDraggingExternal=!0},hitOver:function(a){d=e.computeExternalDrop(a.component.getHitSpan(a),i),d&&!f.isExternalSpanAllowed(e.eventToSpan(d),d,i.eventProps)&&(g(),d=null),d&&e.renderDrag(d)},hitOut:function(){d=null},hitDone:function(){h(),e.unrenderDrag()},interactionEnd:function(b){d&&e.view.reportExternalDrop(i,d,a,b,c),e.isDraggingExternal=!1,e.externalDragListener=null}});j.startDrag(b)},computeExternalDrop:function(a,b){var c=this.view.calendar,d={start:c.applyTimezone(a.start),end:null};return b.startTime&&!d.start.hasTime()&&d.start.time(b.startTime),b.duration&&(d.end=d.start.clone().add(b.duration)),d},renderDrag:function(a,b){},unrenderDrag:function(){},buildSegResizeListener:function(a,b){var c,d,e=this,f=this.view,i=f.calendar,j=a.el,k=a.event,l=i.getEventEnd(k),m=this.segResizeListener=new rb(this,{scroll:f.opt("dragScroll"),subjectEl:j,interactionStart:function(){c=!1},dragStart:function(b){c=!0,e.handleSegMouseout(a,b),e.segResizeStart(a,b)},hitOver:function(c,h,j){var m=e.getHitSpan(j),n=e.getHitSpan(c);d=b?e.computeEventStartResize(m,n,k):e.computeEventEndResize(m,n,k),d&&(i.isEventSpanAllowed(e.eventToSpan(d),k)?d.start.isSame(k.start)&&d.end.isSame(l)&&(d=null):(g(),d=null)),d&&(f.hideEvent(k),e.renderEventResize(d,a))},hitOut:function(){d=null},hitDone:function(){e.unrenderEventResize(),f.showEvent(k),h()},interactionEnd:function(b){c&&e.segResizeStop(a,b),d&&f.reportEventResize(k,d,this.largeUnit,j,b),e.segResizeListener=null}});return m},segResizeStart:function(a,b){this.isResizingSeg=!0,this.view.trigger("eventResizeStart",a.el[0],a.event,b,{})},segResizeStop:function(a,b){this.isResizingSeg=!1,this.view.trigger("eventResizeStop",a.el[0],a.event,b,{})},computeEventStartResize:function(a,b,c){return this.computeEventResize("start",a,b,c)},computeEventEndResize:function(a,b,c){return this.computeEventResize("end",a,b,c)},computeEventResize:function(a,b,c,d){var e,f,g=this.view.calendar,h=this.diffDates(c[a],b[a]);return e={start:d.start.clone(),end:g.getEventEnd(d),allDay:d.allDay},e.allDay&&T(h)&&(e.allDay=!1,g.normalizeEventTimes(e)),e[a].add(h),e.start.isBefore(e.end)||(f=this.minResizeDuration||(d.allDay?g.defaultAllDayEventDuration:g.defaultTimedEventDuration),"start"==a?e.start=e.end.clone().subtract(f):e.end=e.start.clone().add(f)),e},renderEventResize:function(a,b){},unrenderEventResize:function(){},getEventTimeText:function(a,b,c){return null==b&&(b=this.eventTimeFormat),null==c&&(c=this.displayEventEnd),this.displayEventTime&&a.start.hasTime()?c&&a.end?this.view.formatRange(a,b):a.start.format(b):""},getSegClasses:function(a,b,c){var d=this.view,e=a.event,f=["fc-event",a.isStart?"fc-start":"fc-not-start",a.isEnd?"fc-end":"fc-not-end"].concat(e.className,e.source?e.source.className:[]);return b&&f.push("fc-draggable"),c&&f.push("fc-resizable"),d.isEventSelected(e)&&f.push("fc-selected"),f},getSegSkinCss:function(a){var b=a.event,c=this.view,d=b.source||{},e=b.color,f=d.color,g=c.opt("eventColor");return{"background-color":b.backgroundColor||e||d.backgroundColor||f||c.opt("eventBackgroundColor")||g,"border-color":b.borderColor||e||d.borderColor||f||c.opt("eventBorderColor")||g,color:b.textColor||d.textColor||c.opt("eventTextColor")}},eventToSegs:function(a){return this.eventsToSegs([a])},eventToSpan:function(a){return this.eventToSpans(a)[0]},eventToSpans:function(a){var b=this.eventToRange(a);return this.eventRangeToSpans(b,a)},eventsToSegs:function(b,c){var d=this,e=Ga(b),f=[];return a.each(e,function(a,b){var e,g=[];for(e=0;e<b.length;e++)g.push(d.eventToRange(b[e]));if(Ea(b[0]))for(g=d.invertRanges(g),e=0;e<g.length;e++)f.push.apply(f,d.eventRangeToSegs(g[e],b[0],c));else for(e=0;e<g.length;e++)f.push.apply(f,d.eventRangeToSegs(g[e],b[e],c))}),f},eventToRange:function(a){return{start:a.start.clone().stripZone(),end:(a.end?a.end.clone():this.view.calendar.getDefaultEventEnd(null!=a.allDay?a.allDay:!a.start.hasTime(),a.start)).stripZone()}},eventRangeToSegs:function(a,b,c){var d,e=this.eventRangeToSpans(a,b),f=[];for(d=0;d<e.length;d++)f.push.apply(f,this.eventSpanToSegs(e[d],b,c));return f},eventRangeToSpans:function(b,c){return[a.extend({},b)]},eventSpanToSegs:function(a,b,c){var d,e,f=c?c(a):this.spanToSegs(a);for(d=0;d<f.length;d++)e=f[d],e.event=b,e.eventStartMS=+a.start,e.eventDurationMS=a.end-a.start;return f},invertRanges:function(a){var b,c,d=this.view,e=d.start.clone(),f=d.end.clone(),g=[],h=e;for(a.sort(Ha),b=0;b<a.length;b++)c=a[b],c.start>h&&g.push({start:h,end:c.start}),h=c.end;return f>h&&g.push({start:h,end:f}),g},sortEventSegs:function(a){a.sort(ia(this,"compareEventSegs"))},compareEventSegs:function(a,b){return a.eventStartMS-b.eventStartMS||b.eventDurationMS-a.eventDurationMS||b.event.allDay-a.event.allDay||H(a.event,b.event,this.view.eventOrderSpecs)}}),Wa.isBgEvent=Da,Wa.dataAttrPrefix="";var ub=Wa.DayTableMixin={breakOnWeeks:!1,dayDates:null,dayIndices:null,daysPerRow:null,rowCnt:null,colCnt:null,colHeadFormat:null,updateDayTable:function(){for(var a,b,c,d=this.view,e=this.start.clone(),f=-1,g=[],h=[];e.isBefore(this.end);)d.isHiddenDay(e)?g.push(f+.5):(f++,g.push(f),h.push(e.clone())),e.add(1,"days");if(this.breakOnWeeks){for(b=h[0].day(),a=1;a<h.length&&h[a].day()!=b;a++);c=Math.ceil(h.length/a)}else c=1,a=h.length;this.dayDates=h,this.dayIndices=g,this.daysPerRow=a,this.rowCnt=c,this.updateDayTableCols()},updateDayTableCols:function(){this.colCnt=this.computeColCnt(),this.colHeadFormat=this.view.opt("columnFormat")||this.computeColHeadFormat()},computeColCnt:function(){return this.daysPerRow},getCellDate:function(a,b){return this.dayDates[this.getCellDayIndex(a,b)].clone()},getCellRange:function(a,b){var c=this.getCellDate(a,b),d=c.clone().add(1,"days");return{start:c,end:d}},getCellDayIndex:function(a,b){return a*this.daysPerRow+this.getColDayIndex(b)},getColDayIndex:function(a){return this.isRTL?this.colCnt-1-a:a},getDateDayIndex:function(a){var b=this.dayIndices,c=a.diff(this.start,"days");return 0>c?b[0]-1:c>=b.length?b[b.length-1]+1:b[c]},computeColHeadFormat:function(){return this.rowCnt>1||this.colCnt>10?"ddd":this.colCnt>1?this.view.opt("dayOfMonthFormat"):"dddd"},sliceRangeByRow:function(a){var b,c,d,e,f,g=this.daysPerRow,h=this.view.computeDayRange(a),i=this.getDateDayIndex(h.start),j=this.getDateDayIndex(h.end.clone().subtract(1,"days")),k=[];for(b=0;b<this.rowCnt;b++)c=b*g,d=c+g-1,e=Math.max(i,c),f=Math.min(j,d),e=Math.ceil(e),f=Math.floor(f),f>=e&&k.push({row:b,firstRowDayIndex:e-c,lastRowDayIndex:f-c,isStart:e===i,isEnd:f===j});return k},sliceRangeByDay:function(a){var b,c,d,e,f,g,h=this.daysPerRow,i=this.view.computeDayRange(a),j=this.getDateDayIndex(i.start),k=this.getDateDayIndex(i.end.clone().subtract(1,"days")),l=[];for(b=0;b<this.rowCnt;b++)for(c=b*h, +d=c+h-1,e=c;d>=e;e++)f=Math.max(j,e),g=Math.min(k,e),f=Math.ceil(f),g=Math.floor(g),g>=f&&l.push({row:b,firstRowDayIndex:f-c,lastRowDayIndex:g-c,isStart:f===j,isEnd:g===k});return l},renderHeadHtml:function(){var a=this.view;return'<div class="fc-row '+a.widgetHeaderClass+'"><table><thead>'+this.renderHeadTrHtml()+"</thead></table></div>"},renderHeadIntroHtml:function(){return this.renderIntroHtml()},renderHeadTrHtml:function(){return"<tr>"+(this.isRTL?"":this.renderHeadIntroHtml())+this.renderHeadDateCellsHtml()+(this.isRTL?this.renderHeadIntroHtml():"")+"</tr>"},renderHeadDateCellsHtml:function(){var a,b,c=[];for(a=0;a<this.colCnt;a++)b=this.getCellDate(0,a),c.push(this.renderHeadDateCellHtml(b));return c.join("")},renderHeadDateCellHtml:function(a,b,c){var d=this.view;return'<th class="fc-day-header '+d.widgetHeaderClass+" fc-"+$a[a.day()]+'"'+(1==this.rowCnt?' data-date="'+a.format("YYYY-MM-DD")+'"':"")+(b>1?' colspan="'+b+'"':"")+(c?" "+c:"")+">"+ca(a.format(this.colHeadFormat))+"</th>"},renderBgTrHtml:function(a){return"<tr>"+(this.isRTL?"":this.renderBgIntroHtml(a))+this.renderBgCellsHtml(a)+(this.isRTL?this.renderBgIntroHtml(a):"")+"</tr>"},renderBgIntroHtml:function(a){return this.renderIntroHtml()},renderBgCellsHtml:function(a){var b,c,d=[];for(b=0;b<this.colCnt;b++)c=this.getCellDate(a,b),d.push(this.renderBgCellHtml(c));return d.join("")},renderBgCellHtml:function(a,b){var c=this.view,d=this.getDayClasses(a);return d.unshift("fc-day",c.widgetContentClass),'<td class="'+d.join(" ")+'" data-date="'+a.format("YYYY-MM-DD")+'"'+(b?" "+b:"")+"></td>"},renderIntroHtml:function(){},bookendCells:function(a){var b=this.renderIntroHtml();b&&(this.isRTL?a.append(b):a.prepend(b))}},vb=Wa.DayGrid=tb.extend(ub,{numbersVisible:!1,bottomCoordPadding:0,rowEls:null,cellEls:null,helperEls:null,rowCoordCache:null,colCoordCache:null,renderDates:function(a){var b,c,d=this.view,e=this.rowCnt,f=this.colCnt,g="";for(b=0;e>b;b++)g+=this.renderDayRowHtml(b,a);for(this.el.html(g),this.rowEls=this.el.find(".fc-row"),this.cellEls=this.el.find(".fc-day"),this.rowCoordCache=new pb({els:this.rowEls,isVertical:!0}),this.colCoordCache=new pb({els:this.cellEls.slice(0,this.colCnt),isHorizontal:!0}),b=0;e>b;b++)for(c=0;f>c;c++)d.trigger("dayRender",null,this.getCellDate(b,c),this.getCellEl(b,c))},unrenderDates:function(){this.removeSegPopover()},renderBusinessHours:function(){var a=this.view.calendar.getBusinessHoursEvents(!0),b=this.eventsToSegs(a);this.renderFill("businessHours",b,"bgevent")},renderDayRowHtml:function(a,b){var c=this.view,d=["fc-row","fc-week",c.widgetContentClass];return b&&d.push("fc-rigid"),'<div class="'+d.join(" ")+'"><div class="fc-bg"><table>'+this.renderBgTrHtml(a)+'</table></div><div class="fc-content-skeleton"><table>'+(this.numbersVisible?"<thead>"+this.renderNumberTrHtml(a)+"</thead>":"")+"</table></div></div>"},renderNumberTrHtml:function(a){return"<tr>"+(this.isRTL?"":this.renderNumberIntroHtml(a))+this.renderNumberCellsHtml(a)+(this.isRTL?this.renderNumberIntroHtml(a):"")+"</tr>"},renderNumberIntroHtml:function(a){return this.renderIntroHtml()},renderNumberCellsHtml:function(a){var b,c,d=[];for(b=0;b<this.colCnt;b++)c=this.getCellDate(a,b),d.push(this.renderNumberCellHtml(c));return d.join("")},renderNumberCellHtml:function(a){var b;return this.view.dayNumbersVisible?(b=this.getDayClasses(a),b.unshift("fc-day-number"),'<td class="'+b.join(" ")+'" data-date="'+a.format()+'">'+a.date()+"</td>"):"<td/>"},computeEventTimeFormat:function(){return this.view.opt("extraSmallTimeFormat")},computeDisplayEventEnd:function(){return 1==this.colCnt},rangeUpdated:function(){this.updateDayTable()},spanToSegs:function(a){var b,c,d=this.sliceRangeByRow(a);for(b=0;b<d.length;b++)c=d[b],this.isRTL?(c.leftCol=this.daysPerRow-1-c.lastRowDayIndex,c.rightCol=this.daysPerRow-1-c.firstRowDayIndex):(c.leftCol=c.firstRowDayIndex,c.rightCol=c.lastRowDayIndex);return d},prepareHits:function(){this.colCoordCache.build(),this.rowCoordCache.build(),this.rowCoordCache.bottoms[this.rowCnt-1]+=this.bottomCoordPadding},releaseHits:function(){this.colCoordCache.clear(),this.rowCoordCache.clear()},queryHit:function(a,b){var c=this.colCoordCache.getHorizontalIndex(a),d=this.rowCoordCache.getVerticalIndex(b);return null!=d&&null!=c?this.getCellHit(d,c):void 0},getHitSpan:function(a){return this.getCellRange(a.row,a.col)},getHitEl:function(a){return this.getCellEl(a.row,a.col)},getCellHit:function(a,b){return{row:a,col:b,component:this,left:this.colCoordCache.getLeftOffset(b),right:this.colCoordCache.getRightOffset(b),top:this.rowCoordCache.getTopOffset(a),bottom:this.rowCoordCache.getBottomOffset(a)}},getCellEl:function(a,b){return this.cellEls.eq(a*this.colCnt+b)},renderDrag:function(a,b){return this.renderHighlight(this.eventToSpan(a)),b&&!b.el.closest(this.el).length?this.renderEventLocationHelper(a,b):void 0},unrenderDrag:function(){this.unrenderHighlight(),this.unrenderHelper()},renderEventResize:function(a,b){return this.renderHighlight(this.eventToSpan(a)),this.renderEventLocationHelper(a,b)},unrenderEventResize:function(){this.unrenderHighlight(),this.unrenderHelper()},renderHelper:function(b,c){var d,e=[],f=this.eventToSegs(b);return f=this.renderFgSegEls(f),d=this.renderSegRows(f),this.rowEls.each(function(b,f){var g,h=a(f),i=a('<div class="fc-helper-skeleton"><table/></div>');g=c&&c.row===b?c.el.position().top:h.find(".fc-content-skeleton tbody").position().top,i.css("top",g).find("table").append(d[b].tbodyEl),h.append(i),e.push(i[0])}),this.helperEls=a(e)},unrenderHelper:function(){this.helperEls&&(this.helperEls.remove(),this.helperEls=null)},fillSegTag:"td",renderFill:function(b,c,d){var e,f,g,h=[];for(c=this.renderFillSegEls(b,c),e=0;e<c.length;e++)f=c[e],g=this.renderFillRow(b,f,d),this.rowEls.eq(f.row).append(g),h.push(g[0]);return this.elsByFill[b]=a(h),c},renderFillRow:function(b,c,d){var e,f,g=this.colCnt,h=c.leftCol,i=c.rightCol+1;return d=d||b.toLowerCase(),e=a('<div class="fc-'+d+'-skeleton"><table><tr/></table></div>'),f=e.find("tr"),h>0&&f.append('<td colspan="'+h+'"/>'),f.append(c.el.attr("colspan",i-h)),g>i&&f.append('<td colspan="'+(g-i)+'"/>'),this.bookendCells(f),e}});vb.mixin({rowStructs:null,unrenderEvents:function(){this.removeSegPopover(),tb.prototype.unrenderEvents.apply(this,arguments)},getEventSegs:function(){return tb.prototype.getEventSegs.call(this).concat(this.popoverSegs||[])},renderBgSegs:function(b){var c=a.grep(b,function(a){return a.event.allDay});return tb.prototype.renderBgSegs.call(this,c)},renderFgSegs:function(b){var c;return b=this.renderFgSegEls(b),c=this.rowStructs=this.renderSegRows(b),this.rowEls.each(function(b,d){a(d).find(".fc-content-skeleton > table").append(c[b].tbodyEl)}),b},unrenderFgSegs:function(){for(var a,b=this.rowStructs||[];a=b.pop();)a.tbodyEl.remove();this.rowStructs=null},renderSegRows:function(a){var b,c,d=[];for(b=this.groupSegRows(a),c=0;c<b.length;c++)d.push(this.renderSegRow(c,b[c]));return d},fgSegHtml:function(a,b){var c,d,e=this.view,f=a.event,g=e.isEventDraggable(f),h=!b&&f.allDay&&a.isStart&&e.isEventResizableFromStart(f),i=!b&&f.allDay&&a.isEnd&&e.isEventResizableFromEnd(f),j=this.getSegClasses(a,g,h||i),k=ea(this.getSegSkinCss(a)),l="";return j.unshift("fc-day-grid-event","fc-h-event"),a.isStart&&(c=this.getEventTimeText(f),c&&(l='<span class="fc-time">'+ca(c)+"</span>")),d='<span class="fc-title">'+(ca(f.title||"")||" ")+"</span>",'<a class="'+j.join(" ")+'"'+(f.url?' href="'+ca(f.url)+'"':"")+(k?' style="'+k+'"':"")+'><div class="fc-content">'+(this.isRTL?d+" "+l:l+" "+d)+"</div>"+(h?'<div class="fc-resizer fc-start-resizer" />':"")+(i?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},renderSegRow:function(b,c){function d(b){for(;b>g;)k=(r[e-1]||[])[g],k?k.attr("rowspan",parseInt(k.attr("rowspan")||1,10)+1):(k=a("<td/>"),h.append(k)),q[e][g]=k,r[e][g]=k,g++}var e,f,g,h,i,j,k,l=this.colCnt,m=this.buildSegLevels(c),n=Math.max(1,m.length),o=a("<tbody/>"),p=[],q=[],r=[];for(e=0;n>e;e++){if(f=m[e],g=0,h=a("<tr/>"),p.push([]),q.push([]),r.push([]),f)for(i=0;i<f.length;i++){for(j=f[i],d(j.leftCol),k=a('<td class="fc-event-container"/>').append(j.el),j.leftCol!=j.rightCol?k.attr("colspan",j.rightCol-j.leftCol+1):r[e][g]=k;g<=j.rightCol;)q[e][g]=k,p[e][g]=j,g++;h.append(k)}d(l),this.bookendCells(h),o.append(h)}return{row:b,tbodyEl:o,cellMatrix:q,segMatrix:p,segLevels:m,segs:c}},buildSegLevels:function(a){var b,c,d,e=[];for(this.sortEventSegs(a),b=0;b<a.length;b++){for(c=a[b],d=0;d<e.length&&Ja(c,e[d]);d++);c.level=d,(e[d]||(e[d]=[])).push(c)}for(d=0;d<e.length;d++)e[d].sort(Ka);return e},groupSegRows:function(a){var b,c=[];for(b=0;b<this.rowCnt;b++)c.push([]);for(b=0;b<a.length;b++)c[a[b].row].push(a[b]);return c}}),vb.mixin({segPopover:null,popoverSegs:null,removeSegPopover:function(){this.segPopover&&this.segPopover.hide()},limitRows:function(a){var b,c,d=this.rowStructs||[];for(b=0;b<d.length;b++)this.unlimitRow(b),c=a?"number"==typeof a?a:this.computeRowLevelLimit(b):!1,c!==!1&&this.limitRow(b,c)},computeRowLevelLimit:function(b){function c(b,c){f=Math.max(f,a(c).outerHeight())}var d,e,f,g=this.rowEls.eq(b),h=g.height(),i=this.rowStructs[b].tbodyEl.children();for(d=0;d<i.length;d++)if(e=i.eq(d).removeClass("fc-limited"),f=0,e.find("> td > :first-child").each(c),e.position().top+f>h)return d;return!1},limitRow:function(b,c){function d(d){for(;d>w;)j=t.getCellSegs(b,w,c),j.length&&(m=f[c-1][w],s=t.renderMoreLink(b,w,j),r=a("<div/>").append(s),m.append(r),v.push(r[0])),w++}var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t=this,u=this.rowStructs[b],v=[],w=0;if(c&&c<u.segLevels.length){for(e=u.segLevels[c-1],f=u.cellMatrix,g=u.tbodyEl.children().slice(c).addClass("fc-limited").get(),h=0;h<e.length;h++){for(i=e[h],d(i.leftCol),l=[],k=0;w<=i.rightCol;)j=this.getCellSegs(b,w,c),l.push(j),k+=j.length,w++;if(k){for(m=f[c-1][i.leftCol],n=m.attr("rowspan")||1,o=[],p=0;p<l.length;p++)q=a('<td class="fc-more-cell"/>').attr("rowspan",n),j=l[p],s=this.renderMoreLink(b,i.leftCol+p,[i].concat(j)),r=a("<div/>").append(s),q.append(r),o.push(q[0]),v.push(q[0]);m.addClass("fc-limited").after(a(o)),g.push(m[0])}}d(this.colCnt),u.moreEls=a(v),u.limitedEls=a(g)}},unlimitRow:function(a){var b=this.rowStructs[a];b.moreEls&&(b.moreEls.remove(),b.moreEls=null),b.limitedEls&&(b.limitedEls.removeClass("fc-limited"),b.limitedEls=null)},renderMoreLink:function(b,c,d){var e=this,f=this.view;return a('<a class="fc-more"/>').text(this.getMoreLinkText(d.length)).on("click",function(g){var h=f.opt("eventLimitClick"),i=e.getCellDate(b,c),j=a(this),k=e.getCellEl(b,c),l=e.getCellSegs(b,c),m=e.resliceDaySegs(l,i),n=e.resliceDaySegs(d,i);"function"==typeof h&&(h=f.trigger("eventLimitClick",null,{date:i,dayEl:k,moreEl:j,segs:m,hiddenSegs:n},g)),"popover"===h?e.showSegPopover(b,c,j,m):"string"==typeof h&&f.calendar.zoomTo(i,h)})},showSegPopover:function(a,b,c,d){var e,f,g=this,h=this.view,i=c.parent();e=1==this.rowCnt?h.el:this.rowEls.eq(a),f={className:"fc-more-popover",content:this.renderSegPopoverContent(a,b,d),parentEl:this.el,top:e.offset().top,autoHide:!0,viewportConstrain:h.opt("popoverViewportConstrain"),hide:function(){g.segPopover.removeElement(),g.segPopover=null,g.popoverSegs=null}},this.isRTL?f.right=i.offset().left+i.outerWidth()+1:f.left=i.offset().left-1,this.segPopover=new ob(f),this.segPopover.show()},renderSegPopoverContent:function(b,c,d){var e,f=this.view,g=f.opt("theme"),h=this.getCellDate(b,c).format(f.opt("dayPopoverFormat")),i=a('<div class="fc-header '+f.widgetHeaderClass+'"><span class="fc-close '+(g?"ui-icon ui-icon-closethick":"fc-icon fc-icon-x")+'"></span><span class="fc-title">'+ca(h)+'</span><div class="fc-clear"/></div><div class="fc-body '+f.widgetContentClass+'"><div class="fc-event-container"></div></div>'),j=i.find(".fc-event-container");for(d=this.renderFgSegEls(d,!0),this.popoverSegs=d,e=0;e<d.length;e++)this.prepareHits(),d[e].hit=this.getCellHit(b,c),this.releaseHits(),j.append(d[e].el);return i},resliceDaySegs:function(b,c){var d=a.map(b,function(a){return a.event}),e=c.clone(),f=e.clone().add(1,"days"),g={start:e,end:f};return b=this.eventsToSegs(d,function(a){var b=K(a,g);return b?[b]:[]}),this.sortEventSegs(b),b},getMoreLinkText:function(a){var b=this.view.opt("eventLimitText");return"function"==typeof b?b(a):"+"+a+" "+b},getCellSegs:function(a,b,c){for(var d,e=this.rowStructs[a].segMatrix,f=c||0,g=[];f<e.length;)d=e[f][b],d&&g.push(d),f++;return g}});var wb=Wa.TimeGrid=tb.extend(ub,{slotDuration:null,snapDuration:null,snapsPerSlot:null,minTime:null,maxTime:null,labelFormat:null,labelInterval:null,colEls:null,slatContainerEl:null,slatEls:null,nowIndicatorEls:null,colCoordCache:null,slatCoordCache:null,constructor:function(){tb.apply(this,arguments),this.processOptions()},renderDates:function(){this.el.html(this.renderHtml()),this.colEls=this.el.find(".fc-day"),this.slatContainerEl=this.el.find(".fc-slats"),this.slatEls=this.slatContainerEl.find("tr"),this.colCoordCache=new pb({els:this.colEls,isHorizontal:!0}),this.slatCoordCache=new pb({els:this.slatEls,isVertical:!0}),this.renderContentSkeleton()},renderHtml:function(){return'<div class="fc-bg"><table>'+this.renderBgTrHtml(0)+'</table></div><div class="fc-slats"><table>'+this.renderSlatRowHtml()+"</table></div>"},renderSlatRowHtml:function(){for(var a,c,d,e=this.view,f=this.isRTL,g="",h=b.duration(+this.minTime);h<this.maxTime;)a=this.start.clone().time(h),c=ha(R(h,this.labelInterval)),d='<td class="fc-axis fc-time '+e.widgetContentClass+'" '+e.axisStyleAttr()+">"+(c?"<span>"+ca(a.format(this.labelFormat))+"</span>":"")+"</td>",g+='<tr data-time="'+a.format("HH:mm:ss")+'"'+(c?"":' class="fc-minor"')+">"+(f?"":d)+'<td class="'+e.widgetContentClass+'"/>'+(f?d:"")+"</tr>",h.add(this.slotDuration);return g},processOptions:function(){var c,d=this.view,e=d.opt("slotDuration"),f=d.opt("snapDuration");e=b.duration(e),f=f?b.duration(f):e,this.slotDuration=e,this.snapDuration=f,this.snapsPerSlot=e/f,this.minResizeDuration=f,this.minTime=b.duration(d.opt("minTime")),this.maxTime=b.duration(d.opt("maxTime")),c=d.opt("slotLabelFormat"),a.isArray(c)&&(c=c[c.length-1]),this.labelFormat=c||d.opt("axisFormat")||d.opt("smallTimeFormat"),c=d.opt("slotLabelInterval"),this.labelInterval=c?b.duration(c):this.computeLabelInterval(e)},computeLabelInterval:function(a){var c,d,e;for(c=Nb.length-1;c>=0;c--)if(d=b.duration(Nb[c]),e=R(d,a),ha(e)&&e>1)return d;return b.duration(a)},computeEventTimeFormat:function(){return this.view.opt("noMeridiemTimeFormat")},computeDisplayEventEnd:function(){return!0},prepareHits:function(){this.colCoordCache.build(),this.slatCoordCache.build()},releaseHits:function(){this.colCoordCache.clear()},queryHit:function(a,b){var c=this.snapsPerSlot,d=this.colCoordCache,e=this.slatCoordCache,f=d.getHorizontalIndex(a),g=e.getVerticalIndex(b);if(null!=f&&null!=g){var h=e.getTopOffset(g),i=e.getHeight(g),j=(b-h)/i,k=Math.floor(j*c),l=g*c+k,m=h+k/c*i,n=h+(k+1)/c*i;return{col:f,snap:l,component:this,left:d.getLeftOffset(f),right:d.getRightOffset(f),top:m,bottom:n}}},getHitSpan:function(a){var b,c=this.getCellDate(0,a.col),d=this.computeSnapTime(a.snap);return c.time(d),b=c.clone().add(this.snapDuration),{start:c,end:b}},getHitEl:function(a){return this.colEls.eq(a.col)},rangeUpdated:function(){this.updateDayTable()},computeSnapTime:function(a){return b.duration(this.minTime+this.snapDuration*a)},spanToSegs:function(a){var b,c=this.sliceRangeByTimes(a);for(b=0;b<c.length;b++)this.isRTL?c[b].col=this.daysPerRow-1-c[b].dayIndex:c[b].col=c[b].dayIndex;return c},sliceRangeByTimes:function(a){var b,c,d,e,f=[];for(c=0;c<this.daysPerRow;c++)d=this.dayDates[c].clone(),e={start:d.clone().time(this.minTime),end:d.clone().time(this.maxTime)},b=K(a,e),b&&(b.dayIndex=c,f.push(b));return f},updateSize:function(a){this.slatCoordCache.build(),a&&this.updateSegVerticals([].concat(this.fgSegs||[],this.bgSegs||[],this.businessSegs||[]))},getTotalSlatHeight:function(){return this.slatContainerEl.outerHeight()},computeDateTop:function(a,c){return this.computeTimeTop(b.duration(a-c.clone().stripTime()))},computeTimeTop:function(a){var b,c,d=this.slatEls.length,e=(a-this.minTime)/this.slotDuration;return e=Math.max(0,e),e=Math.min(d,e),b=Math.floor(e),b=Math.min(b,d-1),c=e-b,this.slatCoordCache.getTopPosition(b)+this.slatCoordCache.getHeight(b)*c},renderDrag:function(a,b){return b?this.renderEventLocationHelper(a,b):void this.renderHighlight(this.eventToSpan(a))},unrenderDrag:function(){this.unrenderHelper(),this.unrenderHighlight()},renderEventResize:function(a,b){return this.renderEventLocationHelper(a,b)},unrenderEventResize:function(){this.unrenderHelper()},renderHelper:function(a,b){return this.renderHelperSegs(this.eventToSegs(a),b)},unrenderHelper:function(){this.unrenderHelperSegs()},renderBusinessHours:function(){var a=this.view.calendar.getBusinessHoursEvents(),b=this.eventsToSegs(a);this.renderBusinessSegs(b)},unrenderBusinessHours:function(){this.unrenderBusinessSegs()},getNowIndicatorUnit:function(){return"minute"},renderNowIndicator:function(b){var c,d=this.spanToSegs({start:b,end:b}),e=this.computeDateTop(b,b),f=[];for(c=0;c<d.length;c++)f.push(a('<div class="fc-now-indicator fc-now-indicator-line"></div>').css("top",e).appendTo(this.colContainerEls.eq(d[c].col))[0]);d.length>0&&f.push(a('<div class="fc-now-indicator fc-now-indicator-arrow"></div>').css("top",e).appendTo(this.el.find(".fc-content-skeleton"))[0]),this.nowIndicatorEls=a(f)},unrenderNowIndicator:function(){this.nowIndicatorEls&&(this.nowIndicatorEls.remove(),this.nowIndicatorEls=null)},renderSelection:function(a){this.view.opt("selectHelper")?this.renderEventLocationHelper(a):this.renderHighlight(a)},unrenderSelection:function(){this.unrenderHelper(),this.unrenderHighlight()},renderHighlight:function(a){this.renderHighlightSegs(this.spanToSegs(a))},unrenderHighlight:function(){this.unrenderHighlightSegs()}});wb.mixin({colContainerEls:null,fgContainerEls:null,bgContainerEls:null,helperContainerEls:null,highlightContainerEls:null,businessContainerEls:null,fgSegs:null,bgSegs:null,helperSegs:null,highlightSegs:null,businessSegs:null,renderContentSkeleton:function(){var b,c,d="";for(b=0;b<this.colCnt;b++)d+='<td><div class="fc-content-col"><div class="fc-event-container fc-helper-container"></div><div class="fc-event-container"></div><div class="fc-highlight-container"></div><div class="fc-bgevent-container"></div><div class="fc-business-container"></div></div></td>';c=a('<div class="fc-content-skeleton"><table><tr>'+d+"</tr></table></div>"),this.colContainerEls=c.find(".fc-content-col"),this.helperContainerEls=c.find(".fc-helper-container"),this.fgContainerEls=c.find(".fc-event-container:not(.fc-helper-container)"),this.bgContainerEls=c.find(".fc-bgevent-container"),this.highlightContainerEls=c.find(".fc-highlight-container"),this.businessContainerEls=c.find(".fc-business-container"),this.bookendCells(c.find("tr")),this.el.append(c)},renderFgSegs:function(a){return a=this.renderFgSegsIntoContainers(a,this.fgContainerEls),this.fgSegs=a,a},unrenderFgSegs:function(){this.unrenderNamedSegs("fgSegs")},renderHelperSegs:function(b,c){var d,e,f,g=[];for(b=this.renderFgSegsIntoContainers(b,this.helperContainerEls),d=0;d<b.length;d++)e=b[d],c&&c.col===e.col&&(f=c.el,e.el.css({left:f.css("left"),right:f.css("right"),"margin-left":f.css("margin-left"),"margin-right":f.css("margin-right")})),g.push(e.el[0]);return this.helperSegs=b,a(g)},unrenderHelperSegs:function(){this.unrenderNamedSegs("helperSegs")},renderBgSegs:function(a){return a=this.renderFillSegEls("bgEvent",a),this.updateSegVerticals(a),this.attachSegsByCol(this.groupSegsByCol(a),this.bgContainerEls),this.bgSegs=a,a},unrenderBgSegs:function(){this.unrenderNamedSegs("bgSegs")},renderHighlightSegs:function(a){a=this.renderFillSegEls("highlight",a),this.updateSegVerticals(a),this.attachSegsByCol(this.groupSegsByCol(a),this.highlightContainerEls),this.highlightSegs=a},unrenderHighlightSegs:function(){this.unrenderNamedSegs("highlightSegs")},renderBusinessSegs:function(a){a=this.renderFillSegEls("businessHours",a),this.updateSegVerticals(a),this.attachSegsByCol(this.groupSegsByCol(a),this.businessContainerEls),this.businessSegs=a},unrenderBusinessSegs:function(){this.unrenderNamedSegs("businessSegs")},groupSegsByCol:function(a){var b,c=[];for(b=0;b<this.colCnt;b++)c.push([]);for(b=0;b<a.length;b++)c[a[b].col].push(a[b]);return c},attachSegsByCol:function(a,b){var c,d,e;for(c=0;c<this.colCnt;c++)for(d=a[c],e=0;e<d.length;e++)b.eq(c).append(d[e].el)},unrenderNamedSegs:function(a){var b,c=this[a];if(c){for(b=0;b<c.length;b++)c[b].el.remove();this[a]=null}},renderFgSegsIntoContainers:function(a,b){var c,d;for(a=this.renderFgSegEls(a),c=this.groupSegsByCol(a),d=0;d<this.colCnt;d++)this.updateFgSegCoords(c[d]);return this.attachSegsByCol(c,b),a},fgSegHtml:function(a,b){var c,d,e,f=this.view,g=a.event,h=f.isEventDraggable(g),i=!b&&a.isStart&&f.isEventResizableFromStart(g),j=!b&&a.isEnd&&f.isEventResizableFromEnd(g),k=this.getSegClasses(a,h,i||j),l=ea(this.getSegSkinCss(a));return k.unshift("fc-time-grid-event","fc-v-event"),f.isMultiDayEvent(g)?(a.isStart||a.isEnd)&&(c=this.getEventTimeText(a),d=this.getEventTimeText(a,"LT"),e=this.getEventTimeText(a,null,!1)):(c=this.getEventTimeText(g),d=this.getEventTimeText(g,"LT"),e=this.getEventTimeText(g,null,!1)),'<a class="'+k.join(" ")+'"'+(g.url?' href="'+ca(g.url)+'"':"")+(l?' style="'+l+'"':"")+'><div class="fc-content">'+(c?'<div class="fc-time" data-start="'+ca(e)+'" data-full="'+ca(d)+'"><span>'+ca(c)+"</span></div>":"")+(g.title?'<div class="fc-title">'+ca(g.title)+"</div>":"")+'</div><div class="fc-bg"/>'+(j?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},updateSegVerticals:function(a){this.computeSegVerticals(a),this.assignSegVerticals(a)},computeSegVerticals:function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.top=this.computeDateTop(c.start,c.start),c.bottom=this.computeDateTop(c.end,c.start)},assignSegVerticals:function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.el.css(this.generateSegVerticalCss(c))},generateSegVerticalCss:function(a){return{top:a.top,bottom:-a.bottom}},updateFgSegCoords:function(a){this.computeSegVerticals(a),this.computeFgSegHorizontals(a),this.assignSegVerticals(a),this.assignFgSegHorizontals(a)},computeFgSegHorizontals:function(a){var b,c,d;if(this.sortEventSegs(a),b=La(a),Ma(b),c=b[0]){for(d=0;d<c.length;d++)Na(c[d]);for(d=0;d<c.length;d++)this.computeFgSegForwardBack(c[d],0,0)}},computeFgSegForwardBack:function(a,b,c){var d,e=a.forwardSegs;if(void 0===a.forwardCoord)for(e.length?(this.sortForwardSegs(e),this.computeFgSegForwardBack(e[0],b+1,c),a.forwardCoord=e[0].backwardCoord):a.forwardCoord=1,a.backwardCoord=a.forwardCoord-(a.forwardCoord-c)/(b+1),d=0;d<e.length;d++)this.computeFgSegForwardBack(e[d],0,a.forwardCoord)},sortForwardSegs:function(a){a.sort(ia(this,"compareForwardSegs"))},compareForwardSegs:function(a,b){return b.forwardPressure-a.forwardPressure||(a.backwardCoord||0)-(b.backwardCoord||0)||this.compareEventSegs(a,b)},assignFgSegHorizontals:function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.el.css(this.generateFgSegHorizontalCss(c)),c.bottom-c.top<30&&c.el.addClass("fc-short")},generateFgSegHorizontalCss:function(a){var b,c,d=this.view.opt("slotEventOverlap"),e=a.backwardCoord,f=a.forwardCoord,g=this.generateSegVerticalCss(a);return d&&(f=Math.min(1,e+2*(f-e))),this.isRTL?(b=1-f,c=e):(b=e,c=1-f),g.zIndex=a.level+1,g.left=100*b+"%",g.right=100*c+"%",d&&a.forwardPressure&&(g[this.isRTL?"marginLeft":"marginRight"]=20),g}});var xb=Wa.View=ya.extend(lb,mb,{type:null,name:null,title:null,calendar:null,options:null,el:null,displaying:null,isSkeletonRendered:!1,isEventsRendered:!1,start:null,end:null,intervalStart:null,intervalEnd:null,intervalDuration:null,intervalUnit:null,isRTL:!1,isSelected:!1,selectedEvent:null,eventOrderSpecs:null,widgetHeaderClass:null,widgetContentClass:null,highlightStateClass:null,nextDayThreshold:null,isHiddenDayHash:null,isNowIndicatorRendered:null,initialNowDate:null,initialNowQueriedMs:null,nowIndicatorTimeoutID:null,nowIndicatorIntervalID:null,constructor:function(a,c,d,e){this.calendar=a,this.type=this.name=c,this.options=d,this.intervalDuration=e||b.duration(1,"day"),this.nextDayThreshold=b.duration(this.opt("nextDayThreshold")),this.initThemingProps(),this.initHiddenDays(),this.isRTL=this.opt("isRTL"),this.eventOrderSpecs=G(this.opt("eventOrder")),this.initialize()},initialize:function(){},opt:function(a){return this.options[a]},trigger:function(a,b){var c=this.calendar;return c.trigger.apply(c,[a,b||this].concat(Array.prototype.slice.call(arguments,2),[this]))},setDate:function(a){this.setRange(this.computeRange(a))},setRange:function(b){a.extend(this,b),this.updateTitle()},computeRange:function(a){var b,c,d=O(this.intervalDuration),e=a.clone().startOf(d),f=e.clone().add(this.intervalDuration);return/year|month|week|day/.test(d)?(e.stripTime(),f.stripTime()):(e.hasTime()||(e=this.calendar.time(0)),f.hasTime()||(f=this.calendar.time(0))),b=e.clone(),b=this.skipHiddenDays(b),c=f.clone(),c=this.skipHiddenDays(c,-1,!0),{intervalUnit:d,intervalStart:e,intervalEnd:f,start:b,end:c}},computePrevDate:function(a){return this.massageCurrentDate(a.clone().startOf(this.intervalUnit).subtract(this.intervalDuration),-1)},computeNextDate:function(a){return this.massageCurrentDate(a.clone().startOf(this.intervalUnit).add(this.intervalDuration))},massageCurrentDate:function(a,b){return this.intervalDuration.as("days")<=1&&this.isHiddenDay(a)&&(a=this.skipHiddenDays(a,b),a.startOf("day")),a},updateTitle:function(){this.title=this.computeTitle()},computeTitle:function(){return this.formatRange({start:this.calendar.applyTimezone(this.intervalStart),end:this.calendar.applyTimezone(this.intervalEnd)},this.opt("titleFormat")||this.computeTitleFormat(),this.opt("titleRangeSeparator"))},computeTitleFormat:function(){return"year"==this.intervalUnit?"YYYY":"month"==this.intervalUnit?this.opt("monthYearFormat"):this.intervalDuration.as("days")>1?"ll":"LL"},formatRange:function(a,b,c){var d=a.end;return d.hasTime()||(d=d.clone().subtract(1)),ta(a.start,d,b,c,this.opt("isRTL"))},setElement:function(a){this.el=a,this.bindGlobalHandlers()},removeElement:function(){this.clear(),this.isSkeletonRendered&&(this.unrenderSkeleton(),this.isSkeletonRendered=!1),this.unbindGlobalHandlers(),this.el.remove()},display:function(a){var b=this,c=null;return this.displaying&&(c=this.queryScroll()),this.calendar.freezeContentHeight(),ka(this.clear(),function(){return b.displaying=ka(b.displayView(a),function(){b.forceScroll(b.computeInitialScroll(c)),b.calendar.unfreezeContentHeight(),b.triggerRender()})})},clear:function(){var b=this,c=this.displaying;return c?ka(c,function(){return b.displaying=null,b.clearEvents(),b.clearView()}):a.when()},displayView:function(a){this.isSkeletonRendered||(this.renderSkeleton(),this.isSkeletonRendered=!0),a&&this.setDate(a),this.render&&this.render(),this.renderDates(),this.updateSize(),this.renderBusinessHours(),this.startNowIndicator()},clearView:function(){this.unselect(),this.stopNowIndicator(),this.triggerUnrender(),this.unrenderBusinessHours(),this.unrenderDates(),this.destroy&&this.destroy()},renderSkeleton:function(){},unrenderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},triggerRender:function(){this.trigger("viewRender",this,this,this.el)},triggerUnrender:function(){this.trigger("viewDestroy",this,this,this.el)},bindGlobalHandlers:function(){this.listenTo(a(document),"mousedown",this.handleDocumentMousedown),this.listenTo(a(document),"touchstart",this.processUnselect)},unbindGlobalHandlers:function(){this.stopListeningTo(a(document))},initThemingProps:function(){var a=this.opt("theme")?"ui":"fc";this.widgetHeaderClass=a+"-widget-header",this.widgetContentClass=a+"-widget-content",this.highlightStateClass=a+"-state-highlight"},renderBusinessHours:function(){},unrenderBusinessHours:function(){},startNowIndicator:function(){var a,c,d,e=this;this.opt("nowIndicator")&&(a=this.getNowIndicatorUnit(),a&&(c=ia(this,"updateNowIndicator"),this.initialNowDate=this.calendar.getNow(),this.initialNowQueriedMs=+new Date,this.renderNowIndicator(this.initialNowDate),this.isNowIndicatorRendered=!0,d=this.initialNowDate.clone().startOf(a).add(1,a)-this.initialNowDate,this.nowIndicatorTimeoutID=setTimeout(function(){e.nowIndicatorTimeoutID=null,c(),d=+b.duration(1,a),d=Math.max(100,d),e.nowIndicatorIntervalID=setInterval(c,d)},d)))},updateNowIndicator:function(){this.isNowIndicatorRendered&&(this.unrenderNowIndicator(),this.renderNowIndicator(this.initialNowDate.clone().add(new Date-this.initialNowQueriedMs)))},stopNowIndicator:function(){this.isNowIndicatorRendered&&(this.nowIndicatorTimeoutID&&(clearTimeout(this.nowIndicatorTimeoutID),this.nowIndicatorTimeoutID=null),this.nowIndicatorIntervalID&&(clearTimeout(this.nowIndicatorIntervalID),this.nowIndicatorIntervalID=null),this.unrenderNowIndicator(),this.isNowIndicatorRendered=!1)},getNowIndicatorUnit:function(){},renderNowIndicator:function(a){},unrenderNowIndicator:function(){},updateSize:function(a){var b;a&&(b=this.queryScroll()),this.updateHeight(a),this.updateWidth(a),this.updateNowIndicator(),a&&this.setScroll(b)},updateWidth:function(a){},updateHeight:function(a){var b=this.calendar;this.setHeight(b.getSuggestedViewHeight(),b.isHeightAuto())},setHeight:function(a,b){},computeInitialScroll:function(a){return 0},queryScroll:function(){},setScroll:function(a){},forceScroll:function(a){var b=this;this.setScroll(a),setTimeout(function(){b.setScroll(a)},0)},displayEvents:function(a){var b=this.queryScroll();this.clearEvents(),this.renderEvents(a),this.isEventsRendered=!0,this.setScroll(b),this.triggerEventRender()},clearEvents:function(){var a;this.isEventsRendered&&(a=this.queryScroll(),this.triggerEventUnrender(),this.destroyEvents&&this.destroyEvents(),this.unrenderEvents(),this.setScroll(a),this.isEventsRendered=!1)},renderEvents:function(a){},unrenderEvents:function(){},triggerEventRender:function(){this.renderedEventSegEach(function(a){this.trigger("eventAfterRender",a.event,a.event,a.el)}),this.trigger("eventAfterAllRender")},triggerEventUnrender:function(){this.renderedEventSegEach(function(a){this.trigger("eventDestroy",a.event,a.event,a.el)})},resolveEventEl:function(b,c){var d=this.trigger("eventRender",b,b,c);return d===!1?c=null:d&&d!==!0&&(c=a(d)),c},showEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","")},a)},hideEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","hidden")},a)},renderedEventSegEach:function(a,b){var c,d=this.getEventSegs();for(c=0;c<d.length;c++)b&&d[c].event._id!==b._id||d[c].el&&a.call(this,d[c])},getEventSegs:function(){return[]},isEventDraggable:function(a){var b=a.source||{};return ba(a.startEditable,b.startEditable,this.opt("eventStartEditable"),a.editable,b.editable,this.opt("editable"))},reportEventDrop:function(a,b,c,d,e){var f=this.calendar,g=f.mutateEvent(a,b,c),h=function(){g.undo(),f.reportEventChange()};this.triggerEventDrop(a,g.dateDelta,h,d,e),f.reportEventChange()},triggerEventDrop:function(a,b,c,d,e){this.trigger("eventDrop",d[0],a,b,c,e,{})},reportExternalDrop:function(b,c,d,e,f){var g,h,i=b.eventProps;i&&(g=a.extend({},i,c),h=this.calendar.renderEvent(g,b.stick)[0]),this.triggerExternalDrop(h,c,d,e,f)},triggerExternalDrop:function(a,b,c,d,e){this.trigger("drop",c[0],b.start,d,e),a&&this.trigger("eventReceive",null,a)},renderDrag:function(a,b){},unrenderDrag:function(){},isEventResizableFromStart:function(a){return this.opt("eventResizableFromStart")&&this.isEventResizable(a)},isEventResizableFromEnd:function(a){return this.isEventResizable(a)},isEventResizable:function(a){var b=a.source||{};return ba(a.durationEditable,b.durationEditable,this.opt("eventDurationEditable"),a.editable,b.editable,this.opt("editable"))},reportEventResize:function(a,b,c,d,e){var f=this.calendar,g=f.mutateEvent(a,b,c),h=function(){g.undo(), +f.reportEventChange()};this.triggerEventResize(a,g.durationDelta,h,d,e),f.reportEventChange()},triggerEventResize:function(a,b,c,d,e){this.trigger("eventResize",d[0],a,b,c,e,{})},select:function(a,b){this.unselect(b),this.renderSelection(a),this.reportSelection(a,b)},renderSelection:function(a){},reportSelection:function(a,b){this.isSelected=!0,this.triggerSelect(a,b)},triggerSelect:function(a,b){this.trigger("select",null,this.calendar.applyTimezone(a.start),this.calendar.applyTimezone(a.end),b)},unselect:function(a){this.isSelected&&(this.isSelected=!1,this.destroySelection&&this.destroySelection(),this.unrenderSelection(),this.trigger("unselect",null,a))},unrenderSelection:function(){},selectEvent:function(a){this.selectedEvent&&this.selectedEvent===a||(this.unselectEvent(),this.renderedEventSegEach(function(a){a.el.addClass("fc-selected")},a),this.selectedEvent=a)},unselectEvent:function(){this.selectedEvent&&(this.renderedEventSegEach(function(a){a.el.removeClass("fc-selected")},this.selectedEvent),this.selectedEvent=null)},isEventSelected:function(a){return this.selectedEvent&&this.selectedEvent._id===a._id},handleDocumentMousedown:function(a){u(a)&&this.processUnselect(a)},processUnselect:function(a){this.processRangeUnselect(a),this.processEventUnselect(a)},processRangeUnselect:function(b){var c;this.isSelected&&this.opt("unselectAuto")&&(c=this.opt("unselectCancel"),c&&a(b.target).closest(c).length||this.unselect(b))},processEventUnselect:function(b){this.selectedEvent&&(a(b.target).closest(".fc-selected").length||this.unselectEvent())},triggerDayClick:function(a,b,c){this.trigger("dayClick",b,this.calendar.applyTimezone(a.start),c)},initHiddenDays:function(){var b,c=this.opt("hiddenDays")||[],d=[],e=0;for(this.opt("weekends")===!1&&c.push(0,6),b=0;7>b;b++)(d[b]=-1!==a.inArray(b,c))||e++;if(!e)throw"invalid hiddenDays";this.isHiddenDayHash=d},isHiddenDay:function(a){return b.isMoment(a)&&(a=a.day()),this.isHiddenDayHash[a]},skipHiddenDays:function(a,b,c){var d=a.clone();for(b=b||1;this.isHiddenDayHash[(d.day()+(c?b:0)+7)%7];)d.add(b,"days");return d},computeDayRange:function(a){var b,c=a.start.clone().stripTime(),d=a.end,e=null;return d&&(e=d.clone().stripTime(),b=+d.time(),b&&b>=this.nextDayThreshold&&e.add(1,"days")),(!d||c>=e)&&(e=c.clone().add(1,"days")),{start:c,end:e}},isMultiDayEvent:function(a){var b=this.computeDayRange(a);return b.end.diff(b.start,"days")>1}}),yb=Wa.Scroller=ya.extend({el:null,scrollEl:null,overflowX:null,overflowY:null,constructor:function(a){a=a||{},this.overflowX=a.overflowX||a.overflow||"auto",this.overflowY=a.overflowY||a.overflow||"auto"},render:function(){this.el=this.renderEl(),this.applyOverflow()},renderEl:function(){return this.scrollEl=a('<div class="fc-scroller"></div>')},clear:function(){this.setHeight("auto"),this.applyOverflow()},destroy:function(){this.el.remove()},applyOverflow:function(){this.scrollEl.css({"overflow-x":this.overflowX,"overflow-y":this.overflowY})},lockOverflow:function(a){var b=this.overflowX,c=this.overflowY;a=a||this.getScrollbarWidths(),"auto"===b&&(b=a.top||a.bottom||this.scrollEl[0].scrollWidth-1>this.scrollEl[0].clientWidth?"scroll":"hidden"),"auto"===c&&(c=a.left||a.right||this.scrollEl[0].scrollHeight-1>this.scrollEl[0].clientHeight?"scroll":"hidden"),this.scrollEl.css({"overflow-x":b,"overflow-y":c})},setHeight:function(a){this.scrollEl.height(a)},getScrollTop:function(){return this.scrollEl.scrollTop()},setScrollTop:function(a){this.scrollEl.scrollTop(a)},getClientWidth:function(){return this.scrollEl[0].clientWidth},getClientHeight:function(){return this.scrollEl[0].clientHeight},getScrollbarWidths:function(){return q(this.scrollEl)}}),zb=Wa.Calendar=ya.extend({dirDefaults:null,langDefaults:null,overrides:null,options:null,viewSpecCache:null,view:null,header:null,loadingLevel:0,constructor:Qa,initialize:function(){},initOptions:function(a){var b,e,f,g;a=d(a),b=a.lang,e=Ab[b],e||(b=zb.defaults.lang,e=Ab[b]||{}),f=ba(a.isRTL,e.isRTL,zb.defaults.isRTL),g=f?zb.rtlDefaults:{},this.dirDefaults=g,this.langDefaults=e,this.overrides=a,this.options=c([zb.defaults,g,e,a]),Ra(this.options),this.viewSpecCache={}},getViewSpec:function(a){var b=this.viewSpecCache;return b[a]||(b[a]=this.buildViewSpec(a))},getUnitViewSpec:function(b){var c,d,e;if(-1!=a.inArray(b,_a))for(c=this.header.getViewsWithButtons(),a.each(Wa.views,function(a){c.push(a)}),d=0;d<c.length;d++)if(e=this.getViewSpec(c[d]),e&&e.singleUnit==b)return e},buildViewSpec:function(a){for(var d,e,f,g,h=this.overrides.views||{},i=[],j=[],k=[],l=a;l;)d=Xa[l],e=h[l],l=null,"function"==typeof d&&(d={"class":d}),d&&(i.unshift(d),j.unshift(d.defaults||{}),f=f||d.duration,l=l||d.type),e&&(k.unshift(e),f=f||e.duration,l=l||e.type);return d=W(i),d.type=a,d["class"]?(f&&(f=b.duration(f),f.valueOf()&&(d.duration=f,g=O(f),1===f.as(g)&&(d.singleUnit=g,k.unshift(h[g]||{})))),d.defaults=c(j),d.overrides=c(k),this.buildViewSpecOptions(d),this.buildViewSpecButtonText(d,a),d):!1},buildViewSpecOptions:function(a){a.options=c([zb.defaults,a.defaults,this.dirDefaults,this.langDefaults,this.overrides,a.overrides]),Ra(a.options)},buildViewSpecButtonText:function(a,b){function c(c){var d=c.buttonText||{};return d[b]||(a.singleUnit?d[a.singleUnit]:null)}a.buttonTextOverride=c(this.overrides)||a.overrides.buttonText,a.buttonTextDefault=c(this.langDefaults)||c(this.dirDefaults)||a.defaults.buttonText||c(zb.defaults)||(a.duration?this.humanizeDuration(a.duration):null)||b},instantiateView:function(a){var b=this.getViewSpec(a);return new b["class"](this,a,b.options,b.duration)},isValidViewType:function(a){return Boolean(this.getViewSpec(a))},pushLoading:function(){this.loadingLevel++||this.trigger("loading",null,!0,this.view)},popLoading:function(){--this.loadingLevel||this.trigger("loading",null,!1,this.view)},buildSelectSpan:function(a,b){var c,d=this.moment(a).stripZone();return c=b?this.moment(b).stripZone():d.hasTime()?d.clone().add(this.defaultTimedEventDuration):d.clone().add(this.defaultAllDayEventDuration),{start:d,end:c}}});zb.mixin(lb),zb.defaults={titleRangeSeparator:" – ",monthYearFormat:"MMMM YYYY",defaultTimedEventDuration:"02:00:00",defaultAllDayEventDuration:{days:1},forceEventDuration:!1,nextDayThreshold:"09:00:00",defaultView:"month",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberTitle:"W",weekNumberCalculation:"local",scrollTime:"06:00:00",lazyFetching:!0,startParam:"start",endParam:"end",timezoneParam:"timezone",timezone:!1,isRTL:!1,buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day"},buttonIcons:{prev:"left-single-arrow",next:"right-single-arrow",prevYear:"left-double-arrow",nextYear:"right-double-arrow"},theme:!1,themeButtonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e",prevYear:"seek-prev",nextYear:"seek-next"},dragOpacity:.75,dragRevertDuration:500,dragScroll:!0,unselectAuto:!0,dropAccept:"*",eventOrder:"title",eventLimit:!1,eventLimitText:"more",eventLimitClick:"popover",dayPopoverFormat:"LL",handleWindowResize:!0,windowResizeDelay:200,longPressDelay:1e3},zb.englishDefaults={dayPopoverFormat:"dddd, MMMM D"},zb.rtlDefaults={header:{left:"next,prev today",center:"",right:"title"},buttonIcons:{prev:"right-single-arrow",next:"left-single-arrow",prevYear:"right-double-arrow",nextYear:"left-double-arrow"},themeButtonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w",nextYear:"seek-prev",prevYear:"seek-next"}};var Ab=Wa.langs={};Wa.datepickerLang=function(b,c,d){var e=Ab[b]||(Ab[b]={});e.isRTL=d.isRTL,e.weekNumberTitle=d.weekHeader,a.each(Bb,function(a,b){e[a]=b(d)}),a.datepicker&&(a.datepicker.regional[c]=a.datepicker.regional[b]=d,a.datepicker.regional.en=a.datepicker.regional[""],a.datepicker.setDefaults(d))},Wa.lang=function(b,d){var e,f;e=Ab[b]||(Ab[b]={}),d&&(e=Ab[b]=c([e,d])),f=Sa(b),a.each(Cb,function(a,b){null==e[a]&&(e[a]=b(f,e))}),zb.defaults.lang=b};var Bb={buttonText:function(a){return{prev:da(a.prevText),next:da(a.nextText),today:da(a.currentText)}},monthYearFormat:function(a){return a.showMonthAfterYear?"YYYY["+a.yearSuffix+"] MMMM":"MMMM YYYY["+a.yearSuffix+"]"}},Cb={dayOfMonthFormat:function(a,b){var c=a.longDateFormat("l");return c=c.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g,""),b.isRTL?c+=" ddd":c="ddd "+c,c},mediumTimeFormat:function(a){return a.longDateFormat("LT").replace(/\s*a$/i,"a")},smallTimeFormat:function(a){return a.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"a")},extraSmallTimeFormat:function(a){return a.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"t")},hourFormat:function(a){return a.longDateFormat("LT").replace(":mm","").replace(/(\Wmm)$/,"").replace(/\s*a$/i,"a")},noMeridiemTimeFormat:function(a){return a.longDateFormat("LT").replace(/\s*a$/i,"")}},Db={smallDayDateFormat:function(a){return a.isRTL?"D dd":"dd D"},weekFormat:function(a){return a.isRTL?"w[ "+a.weekNumberTitle+"]":"["+a.weekNumberTitle+" ]w"},smallWeekFormat:function(a){return a.isRTL?"w["+a.weekNumberTitle+"]":"["+a.weekNumberTitle+"]w"}};Wa.lang("en",zb.englishDefaults),Wa.sourceNormalizers=[],Wa.sourceFetchers=[];var Eb={dataType:"json",cache:!1},Fb=1;zb.prototype.normalizeEvent=function(a){},zb.prototype.getPeerEvents=function(a,b){var c,d,e=this.getEventCache(),f=[];for(c=0;c<e.length;c++)d=e[c],b&&b._id===d._id||f.push(d);return f};var Gb=Wa.BasicView=xb.extend({scroller:null,dayGridClass:vb,dayGrid:null,dayNumbersVisible:!1,weekNumbersVisible:!1,weekNumberWidth:null,headContainerEl:null,headRowEl:null,initialize:function(){this.dayGrid=this.instantiateDayGrid(),this.scroller=new yb({overflowX:"hidden",overflowY:"auto"})},instantiateDayGrid:function(){var a=this.dayGridClass.extend(Hb);return new a(this)},setRange:function(a){xb.prototype.setRange.call(this,a),this.dayGrid.breakOnWeeks=/year|month|week/.test(this.intervalUnit),this.dayGrid.setRange(a)},computeRange:function(a){var b=xb.prototype.computeRange.call(this,a);return/year|month/.test(b.intervalUnit)&&(b.start.startOf("week"),b.start=this.skipHiddenDays(b.start),b.end.weekday()&&(b.end.add(1,"week").startOf("week"),b.end=this.skipHiddenDays(b.end,-1,!0))),b},renderDates:function(){this.dayNumbersVisible=this.dayGrid.rowCnt>1,this.weekNumbersVisible=this.opt("weekNumbers"),this.dayGrid.numbersVisible=this.dayNumbersVisible||this.weekNumbersVisible,this.el.addClass("fc-basic-view").html(this.renderSkeletonHtml()),this.renderHead(),this.scroller.render();var b=this.scroller.el.addClass("fc-day-grid-container"),c=a('<div class="fc-day-grid" />').appendTo(b);this.el.find(".fc-body > tr > td").append(b),this.dayGrid.setElement(c),this.dayGrid.renderDates(this.hasRigidRows())},renderHead:function(){this.headContainerEl=this.el.find(".fc-head-container").html(this.dayGrid.renderHeadHtml()),this.headRowEl=this.headContainerEl.find(".fc-row")},unrenderDates:function(){this.dayGrid.unrenderDates(),this.dayGrid.removeElement(),this.scroller.destroy()},renderBusinessHours:function(){this.dayGrid.renderBusinessHours()},renderSkeletonHtml:function(){return'<table><thead class="fc-head"><tr><td class="fc-head-container '+this.widgetHeaderClass+'"></td></tr></thead><tbody class="fc-body"><tr><td class="'+this.widgetContentClass+'"></td></tr></tbody></table>'},weekNumberStyleAttr:function(){return null!==this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},hasRigidRows:function(){var a=this.opt("eventLimit");return a&&"number"!=typeof a},updateWidth:function(){this.weekNumbersVisible&&(this.weekNumberWidth=k(this.el.find(".fc-week-number")))},setHeight:function(a,b){var c,d,g=this.opt("eventLimit");this.scroller.clear(),f(this.headRowEl),this.dayGrid.removeSegPopover(),g&&"number"==typeof g&&this.dayGrid.limitRows(g),c=this.computeScrollerHeight(a),this.setGridHeight(c,b),g&&"number"!=typeof g&&this.dayGrid.limitRows(g),b||(this.scroller.setHeight(c),d=this.scroller.getScrollbarWidths(),(d.left||d.right)&&(e(this.headRowEl,d),c=this.computeScrollerHeight(a),this.scroller.setHeight(c)),this.scroller.lockOverflow(d))},computeScrollerHeight:function(a){return a-l(this.el,this.scroller.el)},setGridHeight:function(a,b){b?j(this.dayGrid.rowEls):i(this.dayGrid.rowEls,a,!0)},queryScroll:function(){return this.scroller.getScrollTop()},setScroll:function(a){this.scroller.setScrollTop(a)},prepareHits:function(){this.dayGrid.prepareHits()},releaseHits:function(){this.dayGrid.releaseHits()},queryHit:function(a,b){return this.dayGrid.queryHit(a,b)},getHitSpan:function(a){return this.dayGrid.getHitSpan(a)},getHitEl:function(a){return this.dayGrid.getHitEl(a)},renderEvents:function(a){this.dayGrid.renderEvents(a),this.updateHeight()},getEventSegs:function(){return this.dayGrid.getEventSegs()},unrenderEvents:function(){this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return this.dayGrid.renderDrag(a,b)},unrenderDrag:function(){this.dayGrid.unrenderDrag()},renderSelection:function(a){this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.dayGrid.unrenderSelection()}}),Hb={renderHeadIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?'<th class="fc-week-number '+a.widgetHeaderClass+'" '+a.weekNumberStyleAttr()+"><span>"+ca(a.opt("weekNumberTitle"))+"</span></th>":""},renderNumberIntroHtml:function(a){var b=this.view;return b.weekNumbersVisible?'<td class="fc-week-number" '+b.weekNumberStyleAttr()+"><span>"+this.getCellDate(a,0).format("w")+"</span></td>":""},renderBgIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?'<td class="fc-week-number '+a.widgetContentClass+'" '+a.weekNumberStyleAttr()+"></td>":""},renderIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?'<td class="fc-week-number" '+a.weekNumberStyleAttr()+"></td>":""}},Ib=Wa.MonthView=Gb.extend({computeRange:function(a){var b,c=Gb.prototype.computeRange.call(this,a);return this.isFixedWeeks()&&(b=Math.ceil(c.end.diff(c.start,"weeks",!0)),c.end.add(6-b,"weeks")),c},setGridHeight:function(a,b){b=b||"variable"===this.opt("weekMode"),b&&(a*=this.rowCnt/6),i(this.dayGrid.rowEls,a,!b)},isFixedWeeks:function(){var a=this.opt("weekMode");return a?"fixed"===a:this.opt("fixedWeekCount")}});Xa.basic={"class":Gb},Xa.basicDay={type:"basic",duration:{days:1}},Xa.basicWeek={type:"basic",duration:{weeks:1}},Xa.month={"class":Ib,duration:{months:1},defaults:{fixedWeekCount:!0}};var Jb=Wa.AgendaView=xb.extend({scroller:null,timeGridClass:wb,timeGrid:null,dayGridClass:vb,dayGrid:null,axisWidth:null,headContainerEl:null,noScrollRowEls:null,bottomRuleEl:null,initialize:function(){this.timeGrid=this.instantiateTimeGrid(),this.opt("allDaySlot")&&(this.dayGrid=this.instantiateDayGrid()),this.scroller=new yb({overflowX:"hidden",overflowY:"auto"})},instantiateTimeGrid:function(){var a=this.timeGridClass.extend(Kb);return new a(this)},instantiateDayGrid:function(){var a=this.dayGridClass.extend(Lb);return new a(this)},setRange:function(a){xb.prototype.setRange.call(this,a),this.timeGrid.setRange(a),this.dayGrid&&this.dayGrid.setRange(a)},renderDates:function(){this.el.addClass("fc-agenda-view").html(this.renderSkeletonHtml()),this.renderHead(),this.scroller.render();var b=this.scroller.el.addClass("fc-time-grid-container"),c=a('<div class="fc-time-grid" />').appendTo(b);this.el.find(".fc-body > tr > td").append(b),this.timeGrid.setElement(c),this.timeGrid.renderDates(),this.bottomRuleEl=a('<hr class="fc-divider '+this.widgetHeaderClass+'"/>').appendTo(this.timeGrid.el),this.dayGrid&&(this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.renderDates(),this.dayGrid.bottomCoordPadding=this.dayGrid.el.next("hr").outerHeight()),this.noScrollRowEls=this.el.find(".fc-row:not(.fc-scroller *)")},renderHead:function(){this.headContainerEl=this.el.find(".fc-head-container").html(this.timeGrid.renderHeadHtml())},unrenderDates:function(){this.timeGrid.unrenderDates(),this.timeGrid.removeElement(),this.dayGrid&&(this.dayGrid.unrenderDates(),this.dayGrid.removeElement()),this.scroller.destroy()},renderSkeletonHtml:function(){return'<table><thead class="fc-head"><tr><td class="fc-head-container '+this.widgetHeaderClass+'"></td></tr></thead><tbody class="fc-body"><tr><td class="'+this.widgetContentClass+'">'+(this.dayGrid?'<div class="fc-day-grid"/><hr class="fc-divider '+this.widgetHeaderClass+'"/>':"")+"</td></tr></tbody></table>"},axisStyleAttr:function(){return null!==this.axisWidth?'style="width:'+this.axisWidth+'px"':""},renderBusinessHours:function(){this.timeGrid.renderBusinessHours(),this.dayGrid&&this.dayGrid.renderBusinessHours()},unrenderBusinessHours:function(){this.timeGrid.unrenderBusinessHours(),this.dayGrid&&this.dayGrid.unrenderBusinessHours()},getNowIndicatorUnit:function(){return this.timeGrid.getNowIndicatorUnit()},renderNowIndicator:function(a){this.timeGrid.renderNowIndicator(a)},unrenderNowIndicator:function(){this.timeGrid.unrenderNowIndicator()},updateSize:function(a){this.timeGrid.updateSize(a),xb.prototype.updateSize.call(this,a)},updateWidth:function(){this.axisWidth=k(this.el.find(".fc-axis"))},setHeight:function(a,b){var c,d,g;this.bottomRuleEl.hide(),this.scroller.clear(),f(this.noScrollRowEls),this.dayGrid&&(this.dayGrid.removeSegPopover(),c=this.opt("eventLimit"),c&&"number"!=typeof c&&(c=Mb),c&&this.dayGrid.limitRows(c)),b||(d=this.computeScrollerHeight(a),this.scroller.setHeight(d),g=this.scroller.getScrollbarWidths(),(g.left||g.right)&&(e(this.noScrollRowEls,g),d=this.computeScrollerHeight(a),this.scroller.setHeight(d)),this.scroller.lockOverflow(g),this.timeGrid.getTotalSlatHeight()<d&&this.bottomRuleEl.show())},computeScrollerHeight:function(a){return a-l(this.el,this.scroller.el)},computeInitialScroll:function(){var a=b.duration(this.opt("scrollTime")),c=this.timeGrid.computeTimeTop(a);return c=Math.ceil(c),c&&c++,c},queryScroll:function(){return this.scroller.getScrollTop()},setScroll:function(a){this.scroller.setScrollTop(a)},prepareHits:function(){this.timeGrid.prepareHits(),this.dayGrid&&this.dayGrid.prepareHits()},releaseHits:function(){this.timeGrid.releaseHits(),this.dayGrid&&this.dayGrid.releaseHits()},queryHit:function(a,b){var c=this.timeGrid.queryHit(a,b);return!c&&this.dayGrid&&(c=this.dayGrid.queryHit(a,b)),c},getHitSpan:function(a){return a.component.getHitSpan(a)},getHitEl:function(a){return a.component.getHitEl(a)},renderEvents:function(a){var b,c,d=[],e=[],f=[];for(c=0;c<a.length;c++)a[c].allDay?d.push(a[c]):e.push(a[c]);b=this.timeGrid.renderEvents(e),this.dayGrid&&(f=this.dayGrid.renderEvents(d)),this.updateHeight()},getEventSegs:function(){return this.timeGrid.getEventSegs().concat(this.dayGrid?this.dayGrid.getEventSegs():[])},unrenderEvents:function(){this.timeGrid.unrenderEvents(),this.dayGrid&&this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return a.start.hasTime()?this.timeGrid.renderDrag(a,b):this.dayGrid?this.dayGrid.renderDrag(a,b):void 0},unrenderDrag:function(){this.timeGrid.unrenderDrag(),this.dayGrid&&this.dayGrid.unrenderDrag()},renderSelection:function(a){a.start.hasTime()||a.end.hasTime()?this.timeGrid.renderSelection(a):this.dayGrid&&this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.timeGrid.unrenderSelection(),this.dayGrid&&this.dayGrid.unrenderSelection()}}),Kb={renderHeadIntroHtml:function(){var a,b=this.view;return b.opt("weekNumbers")?(a=this.start.format(b.opt("smallWeekFormat")),'<th class="fc-axis fc-week-number '+b.widgetHeaderClass+'" '+b.axisStyleAttr()+"><span>"+ca(a)+"</span></th>"):'<th class="fc-axis '+b.widgetHeaderClass+'" '+b.axisStyleAttr()+"></th>"},renderBgIntroHtml:function(){var a=this.view;return'<td class="fc-axis '+a.widgetContentClass+'" '+a.axisStyleAttr()+"></td>"},renderIntroHtml:function(){var a=this.view;return'<td class="fc-axis" '+a.axisStyleAttr()+"></td>"}},Lb={renderBgIntroHtml:function(){var a=this.view;return'<td class="fc-axis '+a.widgetContentClass+'" '+a.axisStyleAttr()+"><span>"+(a.opt("allDayHtml")||ca(a.opt("allDayText")))+"</span></td>"},renderIntroHtml:function(){var a=this.view;return'<td class="fc-axis" '+a.axisStyleAttr()+"></td>"}},Mb=5,Nb=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}];return Xa.agenda={"class":Jb,defaults:{allDaySlot:!0,allDayText:"all-day",slotDuration:"00:30:00",minTime:"00:00:00",maxTime:"24:00:00",slotEventOverlap:!0}},Xa.agendaDay={type:"agenda",duration:{days:1}},Xa.agendaWeek={type:"agenda",duration:{weeks:1}},Wa}); \ No newline at end of file diff --git a/library/fullcalendar/fullcalendar.print.css b/library/fullcalendar/fullcalendar.print.css index 11b823f74..83d11563b 100644 --- a/library/fullcalendar/fullcalendar.print.css +++ b/library/fullcalendar/fullcalendar.print.css @@ -1,5 +1,5 @@ /*! - * FullCalendar v2.7.3 Print Stylesheet + * FullCalendar v2.8.0 Print Stylesheet * Docs & License: http://fullcalendar.io/ * (c) 2016 Adam Shaw */ diff --git a/library/fullcalendar/gcal.js b/library/fullcalendar/gcal.js index 58b85c195..1d6b91c5b 100644 --- a/library/fullcalendar/gcal.js +++ b/library/fullcalendar/gcal.js @@ -1,5 +1,5 @@ /*! - * FullCalendar v2.7.3 Google Calendar Plugin + * FullCalendar v2.8.0 Google Calendar Plugin * Docs & License: http://fullcalendar.io/ * (c) 2016 Adam Shaw */ diff --git a/library/fullcalendar/lang-all.js b/library/fullcalendar/lang-all.js index 7d7e25192..dc7577063 100644 --- a/library/fullcalendar/lang-all.js +++ b/library/fullcalendar/lang-all.js @@ -1,4 +1,4 @@ !function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("moment")):a(jQuery,moment)}(function(a,b){!function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"ar-ma",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:6,doy:12}});return a}(),a.fullCalendar.datepickerLang("ar-ma","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ar-ma",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى"})}(),function(){!function(){"use strict";var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},c={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},d=(b.defineLocale||b.lang).call(b,"ar-sa",{months:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(a){return"م"===a},meridiem:function(a,b,c){return 12>a?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(a){return a.replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(a){return c[a]}).replace(/،/g,",")},postformat:function(b){return b.replace(/\d/g,function(b){return a[b]}).replace(/,/g,"،")},week:{dow:6,doy:12}});return d}(),a.fullCalendar.datepickerLang("ar-sa","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ar-sa",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"ar-tn",{months:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("ar-tn","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ar-tn",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى"})}(),function(){!function(){"use strict";var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},c={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},d=function(a){return 0===a?0:1===a?1:2===a?2:a%100>=3&&10>=a%100?3:a%100>=11?4:5},e={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},f=function(a){return function(b,c,f,g){var h=d(b),i=e[a][d(b)];return 2===h&&(i=i[c?0:1]),i.replace(/%d/i,b)}},g=["كانون الثاني يناير","شباط فبراير","آذار مارس","نيسان أبريل","أيار مايو","حزيران يونيو","تموز يوليو","آب أغسطس","أيلول سبتمبر","تشرين الأول أكتوبر","تشرين الثاني نوفمبر","كانون الأول ديسمبر"],h=(b.defineLocale||b.lang).call(b,"ar",{months:g,monthsShort:g,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(a){return"م"===a},meridiem:function(a,b,c){return 12>a?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:f("s"),m:f("m"),mm:f("m"),h:f("h"),hh:f("h"),d:f("d"),dd:f("d"),M:f("M"),MM:f("M"),y:f("y"),yy:f("y")},preparse:function(a){return a.replace(/\u200f/g,"").replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(a){return c[a]}).replace(/،/g,",")},postformat:function(b){return b.replace(/\d/g,function(b){return a[b]}).replace(/,/g,"،")},week:{dow:6,doy:12}});return h}(),a.fullCalendar.datepickerLang("ar","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ar",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"bg",{months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(a){var b=a%10,c=a%100;return 0===a?a+"-ев":0===c?a+"-ен":c>10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,doy:7}});return a}(),a.fullCalendar.datepickerLang("bg","bg",{closeText:"затвори",prevText:"<назад",nextText:"напред>",nextBigText:">>",currentText:"днес",monthNames:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthNamesShort:["Яну","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Нов","Дек"],dayNames:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота"],dayNamesShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб"],dayNamesMin:["Не","По","Вт","Ср","Че","Пе","Съ"],weekHeader:"Wk",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("bg",{buttonText:{month:"Месец",week:"Седмица",day:"Ден",list:"График"},allDayText:"Цял ден",eventLimitText:function(a){return"+още "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"ca",{months:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),monthsShort:"gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),monthsParseExact:!0,weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd D MMMM YYYY H:mm"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(a,b){var c=1===a?"r":2===a?"n":3===a?"r":4===a?"t":"è";return"w"!==b&&"W"!==b||(c="a"),a+c},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("ca","ca",{closeText:"Tanca",prevText:"Anterior",nextText:"Següent",currentText:"Avui",monthNames:["gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],monthNamesShort:["gen","feb","març","abr","maig","juny","jul","ag","set","oct","nov","des"],dayNames:["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],dayNamesShort:["dg","dl","dt","dc","dj","dv","ds"],dayNamesMin:["dg","dl","dt","dc","dj","dv","ds"],weekHeader:"Set",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ca",{buttonText:{month:"Mes",week:"Setmana",day:"Dia",list:"Agenda"},allDayText:"Tot el dia",eventLimitText:"més"})}(),function(){!function(){"use strict";function a(a){return a>1&&5>a&&1!==~~(a/10)}function c(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"pár sekund":"pár sekundami";case"m":return c?"minuta":e?"minutu":"minutou";case"mm":return c||e?f+(a(b)?"minuty":"minut"):f+"minutami";case"h":return c?"hodina":e?"hodinu":"hodinou";case"hh":return c||e?f+(a(b)?"hodiny":"hodin"):f+"hodinami";case"d":return c||e?"den":"dnem";case"dd":return c||e?f+(a(b)?"dny":"dní"):f+"dny";case"M":return c||e?"měsíc":"měsícem";case"MM":return c||e?f+(a(b)?"měsíce":"měsíců"):f+"měsíci";case"y":return c||e?"rok":"rokem";case"yy":return c||e?f+(a(b)?"roky":"let"):f+"lety"}}var d="leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),e="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_"),f=(b.defineLocale||b.lang).call(b,"cs",{months:d,monthsShort:e,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++)d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(d,e),shortMonthsParse:function(a){var b,c=[];for(b=0;12>b;b++)c[b]=new RegExp("^"+a[b]+"$","i");return c}(e),longMonthsParse:function(a){var b,c=[];for(b=0;12>b;b++)c[b]=new RegExp("^"+a[b]+"$","i");return c}(d),weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return f}(),a.fullCalendar.datepickerLang("cs","cs",{closeText:"Zavřít",prevText:"<Dříve",nextText:"Později>",currentText:"Nyní",monthNames:["leden","únor","březen","duben","květen","červen","červenec","srpen","září","říjen","listopad","prosinec"],monthNamesShort:["led","úno","bře","dub","kvě","čer","čvc","srp","zář","říj","lis","pro"],dayNames:["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],dayNamesShort:["ne","po","út","st","čt","pá","so"],dayNamesMin:["ne","po","út","st","čt","pá","so"],weekHeader:"Týd",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("cs",{buttonText:{month:"Měsíc",week:"Týden",day:"Den",list:"Agenda"},allDayText:"Celý den",eventLimitText:function(a){return"+další: "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd [d.] D. MMMM YYYY HH:mm"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("da","da",{closeText:"Luk",prevText:"<Forrige",nextText:"Næste>",currentText:"Idag",monthNames:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNames:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],dayNamesShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],dayNamesMin:["Sø","Ma","Ti","On","To","Fr","Lø"],weekHeader:"Uge",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("da",{buttonText:{month:"Måned",week:"Uge",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"flere"})}(),function(){!function(){"use strict";function a(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}var c=(b.defineLocale||b.lang).call(b,"de-at",{months:"Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return c}(),a.fullCalendar.datepickerLang("de-at","de",{closeText:"Schließen",prevText:"<Zurück",nextText:"Vor>",currentText:"Heute",monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNamesMin:["So","Mo","Di","Mi","Do","Fr","Sa"],weekHeader:"KW",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("de-at",{buttonText:{month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},allDayText:"Ganztägig",eventLimitText:function(a){return"+ weitere "+a}})}(),function(){!function(){"use strict";function a(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}var c=(b.defineLocale||b.lang).call(b,"de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return c}(),a.fullCalendar.datepickerLang("de","de",{closeText:"Schließen",prevText:"<Zurück",nextText:"Vor>",currentText:"Heute",monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNamesMin:["So","Mo","Di","Mi","Do","Fr","Sa"],weekHeader:"KW",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("de",{buttonText:{month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},allDayText:"Ganztägig",eventLimitText:function(a){return"+ weitere "+a}})}(),function(){!function(){"use strict";function a(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}var c=(b.defineLocale||b.lang).call(b,"el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(a,b){return/D/.test(b.substring(0,b.indexOf("MMMM")))?this._monthsGenitiveEl[a.month()]:this._monthsNominativeEl[a.month()]},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(a,b,c){return a>11?c?"μμ":"ΜΜ":c?"πμ":"ΠΜ"},isPM:function(a){return"μ"===(a+"").toLowerCase()[0]},meridiemParse:/[ΠΜ]\.?Μ?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:function(){switch(this.day()){case 6:return"[το προηγούμενο] dddd [{}] LT";default:return"[την προηγούμενη] dddd [{}] LT"}},sameElse:"L"},calendar:function(b,c){var d=this._calendarEl[b],e=c&&c.hours();return a(d)&&(d=d.apply(c)),d.replace("{}",e%12===1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"λίγα δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},ordinalParse:/\d{1,2}η/,ordinal:"%dη",week:{dow:1,doy:4}});return c}(),a.fullCalendar.datepickerLang("el","el",{closeText:"Κλείσιμο",prevText:"Προηγούμενος",nextText:"Επόμενος",currentText:"Σήμερα",monthNames:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthNamesShort:["Ιαν","Φεβ","Μαρ","Απρ","Μαι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],dayNames:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],dayNamesShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],dayNamesMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],weekHeader:"Εβδ",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("el",{buttonText:{month:"Μήνας",week:"Εβδομάδα",day:"Ημέρα",list:"Ατζέντα"},allDayText:"Ολοήμερο",eventLimitText:"περισσότερα"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("en-au","en-AU",{closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("en-au")}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"YYYY-MM-DD",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}});return a}(),a.fullCalendar.lang("en-ca")}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("en-gb","en-GB",{closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("en-gb")}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"en-ie",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}});return a}(),a.fullCalendar.lang("en-ie")}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"en-nz",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("en-nz","en-NZ",{closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("en-nz")}(),function(){!function(){"use strict";var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),c="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),d=(b.defineLocale||b.lang).call(b,"es",{ -months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(b,d){return/-MMM-/.test(d)?c[b.month()]:a[b.month()]},monthsParseExact:!0,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}});return d}(),a.fullCalendar.datepickerLang("es","es",{closeText:"Cerrar",prevText:"<Ant",nextText:"Sig>",currentText:"Hoy",monthNames:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],monthNamesShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],dayNames:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],dayNamesShort:["dom","lun","mar","mié","jue","vie","sáb"],dayNamesMin:["D","L","M","X","J","V","S"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("es",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Agenda"},allDayHtml:"Todo<br/>el día",eventLimitText:"más"})}(),function(){!function(){"use strict";var a={1:"۱",2:"۲",3:"۳",4:"۴",5:"۵",6:"۶",7:"۷",8:"۸",9:"۹",0:"۰"},c={"۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","۰":"0"},d=(b.defineLocale||b.lang).call(b,"fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysShort:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysMin:"ی_د_س_چ_پ_ج_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/قبل از ظهر|بعد از ظهر/,isPM:function(a){return/بعد از ظهر/.test(a)},meridiem:function(a,b,c){return 12>a?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چندین ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(a){return a.replace(/[۰-۹]/g,function(a){return c[a]}).replace(/،/g,",")},postformat:function(b){return b.replace(/\d/g,function(b){return a[b]}).replace(/,/g,"،")},ordinalParse:/\d{1,2}م/,ordinal:"%dم",week:{dow:6,doy:12}});return d}(),a.fullCalendar.datepickerLang("fa","fa",{closeText:"بستن",prevText:"<قبلی",nextText:"بعدی>",currentText:"امروز",monthNames:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["يکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],dayNamesShort:["ی","د","س","چ","پ","ج","ش"],dayNamesMin:["ی","د","س","چ","پ","ج","ش"],weekHeader:"هف",dateFormat:"yy/mm/dd",firstDay:6,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fa",{buttonText:{month:"ماه",week:"هفته",day:"روز",list:"برنامه"},allDayText:"تمام روز",eventLimitText:function(a){return"بیش از "+a}})}(),function(){!function(){"use strict";function a(a,b,d,e){var f="";switch(d){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=c(a,e)+" "+f}function c(a,b){return 10>a?b?e[a]:d[a]:a}var d="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),e=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",d[7],d[8],d[9]],f=(b.defineLocale||b.lang).call(b,"fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] HH.mm",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] HH.mm",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] HH.mm",llll:"ddd, Do MMM YYYY, [klo] HH.mm"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return f}(),a.fullCalendar.datepickerLang("fi","fi",{closeText:"Sulje",prevText:"«Edellinen",nextText:"Seuraava»",currentText:"Tänään",monthNames:["Tammikuu","Helmikuu","Maaliskuu","Huhtikuu","Toukokuu","Kesäkuu","Heinäkuu","Elokuu","Syyskuu","Lokakuu","Marraskuu","Joulukuu"],monthNamesShort:["Tammi","Helmi","Maalis","Huhti","Touko","Kesä","Heinä","Elo","Syys","Loka","Marras","Joulu"],dayNamesShort:["Su","Ma","Ti","Ke","To","Pe","La"],dayNames:["Sunnuntai","Maanantai","Tiistai","Keskiviikko","Torstai","Perjantai","Lauantai"],dayNamesMin:["Su","Ma","Ti","Ke","To","Pe","La"],weekHeader:"Vk",dateFormat:"d.m.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fi",{buttonText:{month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Tapahtumat"},allDayText:"Koko päivä",eventLimitText:"lisää"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|e)/,ordinal:function(a){return a+(1===a?"er":"e")}});return a}(),a.fullCalendar.datepickerLang("fr-ca","fr-CA",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"yy-mm-dd",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fr-ca",{buttonText:{month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"fr-ch",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|e)/,ordinal:function(a){return a+(1===a?"er":"e")},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("fr-ch","fr-CH",{closeText:"Fermer",prevText:"<Préc",nextText:"Suiv>",currentText:"Courant",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sm",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fr-ch",{buttonText:{month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|)/,ordinal:function(a){return a+(1===a?"er":"")},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("fr","fr",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fr",{buttonText:{month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY HH:mm",LLLL:"dddd, D [ב]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(a){return 2===a?"שעתיים":a+" שעות"},d:"יום",dd:function(a){return 2===a?"יומיים":a+" ימים"},M:"חודש",MM:function(a){return 2===a?"חודשיים":a+" חודשים"},y:"שנה",yy:function(a){return 2===a?"שנתיים":a%10===0&&10!==a?a+" שנה":a+" שנים"}},meridiemParse:/אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,isPM:function(a){return/^(אחה"צ|אחרי הצהריים|בערב)$/.test(a)},meridiem:function(a,b,c){return 5>a?"לפנות בוקר":10>a?"בבוקר":12>a?c?'לפנה"צ':"לפני הצהריים":18>a?c?'אחה"צ':"אחרי הצהריים":"בערב"}});return a}(),a.fullCalendar.datepickerLang("he","he",{closeText:"סגור",prevText:"<הקודם",nextText:"הבא>",currentText:"היום",monthNames:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],monthNamesShort:["ינו","פבר","מרץ","אפר","מאי","יוני","יולי","אוג","ספט","אוק","נוב","דצמ"],dayNames:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת"],dayNamesShort:["א'","ב'","ג'","ד'","ה'","ו'","שבת"],dayNamesMin:["א'","ב'","ג'","ד'","ה'","ו'","שבת"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("he",{defaultButtonText:{month:"חודש",week:"שבוע",day:"יום",list:"סדר יום"},weekNumberTitle:"שבוע",allDayText:"כל היום",eventLimitText:"אחר"})}(),function(){!function(){"use strict";var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},c={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},d=(b.defineLocale||b.lang).call(b,"hi",{months:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",LTS:"A h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm बजे",LLLL:"dddd, D MMMM YYYY, A h:mm बजे"},calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return c[a]})},postformat:function(b){return b.replace(/\d/g,function(b){return a[b]})},meridiemParse:/रात|सुबह|दोपहर|शाम/,meridiemHour:function(a,b){return 12===a&&(a=0),"रात"===b?4>a?a:a+12:"सुबह"===b?a:"दोपहर"===b?a>=10?a:a+12:"शाम"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"रात":10>a?"सुबह":17>a?"दोपहर":20>a?"शाम":"रात"},week:{dow:0,doy:6}});return d}(),a.fullCalendar.datepickerLang("hi","hi",{closeText:"बंद",prevText:"पिछला",nextText:"अगला",currentText:"आज",monthNames:["जनवरी ","फरवरी","मार्च","अप्रेल","मई","जून","जूलाई","अगस्त ","सितम्बर","अक्टूबर","नवम्बर","दिसम्बर"],monthNamesShort:["जन","फर","मार्च","अप्रेल","मई","जून","जूलाई","अग","सित","अक्ट","नव","दि"],dayNames:["रविवार","सोमवार","मंगलवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],dayNamesShort:["रवि","सोम","मंगल","बुध","गुरु","शुक्र","शनि"],dayNamesMin:["रवि","सोम","मंगल","बुध","गुरु","शुक्र","शनि"],weekHeader:"हफ्ता",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("hi",{buttonText:{month:"महीना",week:"सप्ताह",day:"दिन",list:"कार्यसूची"},allDayText:"सभी दिन",eventLimitText:function(a){return"+अधिक "+a}})}(),function(){!function(){"use strict";function a(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}var c=(b.defineLocale||b.lang).call(b,"hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:a,mm:a,h:a,hh:a,d:"dan",dd:a,M:"mjesec",MM:a,y:"godinu",yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("hr","hr",{closeText:"Zatvori",prevText:"<",nextText:">",currentText:"Danas",monthNames:["Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac"],monthNamesShort:["Sij","Velj","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro"],dayNames:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],dayNamesShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],dayNamesMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],weekHeader:"Tje",dateFormat:"dd.mm.yy.",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("hr",{buttonText:{month:"Mjesec",week:"Tjedan",day:"Dan",list:"Raspored"},allDayText:"Cijeli dan",eventLimitText:function(a){return"+ još "+a}})}(),function(){!function(){"use strict";function a(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":return"egy"+(d||b?" perc":" perce");case"mm":return e+(d||b?" perc":" perce");case"h":return"egy"+(d||b?" óra":" órája");case"hh":return e+(d||b?" óra":" órája");case"d":return"egy"+(d||b?" nap":" napja");case"dd":return e+(d||b?" nap":" napja");case"M":return"egy"+(d||b?" hónap":" hónapja");case"MM":return e+(d||b?" hónap":" hónapja");case"y":return"egy"+(d||b?" év":" éve");case"yy":return e+(d||b?" év":" éve")}return""}function c(a){return(a?"":"[múlt] ")+"["+d[this.day()]+"] LT[-kor]"}var d="vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" "),e=(b.defineLocale||b.lang).call(b,"hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D. H:mm",LLLL:"YYYY. MMMM D., dddd H:mm"},meridiemParse:/de|du/i,isPM:function(a){return"u"===a.charAt(1).toLowerCase()},meridiem:function(a,b,c){return 12>a?c===!0?"de":"DE":c===!0?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return c.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return c.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return e}(),a.fullCalendar.datepickerLang("hu","hu",{closeText:"bezár",prevText:"vissza",nextText:"előre",currentText:"ma",monthNames:["Január","Február","Március","Április","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],monthNamesShort:["Jan","Feb","Már","Ápr","Máj","Jún","Júl","Aug","Szep","Okt","Nov","Dec"],dayNames:["Vasárnap","Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat"],dayNamesShort:["Vas","Hét","Ked","Sze","Csü","Pén","Szo"],dayNamesMin:["V","H","K","Sze","Cs","P","Szo"],weekHeader:"Hét",dateFormat:"yy.mm.dd.",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:""}),a.fullCalendar.lang("hu",{buttonText:{month:"Hónap",week:"Hét",day:"Nap",list:"Napló"},allDayText:"Egész nap",eventLimitText:"további"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"siang"===b?a>=11?a:a+12:"sore"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"siang":19>a?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}});return a}(),a.fullCalendar.datepickerLang("id","id",{closeText:"Tutup",prevText:"<mundur",nextText:"maju>",currentText:"hari ini",monthNames:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","Nopember","Desember"],monthNamesShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agus","Sep","Okt","Nop","Des"],dayNames:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],dayNamesShort:["Min","Sen","Sel","Rab","kam","Jum","Sab"],dayNamesMin:["Mg","Sn","Sl","Rb","Km","jm","Sb"],weekHeader:"Mg",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("id",{buttonText:{month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},allDayHtml:"Sehari<br/>penuh",eventLimitText:"lebih"})}(),function(){!function(){"use strict";function a(a){return a%100===11?!0:a%10!==1}function c(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return c?"mínúta":"mínútu";case"mm":return a(b)?f+(c||e?"mínútur":"mínútum"):c?f+"mínúta":f+"mínútu";case"hh":return a(b)?f+(c||e?"klukkustundir":"klukkustundum"):f+"klukkustund";case"d":return c?"dagur":e?"dag":"degi";case"dd":return a(b)?c?f+"dagar":f+(e?"daga":"dögum"):c?f+"dagur":f+(e?"dag":"degi");case"M":return c?"mánuður":e?"mánuð":"mánuði";case"MM":return a(b)?c?f+"mánuðir":f+(e?"mánuði":"mánuðum"):c?f+"mánuður":f+(e?"mánuð":"mánuði");case"y":return c||e?"ár":"ári";case"yy":return a(b)?f+(c||e?"ár":"árum"):f+(c||e?"ár":"ári")}}var d=(b.defineLocale||b.lang).call(b,"is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd, D. MMMM YYYY [kl.] H:mm"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:c,m:c,mm:c,h:"klukkustund",hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return d}(),a.fullCalendar.datepickerLang("is","is",{closeText:"Loka",prevText:"< Fyrri",nextText:"Næsti >",currentText:"Í dag",monthNames:["Janúar","Febrúar","Mars","Apríl","Maí","Júní","Júlí","Ágúst","September","Október","Nóvember","Desember"],monthNamesShort:["Jan","Feb","Mar","Apr","Maí","Jún","Júl","Ágú","Sep","Okt","Nóv","Des"],dayNames:["Sunnudagur","Mánudagur","Þriðjudagur","Miðvikudagur","Fimmtudagur","Föstudagur","Laugardagur"],dayNamesShort:["Sun","Mán","Þri","Mið","Fim","Fös","Lau"],dayNamesMin:["Su","Má","Þr","Mi","Fi","Fö","La"],weekHeader:"Vika",dateFormat:"dd.mm.yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("is",{buttonText:{month:"Mánuður",week:"Vika",day:"Dagur",list:"Dagskrá"},allDayHtml:"Allan<br/>daginn",eventLimitText:"meira"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"Do_Lu_Ma_Me_Gi_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(a){return(/^[0-9].+$/.test(a)?"tra":"in")+" "+a},past:"%s fa",s:"alcuni secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("it","it",{closeText:"Chiudi",prevText:"<Prec",nextText:"Succ>",currentText:"Oggi",monthNames:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthNamesShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],dayNames:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],dayNamesShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],dayNamesMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("it",{buttonText:{month:"Mese",week:"Settimana",day:"Giorno",list:"Agenda"},allDayHtml:"Tutto il<br/>giorno",eventLimitText:function(a){return"+altri "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"ja",{months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",LTS:"Ah時m分s秒",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah時m分",LLLL:"YYYY年M月D日Ah時m分 dddd"},meridiemParse:/午前|午後/i,isPM:function(a){return"午後"===a},meridiem:function(a,b,c){return 12>a?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},ordinalParse:/\d{1,2}日/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";default:return a}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}});return a}(),a.fullCalendar.datepickerLang("ja","ja",{closeText:"閉じる",prevText:"<前",nextText:"次>",currentText:"今日",monthNames:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthNamesShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayNames:["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],dayNamesShort:["日","月","火","水","木","金","土"],dayNamesMin:["日","月","火","水","木","金","土"],weekHeader:"週",dateFormat:"yy/mm/dd",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),a.fullCalendar.lang("ja",{buttonText:{month:"月",week:"週",day:"日",list:"予定リスト"},allDayText:"終日",eventLimitText:function(a){return"他 "+a+" 件"}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 m분",LTS:"A h시 m분 s초",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 A h시 m분",LLLL:"YYYY년 MMMM D일 dddd A h시 m분"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇 초",ss:"%d초",m:"일분",mm:"%d분",h:"한 시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한 달",MM:"%d달",y:"일 년",yy:"%d년"},ordinalParse:/\d{1,2}일/,ordinal:"%d일",meridiemParse:/오전|오후/,isPM:function(a){return"오후"===a},meridiem:function(a,b,c){return 12>a?"오전":"오후"}});return a}(),a.fullCalendar.datepickerLang("ko","ko",{closeText:"닫기",prevText:"이전달",nextText:"다음달",currentText:"오늘",monthNames:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthNamesShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],dayNames:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],dayNamesShort:["일","월","화","수","목","금","토"],dayNamesMin:["일","월","화","수","목","금","토"],weekHeader:"Wk",dateFormat:"yy-mm-dd",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"년"}),a.fullCalendar.lang("ko",{buttonText:{month:"월",week:"주",day:"일",list:"일정목록"},allDayText:"종일",eventLimitText:"개"})}(),function(){!function(){"use strict";function a(a,b,c,d){return b?"kelios sekundės":d?"kelių sekundžių":"kelias sekundes"}function c(a,b,c,d){return b?e(c)[0]:d?e(c)[1]:e(c)[2]}function d(a){return a%10===0||a>10&&20>a}function e(a){return g[a].split("_")}function f(a,b,f,g){var h=a+" ";return 1===a?h+c(a,b,f[0],g):b?h+(d(a)?e(f)[1]:e(f)[0]):g?h+e(f)[1]:h+(d(a)?e(f)[1]:e(f)[2])}var g={m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes", -h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"},h=(b.defineLocale||b.lang).call(b,"lt",{months:{format:"sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis".split("_")},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:a,m:c,mm:f,h:c,hh:f,d:c,dd:f,M:c,MM:f,y:c,yy:f},ordinalParse:/\d{1,2}-oji/,ordinal:function(a){return a+"-oji"},week:{dow:1,doy:4}});return h}(),a.fullCalendar.datepickerLang("lt","lt",{closeText:"Uždaryti",prevText:"<Atgal",nextText:"Pirmyn>",currentText:"Šiandien",monthNames:["Sausis","Vasaris","Kovas","Balandis","Gegužė","Birželis","Liepa","Rugpjūtis","Rugsėjis","Spalis","Lapkritis","Gruodis"],monthNamesShort:["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rugp","Rugs","Spa","Lap","Gru"],dayNames:["sekmadienis","pirmadienis","antradienis","trečiadienis","ketvirtadienis","penktadienis","šeštadienis"],dayNamesShort:["sek","pir","ant","tre","ket","pen","šeš"],dayNamesMin:["Se","Pr","An","Tr","Ke","Pe","Še"],weekHeader:"SAV",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:""}),a.fullCalendar.lang("lt",{buttonText:{month:"Mėnuo",week:"Savaitė",day:"Diena",list:"Darbotvarkė"},allDayText:"Visą dieną",eventLimitText:"daugiau"})}(),function(){!function(){"use strict";function a(a,b,c){return c?b%10===1&&11!==b?a[2]:a[3]:b%10===1&&11!==b?a[0]:a[1]}function c(b,c,d){return b+" "+a(f[d],b,c)}function d(b,c,d){return a(f[d],b,c)}function e(a,b){return b?"dažas sekundes":"dažām sekundēm"}var f={m:"minūtes_minūtēm_minūte_minūtes".split("_"),mm:"minūtes_minūtēm_minūte_minūtes".split("_"),h:"stundas_stundām_stunda_stundas".split("_"),hh:"stundas_stundām_stunda_stundas".split("_"),d:"dienas_dienām_diena_dienas".split("_"),dd:"dienas_dienām_diena_dienas".split("_"),M:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),MM:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")},g=(b.defineLocale||b.lang).call(b,"lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"pēc %s",past:"pirms %s",s:e,m:d,mm:c,h:d,hh:c,d:d,dd:c,M:d,MM:c,y:d,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return g}(),a.fullCalendar.datepickerLang("lv","lv",{closeText:"Aizvērt",prevText:"Iepr.",nextText:"Nāk.",currentText:"Šodien",monthNames:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthNamesShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],dayNames:["svētdiena","pirmdiena","otrdiena","trešdiena","ceturtdiena","piektdiena","sestdiena"],dayNamesShort:["svt","prm","otr","tre","ctr","pkt","sst"],dayNamesMin:["Sv","Pr","Ot","Tr","Ct","Pk","Ss"],weekHeader:"Ned.",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("lv",{buttonText:{month:"Mēnesis",week:"Nedēļa",day:"Diena",list:"Dienas kārtība"},allDayText:"Visu dienu",eventLimitText:function(a){return"+vēl "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] HH:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("nb","nb",{closeText:"Lukk",prevText:"«Forrige",nextText:"Neste»",currentText:"I dag",monthNames:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],monthNamesShort:["jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des"],dayNamesShort:["søn","man","tir","ons","tor","fre","lør"],dayNames:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],dayNamesMin:["sø","ma","ti","on","to","fr","lø"],weekHeader:"Uke",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("nb",{buttonText:{month:"Måned",week:"Uke",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"til"})}(),function(){!function(){"use strict";var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),c="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),d=(b.defineLocale||b.lang).call(b,"nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(b,d){return/-MMM-/.test(d)?c[b.month()]:a[b.month()]},monthsParseExact:!0,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,doy:4}});return d}(),a.fullCalendar.datepickerLang("nl","nl",{closeText:"Sluiten",prevText:"←",nextText:"→",currentText:"Vandaag",monthNames:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthNamesShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],dayNames:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],dayNamesShort:["zon","maa","din","woe","don","vri","zat"],dayNamesMin:["zo","ma","di","wo","do","vr","za"],weekHeader:"Wk",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("nl",{buttonText:{month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Hele dag",eventLimitText:"extra"})}(),function(){!function(){"use strict";function a(a){return 5>a%10&&a%10>1&&~~(a/10)%10!==1}function c(b,c,d){var e=b+" ";switch(d){case"m":return c?"minuta":"minutę";case"mm":return e+(a(b)?"minuty":"minut");case"h":return c?"godzina":"godzinę";case"hh":return e+(a(b)?"godziny":"godzin");case"MM":return e+(a(b)?"miesiące":"miesięcy");case"yy":return e+(a(b)?"lata":"lat")}}var d="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),e="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"),f=(b.defineLocale||b.lang).call(b,"pl",{months:function(a,b){return""===b?"("+e[a.month()]+"|"+d[a.month()]+")":/D MMMM/.test(b)?e[a.month()]:d[a.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:c,mm:c,h:c,hh:c,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:c,y:"rok",yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return f}(),a.fullCalendar.datepickerLang("pl","pl",{closeText:"Zamknij",prevText:"<Poprzedni",nextText:"Następny>",currentText:"Dziś",monthNames:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthNamesShort:["Sty","Lu","Mar","Kw","Maj","Cze","Lip","Sie","Wrz","Pa","Lis","Gru"],dayNames:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],dayNamesShort:["Nie","Pn","Wt","Śr","Czw","Pt","So"],dayNamesMin:["N","Pn","Wt","Śr","Cz","Pt","So"],weekHeader:"Tydz",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pl",{buttonText:{month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Plan dnia"},allDayText:"Cały dzień",eventLimitText:"więcej"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"pt-br",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [às] HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"poucos segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº"});return a}(),a.fullCalendar.datepickerLang("pt-br","pt-BR",{closeText:"Fechar",prevText:"<Anterior",nextText:"Próximo>",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pt-br",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Compromissos"},allDayText:"dia inteiro",eventLimitText:function(a){return"mais +"+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"pt",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("pt","pt",{closeText:"Fechar",prevText:"Anterior",nextText:"Seguinte",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sem",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pt",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Agenda"},allDayText:"Todo o dia",eventLimitText:"mais"})}(),function(){!function(){"use strict";function a(a,b,c){var d={mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"},e=" ";return(a%100>=20||a>=100&&a%100===0)&&(e=" de "),a+e+d[c]}var c=(b.defineLocale||b.lang).call(b,"ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",m:"un minut",mm:a,h:"o oră",hh:a,d:"o zi",dd:a,M:"o lună",MM:a,y:"un an",yy:a},week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("ro","ro",{closeText:"Închide",prevText:"« Luna precedentă",nextText:"Luna următoare »",currentText:"Azi",monthNames:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthNamesShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă"],dayNamesShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm"],dayNamesMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],weekHeader:"Săpt",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ro",{buttonText:{prev:"precedentă",next:"următoare",month:"Lună",week:"Săptămână",day:"Zi",list:"Agendă"},allDayText:"Toată ziua",eventLimitText:function(a){return"+alte "+a}})}(),function(){!function(){"use strict";function a(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(b,c,d){var e={mm:c?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===d?c?"минута":"минуту":b+" "+a(e[d],+b)}var d=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i],e=(b.defineLocale||b.lang).call(b,"ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:d,longMonthsParse:d,shortMonthsParse:d,monthsRegex:/^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|сент\.|февр\.|нояб\.|июнь|янв.|июль|дек.|авг.|апр.|марта|мар[.т]|окт.|июн[яь]|июл[яь]|ма[яй])/i,monthsShortRegex:/^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|сент\.|февр\.|нояб\.|июнь|янв.|июль|дек.|авг.|апр.|марта|мар[.т]|окт.|июн[яь]|июл[яь]|ма[яй])/i,monthsStrictRegex:/^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|марта?|июн[яь]|июл[яь]|ма[яй])/i,monthsShortStrictRegex:/^(нояб\.|февр\.|сент\.|июль|янв\.|июн[яь]|мар[.т]|авг\.|апр\.|окт\.|дек\.|ма[яй])/i,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В следующее] dddd [в] LT";case 1:case 2:case 4:return"[В следующий] dddd [в] LT";case 3:case 5:case 6:return"[В следующую] dddd [в] LT"}},lastWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:c,mm:c,h:"час",hh:c,d:"день",dd:c,M:"месяц",MM:c,y:"год",yy:c},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(a){return/^(дня|вечера)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночи":12>a?"утра":17>a?"дня":"вечера"},ordinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":return a+"-й";case"D":return a+"-го";case"w":case"W":return a+"-я";default:return a}},week:{dow:1,doy:7}});return e}(),a.fullCalendar.datepickerLang("ru","ru",{closeText:"Закрыть",prevText:"<Пред",nextText:"След>",currentText:"Сегодня",monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],dayNamesShort:["вск","пнд","втр","срд","чтв","птн","сбт"],dayNamesMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Нед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ru",{buttonText:{month:"Месяц",week:"Неделя",day:"День",list:"Повестка дня"},allDayText:"Весь день",eventLimitText:function(a){return"+ ещё "+a}})}(),function(){!function(){"use strict";function a(a){return a>1&&5>a}function c(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"pár sekúnd":"pár sekundami";case"m":return c?"minúta":e?"minútu":"minútou";case"mm":return c||e?f+(a(b)?"minúty":"minút"):f+"minútami";case"h":return c?"hodina":e?"hodinu":"hodinou";case"hh":return c||e?f+(a(b)?"hodiny":"hodín"):f+"hodinami";case"d":return c||e?"deň":"dňom";case"dd":return c||e?f+(a(b)?"dni":"dní"):f+"dňami";case"M":return c||e?"mesiac":"mesiacom";case"MM":return c||e?f+(a(b)?"mesiace":"mesiacov"):f+"mesiacmi";case"y":return c||e?"rok":"rokom";case"yy":return c||e?f+(a(b)?"roky":"rokov"):f+"rokmi"}}var d="január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),e="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_"),f=(b.defineLocale||b.lang).call(b,"sk",{months:d,monthsShort:e,weekdays:"nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_št_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_št_pi_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo štvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 4:case 5:return"[minulý] dddd [o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return f}(),a.fullCalendar.datepickerLang("sk","sk",{closeText:"Zavrieť",prevText:"<Predchádzajúci",nextText:"Nasledujúci>",currentText:"Dnes",monthNames:["január","február","marec","apríl","máj","jún","júl","august","september","október","november","december"],monthNamesShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],dayNames:["nedeľa","pondelok","utorok","streda","štvrtok","piatok","sobota"],dayNamesShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob"],dayNamesMin:["Ne","Po","Ut","St","Št","Pia","So"],weekHeader:"Ty",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sk",{buttonText:{month:"Mesiac",week:"Týždeň",day:"Deň",list:"Rozvrh"},allDayText:"Celý deň",eventLimitText:function(a){return"+ďalšie: "+a}})}(),function(){!function(){"use strict";function a(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"nekaj sekund":"nekaj sekundami";case"m":return b?"ena minuta":"eno minuto";case"mm":return e+=1===a?b?"minuta":"minuto":2===a?b||d?"minuti":"minutama":5>a?b||d?"minute":"minutami":b||d?"minut":"minutami";case"h":return b?"ena ura":"eno uro";case"hh":return e+=1===a?b?"ura":"uro":2===a?b||d?"uri":"urama":5>a?b||d?"ure":"urami":b||d?"ur":"urami";case"d":return b||d?"en dan":"enim dnem";case"dd":return e+=1===a?b||d?"dan":"dnem":2===a?b||d?"dni":"dnevoma":b||d?"dni":"dnevi";case"M":return b||d?"en mesec":"enim mesecem";case"MM":return e+=1===a?b||d?"mesec":"mesecem":2===a?b||d?"meseca":"mesecema":5>a?b||d?"mesece":"meseci":b||d?"mesecev":"meseci";case"y":return b||d?"eno leto":"enim letom";case"yy":return e+=1===a?b||d?"leto":"letom":2===a?b||d?"leti":"letoma":5>a?b||d?"leta":"leti":b||d?"let":"leti"}}var c=(b.defineLocale||b.lang).call(b,"sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:return"[prejšnjo] [nedeljo] [ob] LT";case 3:return"[prejšnjo] [sredo] [ob] LT";case 6:return"[prejšnjo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"pred %s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("sl","sl",{closeText:"Zapri",prevText:"<Prejšnji",nextText:"Naslednji>",currentText:"Trenutni",monthNames:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],dayNames:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"],dayNamesShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],dayNamesMin:["Ne","Po","To","Sr","Če","Pe","So"],weekHeader:"Teden",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sl",{buttonText:{month:"Mesec",week:"Teden",day:"Dan",list:"Dnevni red"},allDayText:"Ves dan",eventLimitText:"več"})}(),function(){!function(){"use strict";var a={words:{m:["један минут","једне минуте"],mm:["минут","минуте","минута"],h:["један сат","једног сата"],hh:["сат","сата","сати"],dd:["дан","дана","дана"],MM:["месец","месеца","месеци"],yy:["година","године","година"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(b,c,d){var e=a.words[d];return 1===d.length?c?e[0]:e[1]:b+" "+a.correctGrammaticalCase(b,e)}},c=(b.defineLocale||b.lang).call(b,"sr-cyrl",{months:"јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар".split("_"),monthsShort:"јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.".split("_"),monthsParseExact:!0,weekdays:"недеља_понедељак_уторак_среда_четвртак_петак_субота".split("_"),weekdaysShort:"нед._пон._уто._сре._чет._пет._суб.".split("_"),weekdaysMin:"не_по_ут_ср_че_пе_су".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[данас у] LT",nextDay:"[сутра у] LT",nextWeek:function(){switch(this.day()){case 0:return"[у] [недељу] [у] LT";case 3:return"[у] [среду] [у] LT";case 6:return"[у] [суботу] [у] LT";case 1:case 2:case 4:case 5:return"[у] dddd [у] LT"}},lastDay:"[јуче у] LT",lastWeek:function(){var a=["[прошле] [недеље] [у] LT","[прошлог] [понедељка] [у] LT","[прошлог] [уторка] [у] LT","[прошле] [среде] [у] LT","[прошлог] [четвртка] [у] LT","[прошлог] [петка] [у] LT","[прошле] [суботе] [у] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"за %s",past:"пре %s",s:"неколико секунди",m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:"дан",dd:a.translate,M:"месец",MM:a.translate,y:"годину",yy:a.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("sr-cyrl","sr",{closeText:"Затвори",prevText:"<",nextText:">",currentText:"Данас",monthNames:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthNamesShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],dayNames:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],dayNamesShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],dayNamesMin:["Не","По","Ут","Ср","Че","Пе","Су"],weekHeader:"Сед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sr-cyrl",{buttonText:{month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},allDayText:"Цео дан",eventLimitText:function(a){return"+ још "+a}})}(),function(){!function(){"use strict";var a={words:{m:["jedan minut","jedne minute"],mm:["minut","minute","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mesec","meseca","meseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(b,c,d){var e=a.words[d];return 1===d.length?c?e[0]:e[1]:b+" "+a.correctGrammaticalCase(b,e)}},c=(b.defineLocale||b.lang).call(b,"sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var a=["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:"dan",dd:a.translate,M:"mesec",MM:a.translate,y:"godinu",yy:a.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("sr","sr",{closeText:"Затвори",prevText:"<",nextText:">",currentText:"Данас",monthNames:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthNamesShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],dayNames:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],dayNamesShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],dayNamesMin:["Не","По","Ут","Ср","Че","Пе","Су"],weekHeader:"Сед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sr",{buttonText:{month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},allDayText:"Цео дан",eventLimitText:function(a){return"+ још "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"), -monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [kl.] HH:mm",LLLL:"dddd D MMMM YYYY [kl.] HH:mm",lll:"D MMM YYYY HH:mm",llll:"ddd D MMM YYYY HH:mm"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"[På] dddd LT",lastWeek:"[I] dddd[s] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}(e|a)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"e":1===b?"a":2===b?"a":"e";return a+c},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("sv","sv",{closeText:"Stäng",prevText:"«Förra",nextText:"Nästa»",currentText:"Idag",monthNames:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNamesShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör"],dayNames:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"],dayNamesMin:["Sö","Må","Ti","On","To","Fr","Lö"],weekHeader:"Ve",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sv",{buttonText:{month:"Månad",week:"Vecka",day:"Dag",list:"Program"},allDayText:"Heldag",eventLimitText:"till"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),monthsParseExact:!0,weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H นาฬิกา m นาที",LTS:"H นาฬิกา m นาที s วินาที",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา H นาฬิกา m นาที",LLLL:"วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(a){return"หลังเที่ยง"===a},meridiem:function(a,b,c){return 12>a?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}});return a}(),a.fullCalendar.datepickerLang("th","th",{closeText:"ปิด",prevText:"« ย้อน",nextText:"ถัดไป »",currentText:"วันนี้",monthNames:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthNamesShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],dayNames:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัสบดี","ศุกร์","เสาร์"],dayNamesShort:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],dayNamesMin:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("th",{buttonText:{month:"เดือน",week:"สัปดาห์",day:"วัน",list:"แผนงาน"},allDayText:"ตลอดวัน",eventLimitText:"เพิ่มเติม"})}(),function(){!function(){"use strict";var a={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"},c=(b.defineLocale||b.lang).call(b,"tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinalParse:/\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,ordinal:function(b){if(0===b)return b+"'ıncı";var c=b%10,d=b%100-c,e=b>=100?100:null;return b+(a[c]||a[d]||a[e])},week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("tr","tr",{closeText:"kapat",prevText:"<geri",nextText:"ileri>",currentText:"bugün",monthNames:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthNamesShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],dayNames:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],dayNamesShort:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],dayNamesMin:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],weekHeader:"Hf",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("tr",{buttonText:{next:"ileri",month:"Ay",week:"Hafta",day:"Gün",list:"Ajanda"},allDayText:"Tüm gün",eventLimitText:"daha fazla"})}(),function(){!function(){"use strict";function a(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(b,c,d){var e={mm:c?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:c?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===d?c?"хвилина":"хвилину":"h"===d?c?"година":"годину":b+" "+a(e[d],+b)}function d(a,b){var c={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")},d=/(\[[ВвУу]\]) ?dddd/.test(b)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(b)?"genitive":"nominative";return c[d][a.day()]}function e(a){return function(){return a+"о"+(11===this.hours()?"б":"")+"] LT"}}var f=(b.defineLocale||b.lang).call(b,"uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:d,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:e("[Сьогодні "),nextDay:e("[Завтра "),lastDay:e("[Вчора "),nextWeek:e("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return e("[Минулої] dddd [").call(this);case 1:case 2:case 4:return e("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",m:c,mm:c,h:"годину",hh:c,d:"день",dd:c,M:"місяць",MM:c,y:"рік",yy:c},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(a){return/^(дня|вечора)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночі":12>a?"ранку":17>a?"дня":"вечора"},ordinalParse:/\d{1,2}-(й|го)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":case"w":case"W":return a+"-й";case"D":return a+"-го";default:return a}},week:{dow:1,doy:7}});return f}(),a.fullCalendar.datepickerLang("uk","uk",{closeText:"Закрити",prevText:"<",nextText:">",currentText:"Сьогодні",monthNames:["Січень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthNamesShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],dayNames:["неділя","понеділок","вівторок","середа","четвер","п’ятниця","субота"],dayNamesShort:["нед","пнд","вів","срд","чтв","птн","сбт"],dayNamesMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Тиж",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("uk",{buttonText:{month:"Місяць",week:"Тиждень",day:"День",list:"Порядок денний"},allDayText:"Увесь день",eventLimitText:function(a){return"+ще "+a+"..."}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"vi",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),monthsParseExact:!0,weekdays:"chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysParseExact:!0,meridiemParse:/sa|ch/i,isPM:function(a){return/^ch$/i.test(a)},meridiem:function(a,b,c){return 12>a?c?"sa":"SA":c?"ch":"CH"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY HH:mm",LLLL:"dddd, D MMMM [năm] YYYY HH:mm",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngày mai lúc] LT",nextWeek:"dddd [tuần tới lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần rồi lúc] LT",sameElse:"L"},relativeTime:{future:"%s tới",past:"%s trước",s:"vài giây",m:"một phút",mm:"%d phút",h:"một giờ",hh:"%d giờ",d:"một ngày",dd:"%d ngày",M:"một tháng",MM:"%d tháng",y:"một năm",yy:"%d năm"},ordinalParse:/\d{1,2}/,ordinal:function(a){return a},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("vi","vi",{closeText:"Đóng",prevText:"<Trước",nextText:"Tiếp>",currentText:"Hôm nay",monthNames:["Tháng Một","Tháng Hai","Tháng Ba","Tháng Tư","Tháng Năm","Tháng Sáu","Tháng Bảy","Tháng Tám","Tháng Chín","Tháng Mười","Tháng Mười Một","Tháng Mười Hai"],monthNamesShort:["Tháng 1","Tháng 2","Tháng 3","Tháng 4","Tháng 5","Tháng 6","Tháng 7","Tháng 8","Tháng 9","Tháng 10","Tháng 11","Tháng 12"],dayNames:["Chủ Nhật","Thứ Hai","Thứ Ba","Thứ Tư","Thứ Năm","Thứ Sáu","Thứ Bảy"],dayNamesShort:["CN","T2","T3","T4","T5","T6","T7"],dayNamesMin:["CN","T2","T3","T4","T5","T6","T7"],weekHeader:"Tu",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("vi",{buttonText:{month:"Tháng",week:"Tuần",day:"Ngày",list:"Lịch biểu"},allDayText:"Cả ngày",eventLimitText:function(a){return"+ thêm "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm分",LTS:"Ah点m分s秒",L:"YYYY-MM-DD",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日Ah点mm分",LLLL:"YYYY年MMMD日ddddAh点mm分",l:"YYYY-MM-DD",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日Ah点mm分",llll:"YYYY年MMMD日ddddAh点mm分"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"凌晨"===b||"早上"===b||"上午"===b?a:"下午"===b||"晚上"===b?a+12:a>=11?a:a+12},meridiem:function(a,b,c){var d=100*a+b;return 600>d?"凌晨":900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:function(){return 0===this.minutes()?"[今天]Ah[点整]":"[今天]LT"},nextDay:function(){return 0===this.minutes()?"[明天]Ah[点整]":"[明天]LT"},lastDay:function(){return 0===this.minutes()?"[昨天]Ah[点整]":"[昨天]LT"},nextWeek:function(){var a,c;return a=b().startOf("week"),c=this.diff(a,"days")>=7?"[下]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},lastWeek:function(){var a,c;return a=b().startOf("week"),c=this.unix()<a.unix()?"[上]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},sameElse:"LL"},ordinalParse:/\d{1,2}(日|月|周)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"周";default:return a}},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("zh-cn","zh-CN",{closeText:"关闭",prevText:"<上月",nextText:"下月>",currentText:"今天",monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],dayNamesMin:["日","一","二","三","四","五","六"],weekHeader:"周",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),a.fullCalendar.lang("zh-cn",{buttonText:{month:"月",week:"周",day:"日",list:"日程"},allDayText:"全天",eventLimitText:function(a){return"另外 "+a+" 个"}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm分",LTS:"Ah點m分s秒",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日Ah點mm分",LLLL:"YYYY年MMMD日ddddAh點mm分",l:"YYYY年MMMD日",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日Ah點mm分",llll:"YYYY年MMMD日ddddAh點mm分"},meridiemParse:/早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"早上"===b||"上午"===b?a:"中午"===b?a>=11?a:a+12:"下午"===b||"晚上"===b?a+12:void 0},meridiem:function(a,b,c){var d=100*a+b;return 900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},ordinalParse:/\d{1,2}(日|月|週)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"週";default:return a}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"1分鐘",mm:"%d分鐘",h:"1小時",hh:"%d小時",d:"1天",dd:"%d天",M:"1個月",MM:"%d個月",y:"1年",yy:"%d年"}});return a}(),a.fullCalendar.datepickerLang("zh-tw","zh-TW",{closeText:"關閉",prevText:"<上月",nextText:"下月>",currentText:"今天",monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],dayNamesMin:["日","一","二","三","四","五","六"],weekHeader:"周",dateFormat:"yy/mm/dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),a.fullCalendar.lang("zh-tw",{buttonText:{month:"月",week:"週",day:"天",list:"待辦事項"},allDayText:"全天",eventLimitText:"更多"})}(),(b.locale||b.lang).call(b,"en"),a.fullCalendar.lang("en"),a.datepicker&&a.datepicker.setDefaults(a.datepicker.regional[""])}); \ No newline at end of file +months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(b,d){return/-MMM-/.test(d)?c[b.month()]:a[b.month()]},monthsParseExact:!0,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}});return d}(),a.fullCalendar.datepickerLang("es","es",{closeText:"Cerrar",prevText:"<Ant",nextText:"Sig>",currentText:"Hoy",monthNames:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],monthNamesShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],dayNames:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],dayNamesShort:["dom","lun","mar","mié","jue","vie","sáb"],dayNamesMin:["D","L","M","X","J","V","S"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("es",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Agenda"},allDayHtml:"Todo<br/>el día",eventLimitText:"más"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),monthsParseExact:!0,weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] HH:mm",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] HH:mm",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] HH:mm",llll:"ddd, YYYY[ko] MMM D[a] HH:mm"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return a}(),a.fullCalendar.datepickerLang("eu","eu",{closeText:"Egina",prevText:"<Aur",nextText:"Hur>",currentText:"Gaur",monthNames:["urtarrila","otsaila","martxoa","apirila","maiatza","ekaina","uztaila","abuztua","iraila","urria","azaroa","abendua"],monthNamesShort:["urt.","ots.","mar.","api.","mai.","eka.","uzt.","abu.","ira.","urr.","aza.","abe."],dayNames:["igandea","astelehena","asteartea","asteazkena","osteguna","ostirala","larunbata"],dayNamesShort:["ig.","al.","ar.","az.","og.","ol.","lr."],dayNamesMin:["ig","al","ar","az","og","ol","lr"],weekHeader:"As",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("eu",{buttonText:{month:"Hilabetea",week:"Astea",day:"Eguna",list:"Agenda"},allDayHtml:"Egun<br/>osoa",eventLimitText:"gehiago"})}(),function(){!function(){"use strict";var a={1:"۱",2:"۲",3:"۳",4:"۴",5:"۵",6:"۶",7:"۷",8:"۸",9:"۹",0:"۰"},c={"۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","۰":"0"},d=(b.defineLocale||b.lang).call(b,"fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysShort:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysMin:"ی_د_س_چ_پ_ج_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/قبل از ظهر|بعد از ظهر/,isPM:function(a){return/بعد از ظهر/.test(a)},meridiem:function(a,b,c){return 12>a?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چندین ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(a){return a.replace(/[۰-۹]/g,function(a){return c[a]}).replace(/،/g,",")},postformat:function(b){return b.replace(/\d/g,function(b){return a[b]}).replace(/,/g,"،")},ordinalParse:/\d{1,2}م/,ordinal:"%dم",week:{dow:6,doy:12}});return d}(),a.fullCalendar.datepickerLang("fa","fa",{closeText:"بستن",prevText:"<قبلی",nextText:"بعدی>",currentText:"امروز",monthNames:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["يکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],dayNamesShort:["ی","د","س","چ","پ","ج","ش"],dayNamesMin:["ی","د","س","چ","پ","ج","ش"],weekHeader:"هف",dateFormat:"yy/mm/dd",firstDay:6,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fa",{buttonText:{month:"ماه",week:"هفته",day:"روز",list:"برنامه"},allDayText:"تمام روز",eventLimitText:function(a){return"بیش از "+a}})}(),function(){!function(){"use strict";function a(a,b,d,e){var f="";switch(d){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=c(a,e)+" "+f}function c(a,b){return 10>a?b?e[a]:d[a]:a}var d="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),e=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",d[7],d[8],d[9]],f=(b.defineLocale||b.lang).call(b,"fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] HH.mm",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] HH.mm",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] HH.mm",llll:"ddd, Do MMM YYYY, [klo] HH.mm"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return f}(),a.fullCalendar.datepickerLang("fi","fi",{closeText:"Sulje",prevText:"«Edellinen",nextText:"Seuraava»",currentText:"Tänään",monthNames:["Tammikuu","Helmikuu","Maaliskuu","Huhtikuu","Toukokuu","Kesäkuu","Heinäkuu","Elokuu","Syyskuu","Lokakuu","Marraskuu","Joulukuu"],monthNamesShort:["Tammi","Helmi","Maalis","Huhti","Touko","Kesä","Heinä","Elo","Syys","Loka","Marras","Joulu"],dayNamesShort:["Su","Ma","Ti","Ke","To","Pe","La"],dayNames:["Sunnuntai","Maanantai","Tiistai","Keskiviikko","Torstai","Perjantai","Lauantai"],dayNamesMin:["Su","Ma","Ti","Ke","To","Pe","La"],weekHeader:"Vk",dateFormat:"d.m.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fi",{buttonText:{month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Tapahtumat"},allDayText:"Koko päivä",eventLimitText:"lisää"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|e)/,ordinal:function(a){return a+(1===a?"er":"e")}});return a}(),a.fullCalendar.datepickerLang("fr-ca","fr-CA",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"yy-mm-dd",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fr-ca",{buttonText:{year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"fr-ch",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|e)/,ordinal:function(a){return a+(1===a?"er":"e")},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("fr-ch","fr-CH",{closeText:"Fermer",prevText:"<Préc",nextText:"Suiv>",currentText:"Courant",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sm",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fr-ch",{buttonText:{year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|)/,ordinal:function(a){return a+(1===a?"er":"")},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("fr","fr",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fr",{buttonText:{year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"gl",{months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),monthsParseExact:!0,weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd D MMMM YYYY H:mm"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"ás":"á")+"] LT"},nextDay:function(){return"[mañá "+(1!==this.hours()?"ás":"á")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(a){return"uns segundos"===a?"nuns segundos":"en "+a},past:"hai %s",s:"uns segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:7}});return a}(),a.fullCalendar.datepickerLang("gl","gl",{closeText:"Pechar",prevText:"<Ant",nextText:"Seg>",currentText:"Hoxe",monthNames:["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],monthNamesShort:["Xan","Feb","Mar","Abr","Mai","Xuñ","Xul","Ago","Set","Out","Nov","Dec"],dayNames:["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado"],dayNamesShort:["Dom","Lun","Mar","Mér","Xov","Ven","Sáb"],dayNamesMin:["Do","Lu","Ma","Mé","Xo","Ve","Sá"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("gl",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Axenda"},allDayHtml:"Todo<br/>o día",eventLimitText:"máis"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY HH:mm",LLLL:"dddd, D [ב]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(a){return 2===a?"שעתיים":a+" שעות"},d:"יום",dd:function(a){return 2===a?"יומיים":a+" ימים"},M:"חודש",MM:function(a){return 2===a?"חודשיים":a+" חודשים"},y:"שנה",yy:function(a){return 2===a?"שנתיים":a%10===0&&10!==a?a+" שנה":a+" שנים"}},meridiemParse:/אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,isPM:function(a){return/^(אחה"צ|אחרי הצהריים|בערב)$/.test(a)},meridiem:function(a,b,c){return 5>a?"לפנות בוקר":10>a?"בבוקר":12>a?c?'לפנה"צ':"לפני הצהריים":18>a?c?'אחה"צ':"אחרי הצהריים":"בערב"}});return a}(),a.fullCalendar.datepickerLang("he","he",{closeText:"סגור",prevText:"<הקודם",nextText:"הבא>",currentText:"היום",monthNames:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],monthNamesShort:["ינו","פבר","מרץ","אפר","מאי","יוני","יולי","אוג","ספט","אוק","נוב","דצמ"],dayNames:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת"],dayNamesShort:["א'","ב'","ג'","ד'","ה'","ו'","שבת"],dayNamesMin:["א'","ב'","ג'","ד'","ה'","ו'","שבת"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("he",{defaultButtonText:{month:"חודש",week:"שבוע",day:"יום",list:"סדר יום"},weekNumberTitle:"שבוע",allDayText:"כל היום",eventLimitText:"אחר"})}(),function(){!function(){"use strict";var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},c={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},d=(b.defineLocale||b.lang).call(b,"hi",{months:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",LTS:"A h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm बजे",LLLL:"dddd, D MMMM YYYY, A h:mm बजे"},calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return c[a]})},postformat:function(b){return b.replace(/\d/g,function(b){return a[b]})},meridiemParse:/रात|सुबह|दोपहर|शाम/,meridiemHour:function(a,b){return 12===a&&(a=0),"रात"===b?4>a?a:a+12:"सुबह"===b?a:"दोपहर"===b?a>=10?a:a+12:"शाम"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"रात":10>a?"सुबह":17>a?"दोपहर":20>a?"शाम":"रात"},week:{dow:0,doy:6}});return d}(),a.fullCalendar.datepickerLang("hi","hi",{closeText:"बंद",prevText:"पिछला",nextText:"अगला",currentText:"आज",monthNames:["जनवरी ","फरवरी","मार्च","अप्रेल","मई","जून","जूलाई","अगस्त ","सितम्बर","अक्टूबर","नवम्बर","दिसम्बर"],monthNamesShort:["जन","फर","मार्च","अप्रेल","मई","जून","जूलाई","अग","सित","अक्ट","नव","दि"],dayNames:["रविवार","सोमवार","मंगलवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],dayNamesShort:["रवि","सोम","मंगल","बुध","गुरु","शुक्र","शनि"],dayNamesMin:["रवि","सोम","मंगल","बुध","गुरु","शुक्र","शनि"],weekHeader:"हफ्ता",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("hi",{buttonText:{month:"महीना",week:"सप्ताह",day:"दिन",list:"कार्यसूची"},allDayText:"सभी दिन",eventLimitText:function(a){return"+अधिक "+a}})}(),function(){!function(){"use strict";function a(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}var c=(b.defineLocale||b.lang).call(b,"hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:a,mm:a,h:a,hh:a,d:"dan",dd:a,M:"mjesec",MM:a,y:"godinu",yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("hr","hr",{closeText:"Zatvori",prevText:"<",nextText:">",currentText:"Danas",monthNames:["Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac"],monthNamesShort:["Sij","Velj","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro"],dayNames:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],dayNamesShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],dayNamesMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],weekHeader:"Tje",dateFormat:"dd.mm.yy.",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("hr",{buttonText:{month:"Mjesec",week:"Tjedan",day:"Dan",list:"Raspored"},allDayText:"Cijeli dan",eventLimitText:function(a){return"+ još "+a}})}(),function(){!function(){"use strict";function a(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":return"egy"+(d||b?" perc":" perce");case"mm":return e+(d||b?" perc":" perce");case"h":return"egy"+(d||b?" óra":" órája");case"hh":return e+(d||b?" óra":" órája");case"d":return"egy"+(d||b?" nap":" napja");case"dd":return e+(d||b?" nap":" napja");case"M":return"egy"+(d||b?" hónap":" hónapja");case"MM":return e+(d||b?" hónap":" hónapja");case"y":return"egy"+(d||b?" év":" éve");case"yy":return e+(d||b?" év":" éve")}return""}function c(a){return(a?"":"[múlt] ")+"["+d[this.day()]+"] LT[-kor]"}var d="vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" "),e=(b.defineLocale||b.lang).call(b,"hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D. H:mm",LLLL:"YYYY. MMMM D., dddd H:mm"},meridiemParse:/de|du/i,isPM:function(a){return"u"===a.charAt(1).toLowerCase()},meridiem:function(a,b,c){return 12>a?c===!0?"de":"DE":c===!0?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return c.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return c.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return e}(),a.fullCalendar.datepickerLang("hu","hu",{closeText:"bezár",prevText:"vissza",nextText:"előre",currentText:"ma",monthNames:["Január","Február","Március","Április","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],monthNamesShort:["Jan","Feb","Már","Ápr","Máj","Jún","Júl","Aug","Szep","Okt","Nov","Dec"],dayNames:["Vasárnap","Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat"],dayNamesShort:["Vas","Hét","Ked","Sze","Csü","Pén","Szo"],dayNamesMin:["V","H","K","Sze","Cs","P","Szo"],weekHeader:"Hét",dateFormat:"yy.mm.dd.",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:""}),a.fullCalendar.lang("hu",{buttonText:{month:"Hónap",week:"Hét",day:"Nap",list:"Napló"},allDayText:"Egész nap",eventLimitText:"további"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"siang"===b?a>=11?a:a+12:"sore"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"siang":19>a?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}});return a}(),a.fullCalendar.datepickerLang("id","id",{closeText:"Tutup",prevText:"<mundur",nextText:"maju>",currentText:"hari ini",monthNames:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","Nopember","Desember"],monthNamesShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agus","Sep","Okt","Nop","Des"],dayNames:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],dayNamesShort:["Min","Sen","Sel","Rab","kam","Jum","Sab"],dayNamesMin:["Mg","Sn","Sl","Rb","Km","jm","Sb"],weekHeader:"Mg",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("id",{buttonText:{month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},allDayHtml:"Sehari<br/>penuh",eventLimitText:"lebih"})}(),function(){!function(){"use strict";function a(a){return a%100===11?!0:a%10!==1}function c(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return c?"mínúta":"mínútu";case"mm":return a(b)?f+(c||e?"mínútur":"mínútum"):c?f+"mínúta":f+"mínútu";case"hh":return a(b)?f+(c||e?"klukkustundir":"klukkustundum"):f+"klukkustund";case"d":return c?"dagur":e?"dag":"degi";case"dd":return a(b)?c?f+"dagar":f+(e?"daga":"dögum"):c?f+"dagur":f+(e?"dag":"degi");case"M":return c?"mánuður":e?"mánuð":"mánuði";case"MM":return a(b)?c?f+"mánuðir":f+(e?"mánuði":"mánuðum"):c?f+"mánuður":f+(e?"mánuð":"mánuði");case"y":return c||e?"ár":"ári";case"yy":return a(b)?f+(c||e?"ár":"árum"):f+(c||e?"ár":"ári")}}var d=(b.defineLocale||b.lang).call(b,"is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd, D. MMMM YYYY [kl.] H:mm"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:c,m:c,mm:c,h:"klukkustund",hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return d}(),a.fullCalendar.datepickerLang("is","is",{closeText:"Loka",prevText:"< Fyrri",nextText:"Næsti >",currentText:"Í dag",monthNames:["Janúar","Febrúar","Mars","Apríl","Maí","Júní","Júlí","Ágúst","September","Október","Nóvember","Desember"],monthNamesShort:["Jan","Feb","Mar","Apr","Maí","Jún","Júl","Ágú","Sep","Okt","Nóv","Des"],dayNames:["Sunnudagur","Mánudagur","Þriðjudagur","Miðvikudagur","Fimmtudagur","Föstudagur","Laugardagur"],dayNamesShort:["Sun","Mán","Þri","Mið","Fim","Fös","Lau"],dayNamesMin:["Su","Má","Þr","Mi","Fi","Fö","La"],weekHeader:"Vika",dateFormat:"dd.mm.yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("is",{buttonText:{month:"Mánuður",week:"Vika",day:"Dagur",list:"Dagskrá"},allDayHtml:"Allan<br/>daginn",eventLimitText:"meira"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"Do_Lu_Ma_Me_Gi_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(a){return(/^[0-9].+$/.test(a)?"tra":"in")+" "+a},past:"%s fa",s:"alcuni secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("it","it",{closeText:"Chiudi",prevText:"<Prec",nextText:"Succ>",currentText:"Oggi",monthNames:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"], +monthNamesShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],dayNames:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],dayNamesShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],dayNamesMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("it",{buttonText:{month:"Mese",week:"Settimana",day:"Giorno",list:"Agenda"},allDayHtml:"Tutto il<br/>giorno",eventLimitText:function(a){return"+altri "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"ja",{months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",LTS:"Ah時m分s秒",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah時m分",LLLL:"YYYY年M月D日Ah時m分 dddd"},meridiemParse:/午前|午後/i,isPM:function(a){return"午後"===a},meridiem:function(a,b,c){return 12>a?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},ordinalParse:/\d{1,2}日/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";default:return a}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}});return a}(),a.fullCalendar.datepickerLang("ja","ja",{closeText:"閉じる",prevText:"<前",nextText:"次>",currentText:"今日",monthNames:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthNamesShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayNames:["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],dayNamesShort:["日","月","火","水","木","金","土"],dayNamesMin:["日","月","火","水","木","金","土"],weekHeader:"週",dateFormat:"yy/mm/dd",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),a.fullCalendar.lang("ja",{buttonText:{month:"月",week:"週",day:"日",list:"予定リスト"},allDayText:"終日",eventLimitText:function(a){return"他 "+a+" 件"}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 m분",LTS:"A h시 m분 s초",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 A h시 m분",LLLL:"YYYY년 MMMM D일 dddd A h시 m분"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇 초",ss:"%d초",m:"일분",mm:"%d분",h:"한 시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한 달",MM:"%d달",y:"일 년",yy:"%d년"},ordinalParse:/\d{1,2}일/,ordinal:"%d일",meridiemParse:/오전|오후/,isPM:function(a){return"오후"===a},meridiem:function(a,b,c){return 12>a?"오전":"오후"}});return a}(),a.fullCalendar.datepickerLang("ko","ko",{closeText:"닫기",prevText:"이전달",nextText:"다음달",currentText:"오늘",monthNames:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthNamesShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],dayNames:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],dayNamesShort:["일","월","화","수","목","금","토"],dayNamesMin:["일","월","화","수","목","금","토"],weekHeader:"Wk",dateFormat:"yy-mm-dd",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"년"}),a.fullCalendar.lang("ko",{buttonText:{month:"월",week:"주",day:"일",list:"일정목록"},allDayText:"종일",eventLimitText:"개"})}(),function(){!function(){"use strict";function a(a,b,c,d){var e={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return b?e[c][0]:e[c][1]}function c(a){var b=a.substr(0,a.indexOf(" "));return e(b)?"a "+a:"an "+a}function d(a){var b=a.substr(0,a.indexOf(" "));return e(b)?"viru "+a:"virun "+a}function e(a){if(a=parseInt(a,10),isNaN(a))return!1;if(0>a)return!0;if(10>a)return a>=4&&7>=a;if(100>a){var b=a%10,c=a/10;return e(0===b?c:b)}if(1e4>a){for(;a>=10;)a/=10;return e(a)}return a/=1e3,e(a)}var f=(b.defineLocale||b.lang).call(b,"lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm [Auer]",LTS:"H:mm:ss [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm [Auer]",LLLL:"dddd, D. MMMM YYYY H:mm [Auer]"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:function(){switch(this.day()){case 2:case 4:return"[Leschten] dddd [um] LT";default:return"[Leschte] dddd [um] LT"}}},relativeTime:{future:c,past:d,s:"e puer Sekonnen",m:a,mm:"%d Minutten",h:a,hh:"%d Stonnen",d:a,dd:"%d Deeg",M:a,MM:"%d Méint",y:a,yy:"%d Joer"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return f}(),a.fullCalendar.datepickerLang("lb","lb",{closeText:"Fäerdeg",prevText:"Zréck",nextText:"Weider",currentText:"Haut",monthNames:["Januar","Februar","Mäerz","Abrëll","Mee","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mäe","Abr","Mee","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonndeg","Méindeg","Dënschdeg","Mëttwoch","Donneschdeg","Freideg","Samschdeg"],dayNamesShort:["Son","Méi","Dën","Mët","Don","Fre","Sam"],dayNamesMin:["So","Mé","Dë","Më","Do","Fr","Sa"],weekHeader:"W",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("lb",{buttonText:{month:"Mount",week:"Woch",day:"Dag",list:"Terminiwwersiicht"},allDayText:"Ganzen Dag",eventLimitText:"méi"})}(),function(){!function(){"use strict";function a(a,b,c,d){return b?"kelios sekundės":d?"kelių sekundžių":"kelias sekundes"}function c(a,b,c,d){return b?e(c)[0]:d?e(c)[1]:e(c)[2]}function d(a){return a%10===0||a>10&&20>a}function e(a){return g[a].split("_")}function f(a,b,f,g){var h=a+" ";return 1===a?h+c(a,b,f[0],g):b?h+(d(a)?e(f)[1]:e(f)[0]):g?h+e(f)[1]:h+(d(a)?e(f)[1]:e(f)[2])}var g={m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes",h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"},h=(b.defineLocale||b.lang).call(b,"lt",{months:{format:"sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis".split("_")},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:a,m:c,mm:f,h:c,hh:f,d:c,dd:f,M:c,MM:f,y:c,yy:f},ordinalParse:/\d{1,2}-oji/,ordinal:function(a){return a+"-oji"},week:{dow:1,doy:4}});return h}(),a.fullCalendar.datepickerLang("lt","lt",{closeText:"Uždaryti",prevText:"<Atgal",nextText:"Pirmyn>",currentText:"Šiandien",monthNames:["Sausis","Vasaris","Kovas","Balandis","Gegužė","Birželis","Liepa","Rugpjūtis","Rugsėjis","Spalis","Lapkritis","Gruodis"],monthNamesShort:["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rugp","Rugs","Spa","Lap","Gru"],dayNames:["sekmadienis","pirmadienis","antradienis","trečiadienis","ketvirtadienis","penktadienis","šeštadienis"],dayNamesShort:["sek","pir","ant","tre","ket","pen","šeš"],dayNamesMin:["Se","Pr","An","Tr","Ke","Pe","Še"],weekHeader:"SAV",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:""}),a.fullCalendar.lang("lt",{buttonText:{month:"Mėnuo",week:"Savaitė",day:"Diena",list:"Darbotvarkė"},allDayText:"Visą dieną",eventLimitText:"daugiau"})}(),function(){!function(){"use strict";function a(a,b,c){return c?b%10===1&&11!==b?a[2]:a[3]:b%10===1&&11!==b?a[0]:a[1]}function c(b,c,d){return b+" "+a(f[d],b,c)}function d(b,c,d){return a(f[d],b,c)}function e(a,b){return b?"dažas sekundes":"dažām sekundēm"}var f={m:"minūtes_minūtēm_minūte_minūtes".split("_"),mm:"minūtes_minūtēm_minūte_minūtes".split("_"),h:"stundas_stundām_stunda_stundas".split("_"),hh:"stundas_stundām_stunda_stundas".split("_"),d:"dienas_dienām_diena_dienas".split("_"),dd:"dienas_dienām_diena_dienas".split("_"),M:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),MM:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")},g=(b.defineLocale||b.lang).call(b,"lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"pēc %s",past:"pirms %s",s:e,m:d,mm:c,h:d,hh:c,d:d,dd:c,M:d,MM:c,y:d,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return g}(),a.fullCalendar.datepickerLang("lv","lv",{closeText:"Aizvērt",prevText:"Iepr.",nextText:"Nāk.",currentText:"Šodien",monthNames:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthNamesShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],dayNames:["svētdiena","pirmdiena","otrdiena","trešdiena","ceturtdiena","piektdiena","sestdiena"],dayNamesShort:["svt","prm","otr","tre","ctr","pkt","sst"],dayNamesMin:["Sv","Pr","Ot","Tr","Ct","Pk","Ss"],weekHeader:"Ned.",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("lv",{buttonText:{month:"Mēnesis",week:"Nedēļa",day:"Diena",list:"Dienas kārtība"},allDayText:"Visu dienu",eventLimitText:function(a){return"+vēl "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] HH:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("nb","nb",{closeText:"Lukk",prevText:"«Forrige",nextText:"Neste»",currentText:"I dag",monthNames:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],monthNamesShort:["jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des"],dayNamesShort:["søn","man","tir","ons","tor","fre","lør"],dayNames:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],dayNamesMin:["sø","ma","ti","on","to","fr","lø"],weekHeader:"Uke",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("nb",{buttonText:{month:"Måned",week:"Uke",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"til"})}(),function(){!function(){"use strict";var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),c="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),d=(b.defineLocale||b.lang).call(b,"nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(b,d){return/-MMM-/.test(d)?c[b.month()]:a[b.month()]},monthsParseExact:!0,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,doy:4}});return d}(),a.fullCalendar.datepickerLang("nl","nl",{closeText:"Sluiten",prevText:"←",nextText:"→",currentText:"Vandaag",monthNames:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthNamesShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],dayNames:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],dayNamesShort:["zon","maa","din","woe","don","vri","zat"],dayNamesMin:["zo","ma","di","wo","do","vr","za"],weekHeader:"Wk",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("nl",{buttonText:{month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Hele dag",eventLimitText:"extra"})}(),function(){!function(){"use strict";function a(a){return 5>a%10&&a%10>1&&~~(a/10)%10!==1}function c(b,c,d){var e=b+" ";switch(d){case"m":return c?"minuta":"minutę";case"mm":return e+(a(b)?"minuty":"minut");case"h":return c?"godzina":"godzinę";case"hh":return e+(a(b)?"godziny":"godzin");case"MM":return e+(a(b)?"miesiące":"miesięcy");case"yy":return e+(a(b)?"lata":"lat")}}var d="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),e="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"),f=(b.defineLocale||b.lang).call(b,"pl",{months:function(a,b){return""===b?"("+e[a.month()]+"|"+d[a.month()]+")":/D MMMM/.test(b)?e[a.month()]:d[a.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:c,mm:c,h:c,hh:c,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:c,y:"rok",yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return f}(),a.fullCalendar.datepickerLang("pl","pl",{closeText:"Zamknij",prevText:"<Poprzedni",nextText:"Następny>",currentText:"Dziś",monthNames:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthNamesShort:["Sty","Lu","Mar","Kw","Maj","Cze","Lip","Sie","Wrz","Pa","Lis","Gru"],dayNames:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],dayNamesShort:["Nie","Pn","Wt","Śr","Czw","Pt","So"],dayNamesMin:["N","Pn","Wt","Śr","Cz","Pt","So"],weekHeader:"Tydz",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pl",{buttonText:{month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Plan dnia"},allDayText:"Cały dzień",eventLimitText:"więcej"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"pt-br",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [às] HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"poucos segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº"});return a}(),a.fullCalendar.datepickerLang("pt-br","pt-BR",{closeText:"Fechar",prevText:"<Anterior",nextText:"Próximo>",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pt-br",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Compromissos"},allDayText:"dia inteiro",eventLimitText:function(a){return"mais +"+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"pt",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("pt","pt",{closeText:"Fechar",prevText:"Anterior",nextText:"Seguinte",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sem",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pt",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Agenda"},allDayText:"Todo o dia",eventLimitText:"mais"})}(),function(){!function(){"use strict";function a(a,b,c){var d={mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"},e=" ";return(a%100>=20||a>=100&&a%100===0)&&(e=" de "),a+e+d[c]}var c=(b.defineLocale||b.lang).call(b,"ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",m:"un minut",mm:a,h:"o oră",hh:a,d:"o zi",dd:a,M:"o lună",MM:a,y:"un an",yy:a},week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("ro","ro",{closeText:"Închide",prevText:"« Luna precedentă",nextText:"Luna următoare »",currentText:"Azi",monthNames:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthNamesShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă"],dayNamesShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm"],dayNamesMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],weekHeader:"Săpt",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ro",{buttonText:{prev:"precedentă",next:"următoare",month:"Lună",week:"Săptămână",day:"Zi",list:"Agendă"},allDayText:"Toată ziua",eventLimitText:function(a){return"+alte "+a}})}(),function(){!function(){"use strict";function a(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(b,c,d){var e={mm:c?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===d?c?"минута":"минуту":b+" "+a(e[d],+b)}var d=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i],e=(b.defineLocale||b.lang).call(b,"ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:d,longMonthsParse:d,shortMonthsParse:d,monthsRegex:/^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|сент\.|февр\.|нояб\.|июнь|янв.|июль|дек.|авг.|апр.|марта|мар[.т]|окт.|июн[яь]|июл[яь]|ма[яй])/i,monthsShortRegex:/^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|сент\.|февр\.|нояб\.|июнь|янв.|июль|дек.|авг.|апр.|марта|мар[.т]|окт.|июн[яь]|июл[яь]|ма[яй])/i,monthsStrictRegex:/^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|марта?|июн[яь]|июл[яь]|ма[яй])/i,monthsShortStrictRegex:/^(нояб\.|февр\.|сент\.|июль|янв\.|июн[яь]|мар[.т]|авг\.|апр\.|окт\.|дек\.|ма[яй])/i,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В следующее] dddd [в] LT";case 1:case 2:case 4:return"[В следующий] dddd [в] LT";case 3:case 5:case 6:return"[В следующую] dddd [в] LT"}},lastWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:c,mm:c,h:"час",hh:c,d:"день",dd:c,M:"месяц",MM:c,y:"год",yy:c},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(a){return/^(дня|вечера)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночи":12>a?"утра":17>a?"дня":"вечера"},ordinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":return a+"-й";case"D":return a+"-го";case"w":case"W":return a+"-я";default:return a}},week:{dow:1,doy:7}});return e}(),a.fullCalendar.datepickerLang("ru","ru",{closeText:"Закрыть",prevText:"<Пред",nextText:"След>",currentText:"Сегодня",monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],dayNamesShort:["вск","пнд","втр","срд","чтв","птн","сбт"],dayNamesMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Нед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ru",{buttonText:{month:"Месяц",week:"Неделя",day:"День",list:"Повестка дня"},allDayText:"Весь день",eventLimitText:function(a){return"+ ещё "+a}})}(),function(){!function(){"use strict";function a(a){return a>1&&5>a}function c(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"pár sekúnd":"pár sekundami";case"m":return c?"minúta":e?"minútu":"minútou";case"mm":return c||e?f+(a(b)?"minúty":"minút"):f+"minútami";case"h":return c?"hodina":e?"hodinu":"hodinou";case"hh":return c||e?f+(a(b)?"hodiny":"hodín"):f+"hodinami";case"d":return c||e?"deň":"dňom";case"dd":return c||e?f+(a(b)?"dni":"dní"):f+"dňami";case"M":return c||e?"mesiac":"mesiacom";case"MM":return c||e?f+(a(b)?"mesiace":"mesiacov"):f+"mesiacmi";case"y":return c||e?"rok":"rokom";case"yy":return c||e?f+(a(b)?"roky":"rokov"):f+"rokmi"}}var d="január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),e="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_"),f=(b.defineLocale||b.lang).call(b,"sk",{months:d,monthsShort:e,weekdays:"nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_št_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_št_pi_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo štvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 4:case 5:return"[minulý] dddd [o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return f}(),a.fullCalendar.datepickerLang("sk","sk",{closeText:"Zavrieť",prevText:"<Predchádzajúci",nextText:"Nasledujúci>",currentText:"Dnes",monthNames:["január","február","marec","apríl","máj","jún","júl","august","september","október","november","december"],monthNamesShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],dayNames:["nedeľa","pondelok","utorok","streda","štvrtok","piatok","sobota"],dayNamesShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob"],dayNamesMin:["Ne","Po","Ut","St","Št","Pia","So"],weekHeader:"Ty",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sk",{buttonText:{month:"Mesiac",week:"Týždeň",day:"Deň",list:"Rozvrh"},allDayText:"Celý deň",eventLimitText:function(a){return"+ďalšie: "+a}})}(),function(){!function(){"use strict";function a(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"nekaj sekund":"nekaj sekundami";case"m":return b?"ena minuta":"eno minuto";case"mm":return e+=1===a?b?"minuta":"minuto":2===a?b||d?"minuti":"minutama":5>a?b||d?"minute":"minutami":b||d?"minut":"minutami";case"h":return b?"ena ura":"eno uro";case"hh":return e+=1===a?b?"ura":"uro":2===a?b||d?"uri":"urama":5>a?b||d?"ure":"urami":b||d?"ur":"urami";case"d":return b||d?"en dan":"enim dnem";case"dd":return e+=1===a?b||d?"dan":"dnem":2===a?b||d?"dni":"dnevoma":b||d?"dni":"dnevi";case"M":return b||d?"en mesec":"enim mesecem";case"MM":return e+=1===a?b||d?"mesec":"mesecem":2===a?b||d?"meseca":"mesecema":5>a?b||d?"mesece":"meseci":b||d?"mesecev":"meseci";case"y":return b||d?"eno leto":"enim letom";case"yy":return e+=1===a?b||d?"leto":"letom":2===a?b||d?"leti":"letoma":5>a?b||d?"leta":"leti":b||d?"let":"leti"}}var c=(b.defineLocale||b.lang).call(b,"sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){ +switch(this.day()){case 0:return"[prejšnjo] [nedeljo] [ob] LT";case 3:return"[prejšnjo] [sredo] [ob] LT";case 6:return"[prejšnjo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"pred %s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("sl","sl",{closeText:"Zapri",prevText:"<Prejšnji",nextText:"Naslednji>",currentText:"Trenutni",monthNames:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],dayNames:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"],dayNamesShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],dayNamesMin:["Ne","Po","To","Sr","Če","Pe","So"],weekHeader:"Teden",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sl",{buttonText:{month:"Mesec",week:"Teden",day:"Dan",list:"Dnevni red"},allDayText:"Ves dan",eventLimitText:"več"})}(),function(){!function(){"use strict";var a={words:{m:["један минут","једне минуте"],mm:["минут","минуте","минута"],h:["један сат","једног сата"],hh:["сат","сата","сати"],dd:["дан","дана","дана"],MM:["месец","месеца","месеци"],yy:["година","године","година"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(b,c,d){var e=a.words[d];return 1===d.length?c?e[0]:e[1]:b+" "+a.correctGrammaticalCase(b,e)}},c=(b.defineLocale||b.lang).call(b,"sr-cyrl",{months:"јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар".split("_"),monthsShort:"јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.".split("_"),monthsParseExact:!0,weekdays:"недеља_понедељак_уторак_среда_четвртак_петак_субота".split("_"),weekdaysShort:"нед._пон._уто._сре._чет._пет._суб.".split("_"),weekdaysMin:"не_по_ут_ср_че_пе_су".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[данас у] LT",nextDay:"[сутра у] LT",nextWeek:function(){switch(this.day()){case 0:return"[у] [недељу] [у] LT";case 3:return"[у] [среду] [у] LT";case 6:return"[у] [суботу] [у] LT";case 1:case 2:case 4:case 5:return"[у] dddd [у] LT"}},lastDay:"[јуче у] LT",lastWeek:function(){var a=["[прошле] [недеље] [у] LT","[прошлог] [понедељка] [у] LT","[прошлог] [уторка] [у] LT","[прошле] [среде] [у] LT","[прошлог] [четвртка] [у] LT","[прошлог] [петка] [у] LT","[прошле] [суботе] [у] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"за %s",past:"пре %s",s:"неколико секунди",m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:"дан",dd:a.translate,M:"месец",MM:a.translate,y:"годину",yy:a.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("sr-cyrl","sr",{closeText:"Затвори",prevText:"<",nextText:">",currentText:"Данас",monthNames:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthNamesShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],dayNames:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],dayNamesShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],dayNamesMin:["Не","По","Ут","Ср","Че","Пе","Су"],weekHeader:"Сед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sr-cyrl",{buttonText:{month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},allDayText:"Цео дан",eventLimitText:function(a){return"+ још "+a}})}(),function(){!function(){"use strict";var a={words:{m:["jedan minut","jedne minute"],mm:["minut","minute","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mesec","meseca","meseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(b,c,d){var e=a.words[d];return 1===d.length?c?e[0]:e[1]:b+" "+a.correctGrammaticalCase(b,e)}},c=(b.defineLocale||b.lang).call(b,"sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var a=["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:"dan",dd:a.translate,M:"mesec",MM:a.translate,y:"godinu",yy:a.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("sr","sr",{closeText:"Затвори",prevText:"<",nextText:">",currentText:"Данас",monthNames:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthNamesShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],dayNames:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],dayNamesShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],dayNamesMin:["Не","По","Ут","Ср","Че","Пе","Су"],weekHeader:"Сед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sr",{buttonText:{month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},allDayText:"Цео дан",eventLimitText:function(a){return"+ још "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [kl.] HH:mm",LLLL:"dddd D MMMM YYYY [kl.] HH:mm",lll:"D MMM YYYY HH:mm",llll:"ddd D MMM YYYY HH:mm"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"[På] dddd LT",lastWeek:"[I] dddd[s] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}(e|a)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"e":1===b?"a":2===b?"a":"e";return a+c},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("sv","sv",{closeText:"Stäng",prevText:"«Förra",nextText:"Nästa»",currentText:"Idag",monthNames:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNamesShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör"],dayNames:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"],dayNamesMin:["Sö","Må","Ti","On","To","Fr","Lö"],weekHeader:"Ve",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sv",{buttonText:{month:"Månad",week:"Vecka",day:"Dag",list:"Program"},allDayText:"Heldag",eventLimitText:"till"})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),monthsParseExact:!0,weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H นาฬิกา m นาที",LTS:"H นาฬิกา m นาที s วินาที",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา H นาฬิกา m นาที",LLLL:"วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(a){return"หลังเที่ยง"===a},meridiem:function(a,b,c){return 12>a?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}});return a}(),a.fullCalendar.datepickerLang("th","th",{closeText:"ปิด",prevText:"« ย้อน",nextText:"ถัดไป »",currentText:"วันนี้",monthNames:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthNamesShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],dayNames:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัสบดี","ศุกร์","เสาร์"],dayNamesShort:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],dayNamesMin:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("th",{buttonText:{month:"เดือน",week:"สัปดาห์",day:"วัน",list:"แผนงาน"},allDayText:"ตลอดวัน",eventLimitText:"เพิ่มเติม"})}(),function(){!function(){"use strict";var a={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"},c=(b.defineLocale||b.lang).call(b,"tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinalParse:/\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,ordinal:function(b){if(0===b)return b+"'ıncı";var c=b%10,d=b%100-c,e=b>=100?100:null;return b+(a[c]||a[d]||a[e])},week:{dow:1,doy:7}});return c}(),a.fullCalendar.datepickerLang("tr","tr",{closeText:"kapat",prevText:"<geri",nextText:"ileri>",currentText:"bugün",monthNames:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthNamesShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],dayNames:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],dayNamesShort:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],dayNamesMin:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],weekHeader:"Hf",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("tr",{buttonText:{next:"ileri",month:"Ay",week:"Hafta",day:"Gün",list:"Ajanda"},allDayText:"Tüm gün",eventLimitText:"daha fazla"})}(),function(){!function(){"use strict";function a(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(b,c,d){var e={mm:c?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:c?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===d?c?"хвилина":"хвилину":"h"===d?c?"година":"годину":b+" "+a(e[d],+b)}function d(a,b){var c={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")},d=/(\[[ВвУу]\]) ?dddd/.test(b)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(b)?"genitive":"nominative";return c[d][a.day()]}function e(a){return function(){return a+"о"+(11===this.hours()?"б":"")+"] LT"}}var f=(b.defineLocale||b.lang).call(b,"uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:d,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:e("[Сьогодні "),nextDay:e("[Завтра "),lastDay:e("[Вчора "),nextWeek:e("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return e("[Минулої] dddd [").call(this);case 1:case 2:case 4:return e("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",m:c,mm:c,h:"годину",hh:c,d:"день",dd:c,M:"місяць",MM:c,y:"рік",yy:c},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(a){return/^(дня|вечора)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночі":12>a?"ранку":17>a?"дня":"вечора"},ordinalParse:/\d{1,2}-(й|го)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":case"w":case"W":return a+"-й";case"D":return a+"-го";default:return a}},week:{dow:1,doy:7}});return f}(),a.fullCalendar.datepickerLang("uk","uk",{closeText:"Закрити",prevText:"<",nextText:">",currentText:"Сьогодні",monthNames:["Січень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthNamesShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],dayNames:["неділя","понеділок","вівторок","середа","четвер","п’ятниця","субота"],dayNamesShort:["нед","пнд","вів","срд","чтв","птн","сбт"],dayNamesMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Тиж",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("uk",{buttonText:{month:"Місяць",week:"Тиждень",day:"День",list:"Порядок денний"},allDayText:"Увесь день",eventLimitText:function(a){return"+ще "+a+"..."}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"vi",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),monthsParseExact:!0,weekdays:"chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysParseExact:!0,meridiemParse:/sa|ch/i,isPM:function(a){return/^ch$/i.test(a)},meridiem:function(a,b,c){return 12>a?c?"sa":"SA":c?"ch":"CH"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY HH:mm",LLLL:"dddd, D MMMM [năm] YYYY HH:mm",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngày mai lúc] LT",nextWeek:"dddd [tuần tới lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần rồi lúc] LT",sameElse:"L"},relativeTime:{future:"%s tới",past:"%s trước",s:"vài giây",m:"một phút",mm:"%d phút",h:"một giờ",hh:"%d giờ",d:"một ngày",dd:"%d ngày",M:"một tháng",MM:"%d tháng",y:"một năm",yy:"%d năm"},ordinalParse:/\d{1,2}/,ordinal:function(a){return a},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("vi","vi",{closeText:"Đóng",prevText:"<Trước",nextText:"Tiếp>",currentText:"Hôm nay",monthNames:["Tháng Một","Tháng Hai","Tháng Ba","Tháng Tư","Tháng Năm","Tháng Sáu","Tháng Bảy","Tháng Tám","Tháng Chín","Tháng Mười","Tháng Mười Một","Tháng Mười Hai"],monthNamesShort:["Tháng 1","Tháng 2","Tháng 3","Tháng 4","Tháng 5","Tháng 6","Tháng 7","Tháng 8","Tháng 9","Tháng 10","Tháng 11","Tháng 12"],dayNames:["Chủ Nhật","Thứ Hai","Thứ Ba","Thứ Tư","Thứ Năm","Thứ Sáu","Thứ Bảy"],dayNamesShort:["CN","T2","T3","T4","T5","T6","T7"],dayNamesMin:["CN","T2","T3","T4","T5","T6","T7"],weekHeader:"Tu",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("vi",{buttonText:{month:"Tháng",week:"Tuần",day:"Ngày",list:"Lịch biểu"},allDayText:"Cả ngày",eventLimitText:function(a){return"+ thêm "+a}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm分",LTS:"Ah点m分s秒",L:"YYYY-MM-DD",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日Ah点mm分",LLLL:"YYYY年MMMD日ddddAh点mm分",l:"YYYY-MM-DD",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日Ah点mm分",llll:"YYYY年MMMD日ddddAh点mm分"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"凌晨"===b||"早上"===b||"上午"===b?a:"下午"===b||"晚上"===b?a+12:a>=11?a:a+12},meridiem:function(a,b,c){var d=100*a+b;return 600>d?"凌晨":900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:function(){return 0===this.minutes()?"[今天]Ah[点整]":"[今天]LT"},nextDay:function(){return 0===this.minutes()?"[明天]Ah[点整]":"[明天]LT"},lastDay:function(){return 0===this.minutes()?"[昨天]Ah[点整]":"[昨天]LT"},nextWeek:function(){var a,c;return a=b().startOf("week"),c=this.diff(a,"days")>=7?"[下]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},lastWeek:function(){var a,c;return a=b().startOf("week"),c=this.unix()<a.unix()?"[上]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},sameElse:"LL"},ordinalParse:/\d{1,2}(日|月|周)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"周";default:return a}},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("zh-cn","zh-CN",{closeText:"关闭",prevText:"<上月",nextText:"下月>",currentText:"今天",monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],dayNamesMin:["日","一","二","三","四","五","六"],weekHeader:"周",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),a.fullCalendar.lang("zh-cn",{buttonText:{month:"月",week:"周",day:"日",list:"日程"},allDayText:"全天",eventLimitText:function(a){return"另外 "+a+" 个"}})}(),function(){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm分",LTS:"Ah點m分s秒",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日Ah點mm分",LLLL:"YYYY年MMMD日ddddAh點mm分",l:"YYYY年MMMD日",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日Ah點mm分",llll:"YYYY年MMMD日ddddAh點mm分"},meridiemParse:/早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"早上"===b||"上午"===b?a:"中午"===b?a>=11?a:a+12:"下午"===b||"晚上"===b?a+12:void 0},meridiem:function(a,b,c){var d=100*a+b;return 900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},ordinalParse:/\d{1,2}(日|月|週)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"週";default:return a}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"1分鐘",mm:"%d分鐘",h:"1小時",hh:"%d小時",d:"1天",dd:"%d天",M:"1個月",MM:"%d個月",y:"1年",yy:"%d年"}});return a}(),a.fullCalendar.datepickerLang("zh-tw","zh-TW",{closeText:"關閉",prevText:"<上月",nextText:"下月>",currentText:"今天",monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],dayNamesMin:["日","一","二","三","四","五","六"],weekHeader:"周",dateFormat:"yy/mm/dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),a.fullCalendar.lang("zh-tw",{buttonText:{month:"月",week:"週",day:"天",list:"待辦事項"},allDayText:"全天",eventLimitText:"更多"})}(),(b.locale||b.lang).call(b,"en"),a.fullCalendar.lang("en"),a.datepicker&&a.datepicker.setDefaults(a.datepicker.regional[""])}); \ No newline at end of file diff --git a/view/css/mod_cal.css b/view/css/mod_cal.css index 184227a91..f0b5c0166 100644 --- a/view/css/mod_cal.css +++ b/view/css/mod_cal.css @@ -1,7 +1,3 @@ -.fc-scroller { - overflow: hidden !important; -} - /* fix borders */ .fc th:first-child, diff --git a/view/css/mod_events.css b/view/css/mod_events.css index 184227a91..f0b5c0166 100644 --- a/view/css/mod_events.css +++ b/view/css/mod_events.css @@ -1,7 +1,3 @@ -.fc-scroller { - overflow: hidden !important; -} - /* fix borders */ .fc th:first-child, -- cgit v1.2.3 From 7b2d54dffac5a5ee3c0ff79aee964ac0869b3142 Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Tue, 28 Jun 2016 13:44:32 +0200 Subject: fix month view in fullscreen mode --- view/tpl/event_head.tpl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/view/tpl/event_head.tpl b/view/tpl/event_head.tpl index 762bdcbb8..4397c5c9d 100755 --- a/view/tpl/event_head.tpl +++ b/view/tpl/event_head.tpl @@ -34,7 +34,13 @@ $('#events-calendar').fullCalendar('option', 'height', 'auto'); } else { - $('#events-calendar').fullCalendar('option', 'height', ''); + if($('main').hasClass('fullscreen')) { + $('#calendar').fullCalendar('option', 'height', $(window).height() - $('.section-title-wrapper').outerHeight(true) - 2); // -2 is for border width (.generic-content-wrapper top and bottom) of .generic-content-wrapper + + } + else { + $('#calendar').fullCalendar('option', 'height', ''); + } } $('#title').text(view.title); } -- cgit v1.2.3 From dcc65bbacb81801b5e138795c18ef9e740dbd26c Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Tue, 28 Jun 2016 21:45:14 +0200 Subject: update to sabre/dav to version 3.2.0 --- vendor/autoload.php | 2 +- vendor/composer/autoload_files.php | 4 +- vendor/composer/autoload_real.php | 14 +- vendor/composer/autoload_static.php | 12 +- vendor/composer/installed.json | 324 ++++++++++----------- vendor/sabre/dav/CHANGELOG.md | 31 ++ vendor/sabre/dav/bin/migrateto32.php | 2 +- vendor/sabre/dav/lib/CalDAV/Backend/PDO.php | 2 +- .../CalDAV/Xml/Property/ScheduleCalendarTransp.php | 22 +- vendor/sabre/dav/lib/DAV/Auth/Backend/File.php | 2 +- vendor/sabre/dav/lib/DAV/FSExt/Directory.php | 10 +- vendor/sabre/dav/lib/DAV/Version.php | 2 +- .../sabre/dav/lib/DAV/Xml/Property/ShareAccess.php | 2 +- .../lib/DAV/Xml/Property/SupportedMethodSet.php | 11 +- vendor/sabre/dav/lib/DAVACL/Plugin.php | 5 - .../tests/Sabre/CalDAV/Backend/AbstractPDOTest.php | 10 + .../dav/tests/Sabre/DAV/Auth/Backend/FileTest.php | 3 +- .../sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php | 19 ++ .../sabre/dav/tests/Sabre/DAV/ServerEventsTest.php | 4 +- .../tests/Sabre/DAVACL/ExpandPropertiesTest.php | 7 + .../tests/Sabre/DAVACL/PluginPropertiesTest.php | 55 ++++ 21 files changed, 319 insertions(+), 224 deletions(-) diff --git a/vendor/autoload.php b/vendor/autoload.php index bb2d0206c..f9e0189d7 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4::getLoader(); +return ComposerAutoloaderInit02c7a5bb99a87a4c8dbf069d69b1a15c::getLoader(); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index a78cbe6fb..24ffd3718 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -7,10 +7,10 @@ $baseDir = dirname($vendorDir); return array( '383eaff206634a77a1be54e64e6459c7' => $vendorDir . '/sabre/uri/lib/functions.php', + '3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php', + '93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/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', ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index d0dfe0ebc..16f7dea85 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4 +class ComposerAutoloaderInit02c7a5bb99a87a4c8dbf069d69b1a15c { private static $loader; @@ -19,15 +19,15 @@ class ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit02c7a5bb99a87a4c8dbf069d69b1a15c', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit02c7a5bb99a87a4c8dbf069d69b1a15c', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION'); if ($useStaticLoader) { require_once __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::getInitializer($loader)); } else { $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -48,19 +48,19 @@ class ComposerAutoloaderInit83c487173ca2d4f0ca8866f7816b9ab4 $loader->register(true); if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::$files; + $includeFiles = Composer\Autoload\ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::$files; } else { $includeFiles = require __DIR__ . '/autoload_files.php'; } foreach ($includeFiles as $fileIdentifier => $file) { - composerRequire83c487173ca2d4f0ca8866f7816b9ab4($fileIdentifier, $file); + composerRequire02c7a5bb99a87a4c8dbf069d69b1a15c($fileIdentifier, $file); } return $loader; } } -function composerRequire83c487173ca2d4f0ca8866f7816b9ab4($fileIdentifier, $file) +function composerRequire02c7a5bb99a87a4c8dbf069d69b1a15c($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { require $file; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index afafda646..15dc46f55 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,15 +4,15 @@ namespace Composer\Autoload; -class ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4 +class ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c { public static $files = array ( '383eaff206634a77a1be54e64e6459c7' => __DIR__ . '/..' . '/sabre/uri/lib/functions.php', + '3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php', + '93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/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', ); @@ -83,9 +83,9 @@ class ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4 public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::$prefixDirsPsr4; - $loader->prefixesPsr0 = ComposerStaticInit83c487173ca2d4f0ca8866f7816b9ab4::$prefixesPsr0; + $loader->prefixLengthsPsr4 = ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::$prefixesPsr0; }, null, ClassLoader::class); } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 4c5a019d8..835190d7f 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,44 +1,4 @@ [ - { - "name": "psr/log", - "version": "1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", - "shasum": "" - }, - "time": "2012-12-21 11:40:51", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "Psr\\Log\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "keywords": [ - "log", - "psr", - "psr-3" - ] - }, { "name": "sabre/uri", "version": "1.1.0", @@ -92,122 +52,6 @@ "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.2", @@ -370,19 +214,175 @@ "xCard" ] }, + { + "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": "psr/log", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "time": "2012-12-21 11:40:51", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ] + }, { "name": "sabre/dav", - "version": "3.2.0-beta1", - "version_normalized": "3.2.0.0-beta1", + "version": "3.2.0", + "version_normalized": "3.2.0.0", "source": { "type": "git", "url": "https://github.com/fruux/sabre-dav.git", - "reference": "32524c79a5890056123aa64499719e7c061bfde8" + "reference": "5b9737cc2f0182e368d14c80df7f6b2d77dc1457" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruux/sabre-dav/zipball/32524c79a5890056123aa64499719e7c061bfde8", - "reference": "32524c79a5890056123aa64499719e7c061bfde8", + "url": "https://api.github.com/repos/fruux/sabre-dav/zipball/5b9737cc2f0182e368d14c80df7f6b2d77dc1457", + "reference": "5b9737cc2f0182e368d14c80df7f6b2d77dc1457", "shasum": "" }, "require": { @@ -413,7 +413,7 @@ "ext-curl": "*", "ext-pdo": "*" }, - "time": "2016-05-21 03:49:31", + "time": "2016-06-28 02:44:05", "bin": [ "bin/sabredav", "bin/naturalselection" diff --git a/vendor/sabre/dav/CHANGELOG.md b/vendor/sabre/dav/CHANGELOG.md index 079650965..d8a3898c3 100644 --- a/vendor/sabre/dav/CHANGELOG.md +++ b/vendor/sabre/dav/CHANGELOG.md @@ -1,12 +1,26 @@ ChangeLog ========= +3.2.0 (2016-06-27) +------------------ + +* The default ACL rules allow an unauthenticated user to read information + about nodes that don't have their own ACL defined. This was a security + problem. +* The zip release ships with [sabre/vobject 4.1.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.2][xml]. + + 3.2.0-beta1 (2016-05-20) ------------------------ * #833: Calendars throw exceptions when the sharing plugin is not enabled. * #834: Return vCards exactly as they were stored if we don't need to convert in between versions. +* The zip release ships with [sabre/vobject 4.1.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. 3.2.0-alpha1 (2016-05-09) @@ -70,6 +84,23 @@ ChangeLog [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml]. +3.1.5 (????-??-??) +------------------ + +* Fixed: Creating a new calendar on some MySQL configurations caused an error. + + +3.1.4 (2016-05-28) +------------------ + +* #834: Backport from `master`: Return vCards exactly as they were stored if + we don't need to convert in between versions. This should speed up many + large addressbook syncs sometimes up to 50%. +* The zip release ships with [sabre/vobject 4.1.0][vobj], + [sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt], + [sabre/uri 1.1.0][uri] and [sabre/xml 1.4.2][xml]. + + 3.1.3 (2016-04-06) ------------------ diff --git a/vendor/sabre/dav/bin/migrateto32.php b/vendor/sabre/dav/bin/migrateto32.php index 59732b511..7567aeb60 100644 --- a/vendor/sabre/dav/bin/migrateto32.php +++ b/vendor/sabre/dav/bin/migrateto32.php @@ -237,7 +237,7 @@ if ($migrateCalendars) { CREATE TABLE calendars ( id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1', - components VARBINARY(20) + components VARBINARY(21) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; SQL ); diff --git a/vendor/sabre/dav/lib/CalDAV/Backend/PDO.php b/vendor/sabre/dav/lib/CalDAV/Backend/PDO.php index b1c013d62..95f1d49a6 100644 --- a/vendor/sabre/dav/lib/CalDAV/Backend/PDO.php +++ b/vendor/sabre/dav/lib/CalDAV/Backend/PDO.php @@ -1502,7 +1502,7 @@ SQL; */ function setPublishStatus($calendarId, $value) { - throw new \Exception('Not implemented'); + throw new \Sabre\DAV\Exception\NotImplemented('Not implemented'); } diff --git a/vendor/sabre/dav/lib/CalDAV/Xml/Property/ScheduleCalendarTransp.php b/vendor/sabre/dav/lib/CalDAV/Xml/Property/ScheduleCalendarTransp.php index 4a253e008..a82b8eff7 100644 --- a/vendor/sabre/dav/lib/CalDAV/Xml/Property/ScheduleCalendarTransp.php +++ b/vendor/sabre/dav/lib/CalDAV/Xml/Property/ScheduleCalendarTransp.php @@ -4,8 +4,8 @@ namespace Sabre\CalDAV\Xml\Property; use Sabre\Xml\Element; use Sabre\Xml\Reader; +use Sabre\Xml\Deserializer; use Sabre\Xml\Writer; -use Sabre\Xml\Element\Elements; use Sabre\CalDAV\Plugin; /** @@ -116,23 +116,13 @@ class ScheduleCalendarTransp implements Element { */ static function xmlDeserialize(Reader $reader) { - $elems = Elements::xmlDeserialize($reader); + $elems = Deserializer\enum($reader, Plugin::NS_CALDAV); - $value = null; - - foreach ($elems as $elem) { - switch ($elem) { - case '{' . Plugin::NS_CALDAV . '}opaque' : - $value = self::OPAQUE; - break; - case '{' . Plugin::NS_CALDAV . '}transparent' : - $value = self::TRANSPARENT; - break; - } + if (in_array('transparent', $elems)) { + $value = self::TRANSPARENT; + } else { + $value = self::OPAQUE; } - if (is_null($value)) - return null; - return new self($value); } diff --git a/vendor/sabre/dav/lib/DAV/Auth/Backend/File.php b/vendor/sabre/dav/lib/DAV/Auth/Backend/File.php index 6756e68df..3a687d747 100644 --- a/vendor/sabre/dav/lib/DAV/Auth/Backend/File.php +++ b/vendor/sabre/dav/lib/DAV/Auth/Backend/File.php @@ -25,7 +25,7 @@ class File extends AbstractDigest { /** * Creates the backend object. * - * If the filename argument is passed in, it will parse out the specified file fist. + * If the filename argument is passed in, it will parse out the specified file first. * * @param string|null $filename */ diff --git a/vendor/sabre/dav/lib/DAV/FSExt/Directory.php b/vendor/sabre/dav/lib/DAV/FSExt/Directory.php index 648079e26..dd5f992db 100644 --- a/vendor/sabre/dav/lib/DAV/FSExt/Directory.php +++ b/vendor/sabre/dav/lib/DAV/FSExt/Directory.php @@ -131,12 +131,7 @@ class Directory extends Node implements DAV\ICollection, DAV\IQuota, DAV\IMoveTa foreach ($iterator as $entry) { - $node = $entry->getFilename(); - - if ($node === '.sabredav') - continue; - - $nodes[] = $this->getChild($node); + $nodes[] = $this->getChild($entry->getFilename()); } return $nodes; @@ -153,9 +148,6 @@ class Directory extends Node implements DAV\ICollection, DAV\IQuota, DAV\IMoveTa // Deleting all children foreach ($this->getChildren() as $child) $child->delete(); - // Removing resource info, if its still around - if (file_exists($this->path . '/.sabredav')) unlink($this->path . '/.sabredav'); - // Removing the directory itself rmdir($this->path); diff --git a/vendor/sabre/dav/lib/DAV/Version.php b/vendor/sabre/dav/lib/DAV/Version.php index 5430b967c..2fda85db8 100644 --- a/vendor/sabre/dav/lib/DAV/Version.php +++ b/vendor/sabre/dav/lib/DAV/Version.php @@ -14,6 +14,6 @@ class Version { /** * Full version number */ - const VERSION = '3.2.0-beta1'; + const VERSION = '3.2.0'; } diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php b/vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php index f27af5415..a3fc6b0e1 100644 --- a/vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php +++ b/vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php @@ -127,7 +127,7 @@ class ShareAccess implements Element { switch ($elem['name']) { case '{DAV:}not-shared' : return new self(SharingPlugin::ACCESS_NOTSHARED); - case '{DAV:}sharedowner' : + case '{DAV:}shared-owner' : return new self(SharingPlugin::ACCESS_SHAREDOWNER); case '{DAV:}read' : return new self(SharingPlugin::ACCESS_READ); diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/SupportedMethodSet.php b/vendor/sabre/dav/lib/DAV/Xml/Property/SupportedMethodSet.php index 56b418db6..7641f3739 100644 --- a/vendor/sabre/dav/lib/DAV/Xml/Property/SupportedMethodSet.php +++ b/vendor/sabre/dav/lib/DAV/Xml/Property/SupportedMethodSet.php @@ -32,16 +32,11 @@ class SupportedMethodSet implements XmlSerializable, HtmlOutput { /** * Creates the property * - * Any reports passed in the constructor - * should be valid report-types in clark-notation. - * - * Either a string or an array of strings must be passed. - * - * @param string|string[] $methods + * @param string[] $methods */ - function __construct($methods = null) { + function __construct(array $methods) { - $this->methods = (array)$methods; + $this->methods = $methods; } diff --git a/vendor/sabre/dav/lib/DAVACL/Plugin.php b/vendor/sabre/dav/lib/DAVACL/Plugin.php index 59a7b0922..8e912309e 100644 --- a/vendor/sabre/dav/lib/DAVACL/Plugin.php +++ b/vendor/sabre/dav/lib/DAVACL/Plugin.php @@ -307,11 +307,6 @@ class Plugin extends DAV\ServerPlugin { 'protected' => true, 'privilege' => '{DAV:}all', ], - [ - 'principal' => '{DAV:}unauthenticated', - 'protected' => true, - 'privilege' => '{DAV:}read', - ], ]; /** diff --git a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/AbstractPDOTest.php b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/AbstractPDOTest.php index 35d6da353..2a00f7925 100644 --- a/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/AbstractPDOTest.php +++ b/vendor/sabre/dav/tests/Sabre/CalDAV/Backend/AbstractPDOTest.php @@ -1418,4 +1418,14 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase { } + /** + * @expectedException \Sabre\DAV\Exception\NotImplemented + */ + function testSetPublishStatus() { + + $backend = new PDO($this->pdo); + $backend->setPublishStatus([1, 1], true); + + } + } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/FileTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/FileTest.php index 9b66d642f..f694f4806 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/FileTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/FileTest.php @@ -23,8 +23,7 @@ class FileTest extends \PHPUnit_Framework_TestCase { function testLoadFileBroken() { file_put_contents(SABRE_TEMPDIR . '/backend', 'user:realm:hash'); - $file = new File(); - $file->loadFile(SABRE_TEMPDIR . '/backend'); + $file = new File(SABRE_TEMPDIR . '/backend'); } diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php index 3ed79a7da..b566dd757 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/PluginTest.php @@ -48,6 +48,25 @@ class PluginTest extends \PHPUnit_Framework_TestCase { } + /** + * @depends testAuthenticateFail + */ + function testAuthenticateFailDontAutoRequire() { + + $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla')); + $backend = new Backend\Mock(); + $backend->fail = true; + + $plugin = new Plugin($backend); + $plugin->autoRequireLogin = false; + $fakeServer->addPlugin($plugin); + $this->assertTrue( + $fakeServer->emit('beforeMethod', [new HTTP\Request(), new HTTP\Response()]) + ); + $this->assertEquals(1, count($plugin->getLoginFailedReasons())); + + } + /** * @depends testAuthenticate */ diff --git a/vendor/sabre/dav/tests/Sabre/DAV/ServerEventsTest.php b/vendor/sabre/dav/tests/Sabre/DAV/ServerEventsTest.php index 6ac20d2da..4c576f108 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/ServerEventsTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/ServerEventsTest.php @@ -31,7 +31,9 @@ class ServerEventsTest extends AbstractServer { function testAfterResponse() { - $mock = $this->getMock('stdClass', ['afterResponseCallback']); + $mock = $this->getMockBuilder('stdClass') + ->setMethods(['afterResponseCallback']) + ->getMock(); $mock->expects($this->once())->method('afterResponseCallback'); $this->server->on('afterResponse', [$mock, 'afterResponseCallback']); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/ExpandPropertiesTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/ExpandPropertiesTest.php index 0612b5474..91de64372 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/ExpandPropertiesTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/ExpandPropertiesTest.php @@ -34,6 +34,13 @@ class ExpandPropertiesTest extends \PHPUnit_Framework_TestCase { $fakeServer->httpResponse = new HTTP\ResponseMock(); $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; + // Anyone can do anything + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ] + ]); $this->assertTrue($plugin instanceof Plugin); $fakeServer->addPlugin($plugin); diff --git a/vendor/sabre/dav/tests/Sabre/DAVACL/PluginPropertiesTest.php b/vendor/sabre/dav/tests/Sabre/DAVACL/PluginPropertiesTest.php index 5762ac902..fb42efba7 100644 --- a/vendor/sabre/dav/tests/Sabre/DAVACL/PluginPropertiesTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAVACL/PluginPropertiesTest.php @@ -11,6 +11,13 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); + //Anyone can do anything $plugin->principalCollectionSet = [ 'principals1', 'principals2', @@ -47,6 +54,12 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $plugin = new DAV\Auth\Plugin(new DAV\Auth\Backend\Mock()); $fakeServer->addPlugin($plugin); $plugin = new Plugin(); + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); $fakeServer->addPlugin($plugin); @@ -80,6 +93,12 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); $server = new DAV\Server(); $server->addPlugin($plugin); @@ -140,6 +159,12 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); $nodes = [ new MockACLNode('foo', [ @@ -227,6 +252,12 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { //$fakeServer->addPlugin($plugin); $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); $fakeServer->addPlugin($plugin); $requestedProperties = [ @@ -256,6 +287,12 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { //$fakeServer->addPlugin($plugin); $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); $fakeServer->addPlugin($plugin); $requestedProperties = [ @@ -286,6 +323,12 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { //$fakeServer->addPlugin($plugin); $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); $fakeServer->addPlugin($plugin); $requestedProperties = [ @@ -315,6 +358,12 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; $fakeServer->addPlugin($plugin); + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); $requestedProperties = [ '{DAV:}group-membership', @@ -343,6 +392,12 @@ class PluginPropertiesTest extends \PHPUnit_Framework_TestCase { $plugin = new Plugin(); $plugin->allowUnauthenticatedAccess = false; $fakeServer->addPlugin($plugin); + $plugin->setDefaultACL([ + [ + 'principal' => '{DAV:}all', + 'privilege' => '{DAV:}all', + ], + ]); $requestedProperties = [ '{DAV:}displayname', -- cgit v1.2.3 From 7d62e087c65d964282171dd736e337cba135610f Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Tue, 28 Jun 2016 13:36:48 -0700 Subject: identity_export_year() was a bit short-sighted. We really require arbitrary date ranges. A new function was created to tackle this - channel_export_items() which takes a channel, and a start and finish date. Finish date will default to "now" if not set. Will be working this into the interface under a module named "export_items" which will correspond closely to the existing "import_items" module you'll need to do the reverse operation. Will also make it available via the API. Once that is complete, I anticipate removing identity_export_year() as it will then be somewhat redundant, and modifying the documentation on the channel export page accordingly. Note: the function works strictly in GMT so an interface would need to convert from channel local time. --- Zotlabs/Lib/SuperCurl.php | 2 +- include/channel.php | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Lib/SuperCurl.php b/Zotlabs/Lib/SuperCurl.php index fd47c399c..1c8583ff5 100644 --- a/Zotlabs/Lib/SuperCurl.php +++ b/Zotlabs/Lib/SuperCurl.php @@ -64,9 +64,9 @@ class SuperCurl { $this->auth = $v; break; case 'magicauth': + // currently experimental $this->magicauth = $v; \Zotlabs\Daemon\Master::Summon([ 'CurlAuth', $v ]); - sleep(2); break; case 'custom': $this->request_method = $v; diff --git a/include/channel.php b/include/channel.php index 913768017..95506ed78 100644 --- a/include/channel.php +++ b/include/channel.php @@ -747,6 +747,44 @@ function identity_export_year($channel_id,$year,$month = 0) { return $ret; } +// export items within an arbitrary date range. Date/time is in UTC. + +function channel_export_items($channel_id,$start,$finish) { + + if(! $start) + return array(); + else + $start = datetime_convert('UTC','UTC',$start); + + $finish = datetime_convert('UTC','UTC',(($finish) ? $finish : 'now')); + if($finish < $start) + return array(); + + $ret = array(); + + $ch = channelx_by_n($channel_id); + if($ch) { + $ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()]; + } + + $r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created", + intval(ITEM_TYPE_POST), + intval($channel_id), + dbesc($start), + dbesc($finish) + ); + + if($r) { + $ret['item'] = array(); + xchan_query($r); + $r = fetch_post_tags($r,true); + foreach($r as $rr) + $ret['item'][] = encode_item($rr,true); + } + + return $ret; +} + /** * @brief Loads a profile into the App structure. -- cgit v1.2.3 From 715b1667d928175c0fac5832b998d9ded92974a3 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Tue, 28 Jun 2016 20:48:43 -0700 Subject: readability --- Zotlabs/Module/Viewconnections.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php index 7523c259b..4364d482a 100644 --- a/Zotlabs/Module/Viewconnections.php +++ b/Zotlabs/Module/Viewconnections.php @@ -10,8 +10,11 @@ class Viewconnections extends \Zotlabs\Web\Controller { if(observer_prohibited()) { return; } - if(argc() > 1) + + if(argc() > 1) { profile_load(argv(1)); + } + } function get() { -- cgit v1.2.3 From f098600c41553bc47267a61fb47a4957046e696e Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Wed, 29 Jun 2016 23:04:34 +0200 Subject: missing backslash leads to wsod on refresh permissions --- Zotlabs/Module/Connedit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index feed9cb1a..7db4950b1 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -433,7 +433,7 @@ class Connedit extends \Zotlabs\Web\Controller { else { // if you are on a different network we'll force a refresh of the connection basic info - Zotlabs\Daemon\Master::Summon(array('Notifier','permission_update',$contact_id)); + \Zotlabs\Daemon\Master::Summon(array('Notifier','permission_update',$contact_id)); } goaway(z_root() . '/connedit/' . $contact_id); } -- cgit v1.2.3 From 2e93a09d83f16f12796ff4edc1aca09339ae2ccf Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Wed, 29 Jun 2016 17:31:48 -0700 Subject: stream large photos through buffered I/O if possible --- Zotlabs/Module/Photo.php | 30 +++++++++++++++++++++++++++--- include/attach.php | 2 +- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index 5148c4a94..66aaec49f 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module; require_once('include/security.php'); +require_once('include/attach.php'); require_once('include/photo/photo_driver.php'); @@ -10,6 +11,8 @@ class Photo extends \Zotlabs\Web\Controller { function init() { $prvcachecontrol = false; + $streaming = null; + $channel = null; switch(argc()) { case 4: @@ -131,6 +134,8 @@ class Photo extends \Zotlabs\Web\Controller { $sql_extra = permissions_sql($r[0]['uid']); + $channel = channelx_by_n($r[0]['uid']); + // Now we'll see if we can access the photo $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d $sql_extra LIMIT 1", @@ -141,8 +146,9 @@ class Photo extends \Zotlabs\Web\Controller { if($r && $allowed) { $data = dbunescbin($r[0]['content']); $mimetype = $r[0]['mimetype']; - if(intval($r[0]['os_storage'])) - $data = file_get_contents($data); + if(intval($r[0]['os_storage'])) { + $streaming = $data; + } } else { @@ -242,7 +248,25 @@ class Photo extends \Zotlabs\Web\Controller { header("Cache-Control: max-age=" . $cache); } - echo $data; + + // If it's a file resource, stream it. + + if($streaming && $channel) { + if(strpos($streaming,'store') !== false) + $istream = fopen($streaming,'rb'); + else + $istream = fopen('store/' . $channel['channel_address'] . '/' . $streaming,'rb'); + $ostream = fopen('php://output','wb'); + if($istream && $ostream) { + pipe_streams($istream,$ostream); + fclose($istream); + fclose($ostream); + } + } + else { + echo $data; + } + killme(); // NOTREACHED } diff --git a/include/attach.php b/include/attach.php index dbcb0f930..b3ddfee88 100644 --- a/include/attach.php +++ b/include/attach.php @@ -1468,7 +1468,7 @@ function find_filename_by_hash($channel_id, $attachHash) { function pipe_streams($in, $out) { $size = 0; while (!feof($in)) - $size += fwrite($out, fread($in, 8192)); + $size += fwrite($out, fread($in, 16384)); return $size; } -- cgit v1.2.3 From df4ff26845ea2868998c6a05397dc8e3aa07ba98 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Wed, 29 Jun 2016 17:53:59 -0700 Subject: only request geolocation permission if we're creating a post. --- view/tpl/jot-header.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/tpl/jot-header.tpl b/view/tpl/jot-header.tpl index f3dd8cafe..9953875ef 100755 --- a/view/tpl/jot-header.tpl +++ b/view/tpl/jot-header.tpl @@ -7,6 +7,7 @@ var pretext = '{{$pretext}}'; function initEditor(cb){ if (editor==false){ $("#profile-jot-text-loading").spin('small').show(); + {{$geotag}} if(plaintext == 'none') { $("#profile-jot-text-loading").spin(false).hide(); $("#profile-jot-text").css({ 'height': 200, 'color': '#000', 'line-height': 'inherit' }); @@ -362,7 +363,6 @@ function enableOnUser(){ $('#profile-nolocation-wrapper').attr('disabled', true); } - {{$geotag}} var initializeEmbedPhotoDialog = function () { $('.embed-photo-selected-photo').each(function (index) { -- cgit v1.2.3 From 9ef710c557fcc4ea01c87e03fd7a477eb037f09c Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Wed, 29 Jun 2016 20:59:00 -0700 Subject: provide wiki as a feature (default is on so there aren't any surprises) and add to channel menu and profile tabs --- Zotlabs/Module/Wiki.php | 15 +++++++++++++++ include/conversation.php | 16 +++++++++++----- include/features.php | 1 + include/nav.php | 2 ++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 38b49effc..2f22f0a81 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -25,8 +25,18 @@ class Wiki extends \Zotlabs\Web\Controller { } function get() { + + if(observer_prohibited(true)) { + return login(); + } + + $tab = 'wiki'; + + require_once('include/wiki.php'); require_once('include/acl_selectors.php'); + require_once('include/conversation.php'); + // TODO: Combine the interface configuration into a unified object // Something like $interface = array('new_page_button' => false, 'new_wiki_button' => false, ...) $wiki_owner = false; @@ -151,6 +161,11 @@ class Wiki extends \Zotlabs\Web\Controller { ) ); + $is_owner = ((local_channel()) && (local_channel() == \App::$profile['profile_uid']) ? true : false); + + $o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']); + + $o .= replace_macros(get_markup_template('wiki.tpl'),array( '$wikiheaderName' => $wikiheaderName, '$wikiheaderPage' => $wikiheaderPage, diff --git a/include/conversation.php b/include/conversation.php index d2d4ffca0..957dbf8e9 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1703,13 +1703,19 @@ function profile_tabs($a, $is_owner = false, $nickname = null){ 'title' => t('Manage Webpages'), 'id' => 'webpages-tab', ); - } else { - /** - * @FIXME we probably need a listing of events that were created by - * this channel and are visible to the observer - */ + } + + if(feature_enabled($uid,'wiki') && (! UNO)) { + $tabs[] = array( + 'label' => t('Wiki'), + 'url' => z_root() . '/wiki/' . $nickname, + 'sel' => ((argv(0) == 'wiki') ? 'active' : ''), + 'title' => t('Wiki'), + 'id' => 'wiki-tab', + ); } + $arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => (($tab) ? $tab : false), 'tabs' => $tabs); call_hooks('profile_tabs', $arr); diff --git a/include/features.php b/include/features.php index 6d38bcfb4..660ea2975 100644 --- a/include/features.php +++ b/include/features.php @@ -52,6 +52,7 @@ function get_features($filtered = true) { array('advanced_profiles', t('Advanced Profiles'), t('Additional profile sections and selections'),false,get_config('feature_lock','advanced_profiles')), array('profile_export', t('Profile Import/Export'), t('Save and load profile details across sites/channels'),false,get_config('feature_lock','profile_export')), array('webpages', t('Web Pages'), t('Provide managed web pages on your channel'),false,get_config('feature_lock','webpages')), + array('wiki', t('Wiki'), t('Provide a wiki for your channel'),true,get_config('feature_lock','wiki')), array('hide_rating', t('Hide Rating'), t('Hide the rating buttons on your channel and profile pages. Note: People can still rate you somewhere else.'),false,get_config('feature_lock','hide_rating')), array('private_notes', t('Private Notes'), t('Enables a tool to store notes and reminders (note: not encrypted)'),false,get_config('feature_lock','private_notes')), array('nav_channel_select', t('Navigation Channel Select'), t('Change channels directly from within the navigation dropdown menu'),false,get_config('feature_lock','nav_channel_select')), diff --git a/include/nav.php b/include/nav.php index 21e9d2c3a..6a79b6530 100644 --- a/include/nav.php +++ b/include/nav.php @@ -104,6 +104,8 @@ EOT; if(feature_enabled($channel['channel_id'],'webpages') && (! UNO)) $nav['usermenu'][] = Array('webpages/' . $channel['channel_address'],t('Webpages'),"",t('Your webpages'),'webpages_nav_btn'); + if(feature_enabled($channel['channel_id'],'wiki') && (! UNO)) + $nav['usermenu'][] = Array('wiki/' . $channel['channel_address'],t('Wiki'),"",t('Your wiki'),'wiki_nav_btn'); } else { if(! get_account_id()) { -- cgit v1.2.3 From 339e620738ed90d18fdfb7e83b637b7d0e50f56e Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Wed, 29 Jun 2016 21:03:53 -0700 Subject: wiki featured disabled by default in UNO. --- include/features.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/features.php b/include/features.php index 660ea2975..2d71aa9be 100644 --- a/include/features.php +++ b/include/features.php @@ -52,7 +52,7 @@ function get_features($filtered = true) { array('advanced_profiles', t('Advanced Profiles'), t('Additional profile sections and selections'),false,get_config('feature_lock','advanced_profiles')), array('profile_export', t('Profile Import/Export'), t('Save and load profile details across sites/channels'),false,get_config('feature_lock','profile_export')), array('webpages', t('Web Pages'), t('Provide managed web pages on your channel'),false,get_config('feature_lock','webpages')), - array('wiki', t('Wiki'), t('Provide a wiki for your channel'),true,get_config('feature_lock','wiki')), + array('wiki', t('Wiki'), t('Provide a wiki for your channel'),((UNO) ? false : true),get_config('feature_lock','wiki')), array('hide_rating', t('Hide Rating'), t('Hide the rating buttons on your channel and profile pages. Note: People can still rate you somewhere else.'),false,get_config('feature_lock','hide_rating')), array('private_notes', t('Private Notes'), t('Enables a tool to store notes and reminders (note: not encrypted)'),false,get_config('feature_lock','private_notes')), array('nav_channel_select', t('Navigation Channel Select'), t('Change channels directly from within the navigation dropdown menu'),false,get_config('feature_lock','nav_channel_select')), -- cgit v1.2.3 From bfe84a9ff753d4d9834ea24ad65edfef3561458c Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Wed, 29 Jun 2016 22:46:47 -0700 Subject: templatise the Dreport page and add a redeliver option for when things stuff up badly. --- Zotlabs/Module/Dreport.php | 52 ++++++++++++++++++++++++++++++++++++++-------- view/tpl/dreport.tpl | 21 +++++++++++++++++++ 2 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 view/tpl/dreport.tpl diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php index e8709c952..904646d5d 100644 --- a/Zotlabs/Module/Dreport.php +++ b/Zotlabs/Module/Dreport.php @@ -16,7 +16,24 @@ class Dreport extends \Zotlabs\Web\Controller { $channel = \App::get_channel(); $mid = ((argc() > 1) ? argv(1) : ''); - + + if($mid === 'push') { + $table = 'push'; + $mid = ((argc() > 2) ? argv(2) : ''); + if($mid) { + $i = q("select id from item where mid = '%s' and author_xchan = '%s' and uid = %d", + dbesc($mid), + dbesc($channel['channel_hash']), + intval($channel['channel_id']) + ); + if($i) { + \Zotlabs\Daemon\Master::Summon([ 'Notifier', 'edit_post', $i[0]['id'] ]); + } + } + sleep(3); + goaway(z_root() . '/dreport/' . urlencode($mid)); + } + if($mid === 'mail') { $table = 'mail'; $mid = ((argc() > 2) ? argv(2) : ''); @@ -60,9 +77,10 @@ class Dreport extends \Zotlabs\Web\Controller { return; } - $o .= '<div class="generic-content-wrapper-styled">'; - $o .= '<h2>' . sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...' . '</h2>'; - $o .= '<table>'; +// $o .= '<div class="generic-content-wrapper-styled">'; +// $o .= '<h2>' . sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...' . '</h2>'; + +// $o .= '<table>'; for($x = 0; $x < count($r); $x++ ) { $r[$x]['name'] = escape_tags(substr($r[$x]['dreport_recip'],strpos($r[$x]['dreport_recip'],' '))); @@ -119,13 +137,29 @@ class Dreport extends \Zotlabs\Web\Controller { } usort($r,'self::dreport_gravity_sort'); - - + + $entries = array(); foreach($r as $rr) { - $o .= '<tr><td width="40%">' . $rr['name'] . '</td><td width="20%">' . escape_tags($rr['dreport_result']) . '</td><td width="20%">' . escape_tags($rr['dreport_time']) . '</td></tr>'; + $entries[] = [ + 'name' => $rr['name'], + 'result' => escape_tags($rr['dreport_result']), + 'time' => escape_tags($rr['dreport_time']) + ]; } - $o .= '</table>'; - $o .= '</div>'; + + $o = replace_macros(get_markup_template('dreport.tpl'), array( + '$title' => sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...', + '$table' => $table, + '$mid' => urlencode($mid), + '$push' => t('Redeliver'), + '$entries' => $entries + )); + +// foreach($r as $rr) { +// $o .= '<tr><td width="40%">' . $rr['name'] . '</td><td width="20%">' . escape_tags($rr['dreport_result']) . '</td><td width="20%">' . escape_tags($rr['dreport_time']) . '</td></tr>'; +// } +// $o .= '</table>'; +// $o .= '</div>'; return $o; diff --git a/view/tpl/dreport.tpl b/view/tpl/dreport.tpl new file mode 100644 index 000000000..7d5524a6a --- /dev/null +++ b/view/tpl/dreport.tpl @@ -0,0 +1,21 @@ +<div class="generic-content-wrapper"> + <div class="section-title-wrapper"> + {{if $table == 'item'}} + <a href="dreport/push/{{$mid}}"><button class="btn btn-default btn-xs pull-right">{{$push}}</button></a> + {{/if}} + <h2>{{$title}}</h2> + </div> + + <div> + <table> + {{if $entries}} + {{foreach $entries as $e}} + <tr> + <td width="40%">{{$e.name}}</td> + <td width="20%">{{$e.result}}</td> + <td width="20%">{{$e.time}}</td> + </tr> + {{/foreach}} + {{/if}} + </table> +</div> -- cgit v1.2.3 From 1cc816f66223d5ea5043d4c667478503293414b8 Mon Sep 17 00:00:00 2001 From: redmatrix <git@macgirvin.com> Date: Wed, 29 Jun 2016 22:53:18 -0700 Subject: dreport: convert timestamp to channel localtime and get rid of old pre-template code --- Zotlabs/Module/Dreport.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php index 904646d5d..17ed6515e 100644 --- a/Zotlabs/Module/Dreport.php +++ b/Zotlabs/Module/Dreport.php @@ -76,12 +76,7 @@ class Dreport extends \Zotlabs\Web\Controller { notice( t('no results') . EOL); return; } - -// $o .= '<div class="generic-content-wrapper-styled">'; -// $o .= '<h2>' . sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...' . '</h2>'; -// $o .= '<table>'; - for($x = 0; $x < count($r); $x++ ) { $r[$x]['name'] = escape_tags(substr($r[$x]['dreport_recip'],strpos($r[$x]['dreport_recip'],' '))); @@ -143,7 +138,7 @@ class Dreport extends \Zotlabs\Web\Controller { $entries[] = [ 'name' => $rr['name'], 'result' => escape_tags($rr['dreport_result']), - 'time' => escape_tags($rr['dreport_time']) + 'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time'])) ]; } @@ -155,11 +150,6 @@ class Dreport extends \Zotlabs\Web\Controller { '$entries' => $entries )); -// foreach($r as $rr) { -// $o .= '<tr><td width="40%">' . $rr['name'] . '</td><td width="20%">' . escape_tags($rr['dreport_result']) . '</td><td width="20%">' . escape_tags($rr['dreport_time']) . '</td></tr>'; -// } -// $o .= '</table>'; -// $o .= '</div>'; return $o; -- cgit v1.2.3 From 852b2659e9a71f0542e822aa20efc009e22ff66a Mon Sep 17 00:00:00 2001 From: Mario Vavti <mario@mariovavti.com> Date: Thu, 30 Jun 2016 21:56:00 +0200 Subject: update moment.js to version 2.13 --- library/moment/CHANGELOG.md | 21 ++ library/moment/README.md | 2 +- library/moment/moment.js | 444 ++++++++++++++++++++++++++++++++++++++----- library/moment/moment.min.js | 6 +- 4 files changed, 423 insertions(+), 50 deletions(-) diff --git a/library/moment/CHANGELOG.md b/library/moment/CHANGELOG.md index cc0e7f571..433fa857e 100644 --- a/library/moment/CHANGELOG.md +++ b/library/moment/CHANGELOG.md @@ -1,6 +1,27 @@ Changelog ========= +### 2.13.0 [See full changelog](https://gist.github.com/ichernev/0132fcf5b61f7fc140b0bb0090480d49) + +## Enhancements: +* [#2982](https://github.com/moment/moment/pull/2982) Add 'date' as alias to 'day' for startOf() and endOf(). +* [#2955](https://github.com/moment/moment/pull/2955) Add parsing negative components in durations when ISO 8601 +* [#2991](https://github.com/moment/moment/pull/2991) isBetween support for both open and closed intervals +* [#3105](https://github.com/moment/moment/pull/3105) Add localeSorted argument to weekday listers +* [#3102](https://github.com/moment/moment/pull/3102) Add k and kk formatting tokens + +## Bugfixes +* [#3109](https://github.com/moment/moment/pull/3109) Fix [#1756](https://github.com/moment/moment/issues/1756) Resolved thread-safe issue on server side. +* [#3078](https://github.com/moment/moment/pull/3078) Fix parsing for months/weekdays with weird characters +* [#3098](https://github.com/moment/moment/pull/3098) Use Z suffix when in UTC mode ([#3020](https://github.com/moment/moment/issues/3020)) +* [#2995](https://github.com/moment/moment/pull/2995) Fix floating point rounding errors in durations +* [#3059](https://github.com/moment/moment/pull/3059) fix bug where diff returns -0 in month-related diffs +* [#3045](https://github.com/moment/moment/pull/3045) Fix mistaking any input for 'a' token +* [#2877](https://github.com/moment/moment/pull/2877) Use explicit .valueOf() calls instead of coercion +* [#3036](https://github.com/moment/moment/pull/3036) Year setter should keep time when DST changes + +Plus 3 new locales and locale fixes. + ### 2.12.0 [See full changelog](https://gist.github.com/ichernev/6e5bfdf8d6522fc4ac73) ## Enhancements: diff --git a/library/moment/README.md b/library/moment/README.md index 6193e5eb8..c45e9d624 100644 --- a/library/moment/README.md +++ b/library/moment/README.md @@ -5,7 +5,7 @@ A lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates. -## [Documentation](http://momentjs.com/docs/) +**[Documentation](http://momentjs.com/docs/)** ## Port to ECMAScript 6 (version 2.10.0) diff --git a/library/moment/moment.js b/library/moment/moment.js index b5f0b3644..ed94e44a1 100644 --- a/library/moment/moment.js +++ b/library/moment/moment.js @@ -1,5 +1,5 @@ //! moment.js -//! version : 2.12.0 +//! version : 2.13.0 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors //! license : MIT //! momentjs.com @@ -76,7 +76,9 @@ invalidMonth : null, invalidFormat : false, userInvalidated : false, - iso : false + iso : false, + parsedDateParts : [], + meridiem : null }; } @@ -87,9 +89,30 @@ return m._pf; } + var some; + if (Array.prototype.some) { + some = Array.prototype.some; + } else { + some = function (fun) { + var t = Object(this); + var len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t && fun.call(this, t[i], i, t)) { + return true; + } + } + + return false; + }; + } + function valid__isValid(m) { if (m._isValid == null) { var flags = getParsingFlags(m); + var parsedParts = some.call(flags.parsedDateParts, function (i) { + return i != null; + }); m._isValid = !isNaN(m._d.getTime()) && flags.overflow < 0 && !flags.empty && @@ -97,7 +120,8 @@ !flags.invalidWeekday && !flags.nullInput && !flags.invalidFormat && - !flags.userInvalidated; + !flags.userInvalidated && + (!flags.meridiem || (flags.meridiem && parsedParts)); if (m._strict) { m._isValid = m._isValid && @@ -240,6 +264,9 @@ var firstTime = true; return extend(function () { + if (utils_hooks__hooks.deprecationHandler != null) { + utils_hooks__hooks.deprecationHandler(null, msg); + } if (firstTime) { warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack); firstTime = false; @@ -251,6 +278,9 @@ var deprecations = {}; function deprecateSimple(name, msg) { + if (utils_hooks__hooks.deprecationHandler != null) { + utils_hooks__hooks.deprecationHandler(name, msg); + } if (!deprecations[name]) { warn(msg); deprecations[name] = true; @@ -258,6 +288,7 @@ } utils_hooks__hooks.suppressDeprecationWarnings = false; + utils_hooks__hooks.deprecationHandler = null; function isFunction(input) { return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; @@ -307,6 +338,22 @@ } } + var keys; + + if (Object.keys) { + keys = Object.keys; + } else { + keys = function (obj) { + var i, res = []; + for (i in obj) { + if (hasOwnProp(obj, i)) { + res.push(i); + } + } + return res; + }; + } + // internal storage for locale config files var locales = {}; var globalLocale; @@ -461,7 +508,7 @@ } function locale_locales__listLocales() { - return Object.keys(locales); + return keys(locales); } var aliases = {}; @@ -540,7 +587,7 @@ Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; } - var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; + var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; @@ -593,7 +640,7 @@ } return function (mom) { - var output = ''; + var output = '', i; for (i = 0; i < length; i++) { output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; } @@ -722,6 +769,23 @@ var WEEK = 7; var WEEKDAY = 8; + var indexOf; + + if (Array.prototype.indexOf) { + indexOf = Array.prototype.indexOf; + } else { + indexOf = function (o) { + // I know + var i; + for (i = 0; i < this.length; ++i) { + if (this[i] === o) { + return i; + } + } + return -1; + }; + } + function daysInMonth(year, month) { return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); } @@ -784,15 +848,63 @@ this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; } + function units_month__handleStrictParse(monthName, format, strict) { + var i, ii, mom, llc = monthName.toLocaleLowerCase(); + if (!this._monthsParse) { + // this is not used + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + for (i = 0; i < 12; ++i) { + mom = create_utc__createUTC([2000, i]); + this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); + this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } + } + function localeMonthsParse (monthName, format, strict) { var i, mom, regex; + if (this._monthsParseExact) { + return units_month__handleStrictParse.call(this, monthName, format, strict); + } + if (!this._monthsParse) { this._monthsParse = []; this._longMonthsParse = []; this._shortMonthsParse = []; } + // TODO: add sorting + // Sorting makes sure if one month (or abbr) is a prefix of another + // see sorting in computeMonthsParse for (i = 0; i < 12; i++) { // make the regex if we don't have it already mom = create_utc__createUTC([2000, i]); @@ -918,8 +1030,8 @@ this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); this._monthsShortRegex = this._monthsRegex; - this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')$', 'i'); - this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')$', 'i'); + this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); } function checkOverflow (m) { @@ -1146,7 +1258,7 @@ // MOMENTS - var getSetYear = makeGetSet('FullYear', false); + var getSetYear = makeGetSet('FullYear', true); function getIsLeapYear () { return isLeapYear(this.year()); @@ -1415,6 +1527,9 @@ config._a[HOUR] > 0) { getParsingFlags(config).bigHour = undefined; } + + getParsingFlags(config).parsedDateParts = config._a.slice(0); + getParsingFlags(config).meridiem = config._meridiem; // handle meridiem config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); @@ -1555,7 +1670,7 @@ if (input === undefined) { config._d = new Date(utils_hooks__hooks.now()); } else if (isDate(input)) { - config._d = new Date(+input); + config._d = new Date(input.valueOf()); } else if (typeof input === 'string') { configFromString(config); } else if (isArray(input)) { @@ -1675,7 +1790,7 @@ this._milliseconds = +milliseconds + seconds * 1e3 + // 1000 minutes * 6e4 + // 1000 * 60 - hours * 36e5; // 1000 * 60 * 60 + hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 // Because of dateAddRemove treats 24 hours as different from a // day when working around DST, we need to store them separately this._days = +days + @@ -1745,9 +1860,9 @@ var res, diff; if (model._isUTC) { res = model.clone(); - diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res); + diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf(); // Use low-level api, because this fn is low-level api. - res._d.setTime(+res._d + diff); + res._d.setTime(res._d.valueOf() + diff); utils_hooks__hooks.updateOffset(res, false); return res; } else { @@ -1908,7 +2023,7 @@ // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere // and further modified to allow for strings containing both week and day - var isoRegex = /^(-)?P(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)W)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?$/; + var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/; function create__createDuration (input, key) { var duration = input, @@ -2052,7 +2167,7 @@ updateOffset = updateOffset == null ? true : updateOffset; if (milliseconds) { - mom._d.setTime(+mom._d + milliseconds * isAdding); + mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); } if (days) { get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding); @@ -2097,9 +2212,9 @@ } units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); if (units === 'millisecond') { - return +this > +localInput; + return this.valueOf() > localInput.valueOf(); } else { - return +localInput < +this.clone().startOf(units); + return localInput.valueOf() < this.clone().startOf(units).valueOf(); } } @@ -2110,14 +2225,16 @@ } units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); if (units === 'millisecond') { - return +this < +localInput; + return this.valueOf() < localInput.valueOf(); } else { - return +this.clone().endOf(units) < +localInput; + return this.clone().endOf(units).valueOf() < localInput.valueOf(); } } - function isBetween (from, to, units) { - return this.isAfter(from, units) && this.isBefore(to, units); + function isBetween (from, to, units, inclusivity) { + inclusivity = inclusivity || '()'; + return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) && + (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units)); } function isSame (input, units) { @@ -2128,10 +2245,10 @@ } units = normalizeUnits(units || 'millisecond'); if (units === 'millisecond') { - return +this === +localInput; + return this.valueOf() === localInput.valueOf(); } else { - inputMs = +localInput; - return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units)); + inputMs = localInput.valueOf(); + return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf(); } } @@ -2198,10 +2315,12 @@ adjust = (b - anchor) / (anchor2 - anchor); } - return -(wholeMonthDiff + adjust); + //check for negative zero, return zero if negative zero + return -(wholeMonthDiff + adjust) || 0; } utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; + utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; function toString () { return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); @@ -2222,7 +2341,10 @@ } function format (inputString) { - var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat); + if (!inputString) { + inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat; + } + var output = formatMoment(this, inputString); return this.localeData().postformat(output); } @@ -2301,6 +2423,7 @@ case 'week': case 'isoWeek': case 'day': + case 'date': this.hours(0); /* falls through */ case 'hour': @@ -2334,19 +2457,25 @@ if (units === undefined || units === 'millisecond') { return this; } + + // 'date' is an alias for 'day', so it should be considered as such. + if (units === 'date') { + units = 'day'; + } + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); } function to_type__valueOf () { - return +this._d - ((this._offset || 0) * 60000); + return this._d.valueOf() - ((this._offset || 0) * 60000); } function unix () { - return Math.floor(+this / 1000); + return Math.floor(this.valueOf() / 1000); } function toDate () { - return this._offset ? new Date(+this) : this._d; + return this._offset ? new Date(this.valueOf()) : this._d; } function toArray () { @@ -2615,9 +2744,15 @@ addRegexToken('d', match1to2); addRegexToken('e', match1to2); addRegexToken('E', match1to2); - addRegexToken('dd', matchWord); - addRegexToken('ddd', matchWord); - addRegexToken('dddd', matchWord); + addRegexToken('dd', function (isStrict, locale) { + return locale.weekdaysMinRegex(isStrict); + }); + addRegexToken('ddd', function (isStrict, locale) { + return locale.weekdaysShortRegex(isStrict); + }); + addRegexToken('dddd', function (isStrict, locale) { + return locale.weekdaysRegex(isStrict); + }); addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { var weekday = config._locale.weekdaysParse(input, token, config._strict); @@ -2670,9 +2805,77 @@ return this._weekdaysMin[m.day()]; } + function day_of_week__handleStrictParse(weekdayName, format, strict) { + var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._shortWeekdaysParse = []; + this._minWeekdaysParse = []; + + for (i = 0; i < 7; ++i) { + mom = create_utc__createUTC([2000, 1]).day(i); + this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); + this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); + this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } + } + function localeWeekdaysParse (weekdayName, format, strict) { var i, mom, regex; + if (this._weekdaysParseExact) { + return day_of_week__handleStrictParse.call(this, weekdayName, format, strict); + } + if (!this._weekdaysParse) { this._weekdaysParse = []; this._minWeekdaysParse = []; @@ -2683,7 +2886,7 @@ for (i = 0; i < 7; i++) { // make the regex if we don't have it already - mom = local__createLocal([2000, 1]).day(i); + mom = create_utc__createUTC([2000, 1]).day(i); if (strict && !this._fullWeekdaysParse[i]) { this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i'); this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i'); @@ -2739,6 +2942,99 @@ return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); } + var defaultWeekdaysRegex = matchWord; + function weekdaysRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysStrictRegex; + } else { + return this._weekdaysRegex; + } + } else { + return this._weekdaysStrictRegex && isStrict ? + this._weekdaysStrictRegex : this._weekdaysRegex; + } + } + + var defaultWeekdaysShortRegex = matchWord; + function weekdaysShortRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysShortStrictRegex; + } else { + return this._weekdaysShortRegex; + } + } else { + return this._weekdaysShortStrictRegex && isStrict ? + this._weekdaysShortStrictRegex : this._weekdaysShortRegex; + } + } + + var defaultWeekdaysMinRegex = matchWord; + function weekdaysMinRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysMinStrictRegex; + } else { + return this._weekdaysMinRegex; + } + } else { + return this._weekdaysMinStrictRegex && isStrict ? + this._weekdaysMinStrictRegex : this._weekdaysMinRegex; + } + } + + + function computeWeekdaysParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], + i, mom, minp, shortp, longp; + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, 1]).day(i); + minp = this.weekdaysMin(mom, ''); + shortp = this.weekdaysShort(mom, ''); + longp = this.weekdays(mom, ''); + minPieces.push(minp); + shortPieces.push(shortp); + longPieces.push(longp); + mixedPieces.push(minp); + mixedPieces.push(shortp); + mixedPieces.push(longp); + } + // Sorting makes sure if one weekday (or abbr) is a prefix of another it + // will match the longer piece. + minPieces.sort(cmpLenRev); + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 7; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._weekdaysShortRegex = this._weekdaysRegex; + this._weekdaysMinRegex = this._weekdaysRegex; + + this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); + } + // FORMATTING addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); @@ -2770,8 +3066,13 @@ return this.hours() % 12 || 12; } + function kFormat() { + return this.hours() || 24; + } + addFormatToken('H', ['HH', 2], 0, 'hour'); addFormatToken('h', ['hh', 2], 0, hFormat); + addFormatToken('k', ['kk', 2], 0, kFormat); addFormatToken('hmm', 0, 0, function () { return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); @@ -3232,6 +3533,13 @@ prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort; prototype__proto.weekdaysParse = localeWeekdaysParse; + prototype__proto._weekdaysRegex = defaultWeekdaysRegex; + prototype__proto.weekdaysRegex = weekdaysRegex; + prototype__proto._weekdaysShortRegex = defaultWeekdaysShortRegex; + prototype__proto.weekdaysShortRegex = weekdaysShortRegex; + prototype__proto._weekdaysMinRegex = defaultWeekdaysMinRegex; + prototype__proto.weekdaysMinRegex = weekdaysMinRegex; + // Hours prototype__proto.isPM = localeIsPM; prototype__proto._meridiemParse = defaultLocaleMeridiemParse; @@ -3243,7 +3551,7 @@ return locale[field](utc, format); } - function list (format, index, field, count, setter) { + function listMonthsImpl (format, index, field) { if (typeof format === 'number') { index = format; format = undefined; @@ -3252,35 +3560,79 @@ format = format || ''; if (index != null) { - return lists__get(format, index, field, setter); + return lists__get(format, index, field, 'month'); } var i; var out = []; - for (i = 0; i < count; i++) { - out[i] = lists__get(format, i, field, setter); + for (i = 0; i < 12; i++) { + out[i] = lists__get(format, i, field, 'month'); + } + return out; + } + + // () + // (5) + // (fmt, 5) + // (fmt) + // (true) + // (true, 5) + // (true, fmt, 5) + // (true, fmt) + function listWeekdaysImpl (localeSorted, format, index, field) { + if (typeof localeSorted === 'boolean') { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + } else { + format = localeSorted; + index = format; + localeSorted = false; + + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + } + + var locale = locale_locales__getLocale(), + shift = localeSorted ? locale._week.dow : 0; + + if (index != null) { + return lists__get(format, (index + shift) % 7, field, 'day'); + } + + var i; + var out = []; + for (i = 0; i < 7; i++) { + out[i] = lists__get(format, (i + shift) % 7, field, 'day'); } return out; } function lists__listMonths (format, index) { - return list(format, index, 'months', 12, 'month'); + return listMonthsImpl(format, index, 'months'); } function lists__listMonthsShort (format, index) { - return list(format, index, 'monthsShort', 12, 'month'); + return listMonthsImpl(format, index, 'monthsShort'); } - function lists__listWeekdays (format, index) { - return list(format, index, 'weekdays', 7, 'day'); + function lists__listWeekdays (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); } - function lists__listWeekdaysShort (format, index) { - return list(format, index, 'weekdaysShort', 7, 'day'); + function lists__listWeekdaysShort (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); } - function lists__listWeekdaysMin (format, index) { - return list(format, index, 'weekdaysMin', 7, 'day'); + function lists__listWeekdaysMin (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); } locale_locales__getSetGlobalLocale('en', { @@ -3651,7 +4003,7 @@ // Side effect imports - utils_hooks__hooks.version = '2.12.0'; + utils_hooks__hooks.version = '2.13.0'; setHookCallback(local__createLocal); diff --git a/library/moment/moment.min.js b/library/moment/moment.min.js index ba38995bd..d301ddbbe 100644 --- a/library/moment/moment.min.js +++ b/library/moment/moment.min.js @@ -1,7 +1,7 @@ //! moment.js -//! version : 2.12.0 +//! version : 2.13.0 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors //! license : MIT //! momentjs.com -!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Zc.apply(null,arguments)}function b(a){Zc=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function f(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function g(a,b){for(var c in b)f(b,c)&&(a[c]=b[c]);return f(b,"toString")&&(a.toString=b.toString),f(b,"valueOf")&&(a.valueOf=b.valueOf),a}function h(a,b,c,d){return Ia(a,b,c,d,!0).utc()}function i(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function j(a){return null==a._pf&&(a._pf=i()),a._pf}function k(a){if(null==a._isValid){var b=j(a);a._isValid=!(isNaN(a._d.getTime())||!(b.overflow<0)||b.empty||b.invalidMonth||b.invalidWeekday||b.nullInput||b.invalidFormat||b.userInvalidated),a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function l(a){var b=h(NaN);return null!=a?g(j(b),a):j(b).userInvalidated=!0,b}function m(a){return void 0===a}function n(a,b){var c,d,e;if(m(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),m(b._i)||(a._i=b._i),m(b._f)||(a._f=b._f),m(b._l)||(a._l=b._l),m(b._strict)||(a._strict=b._strict),m(b._tzm)||(a._tzm=b._tzm),m(b._isUTC)||(a._isUTC=b._isUTC),m(b._offset)||(a._offset=b._offset),m(b._pf)||(a._pf=j(b)),m(b._locale)||(a._locale=b._locale),$c.length>0)for(c in $c)d=$c[c],e=b[d],m(e)||(a[d]=e);return a}function o(b){n(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),_c===!1&&(_c=!0,a.updateOffset(this),_c=!1)}function p(a){return a instanceof o||null!=a&&null!=a._isAMomentObject}function q(a){return 0>a?Math.ceil(a):Math.floor(a)}function r(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=q(b)),c}function s(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&r(a[d])!==r(b[d]))&&g++;return g+f}function t(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function u(a,b){var c=!0;return g(function(){return c&&(t(a+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),c=!1),b.apply(this,arguments)},b)}function v(a,b){ad[a]||(t(b),ad[a]=!0)}function w(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function x(a){return"[object Object]"===Object.prototype.toString.call(a)}function y(a){var b,c;for(c in a)b=a[c],w(b)?this[c]=b:this["_"+c]=b;this._config=a,this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function z(a,b){var c,d=g({},a);for(c in b)f(b,c)&&(x(a[c])&&x(b[c])?(d[c]={},g(d[c],a[c]),g(d[c],b[c])):null!=b[c]?d[c]=b[c]:delete d[c]);return d}function A(a){null!=a&&this.set(a)}function B(a){return a?a.toLowerCase().replace("_","-"):a}function C(a){for(var b,c,d,e,f=0;f<a.length;){for(e=B(a[f]).split("-"),b=e.length,c=B(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=D(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&s(e,c,!0)>=b-1)break;b--}f++}return null}function D(a){var b=null;if(!cd[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=bd._abbr,require("./locale/"+a),E(b)}catch(c){}return cd[a]}function E(a,b){var c;return a&&(c=m(b)?H(a):F(a,b),c&&(bd=c)),bd._abbr}function F(a,b){return null!==b?(b.abbr=a,null!=cd[a]?(v("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale"),b=z(cd[a]._config,b)):null!=b.parentLocale&&(null!=cd[b.parentLocale]?b=z(cd[b.parentLocale]._config,b):v("parentLocaleUndefined","specified parentLocale is not defined yet")),cd[a]=new A(b),E(a),cd[a]):(delete cd[a],null)}function G(a,b){if(null!=b){var c;null!=cd[a]&&(b=z(cd[a]._config,b)),c=new A(b),c.parentLocale=cd[a],cd[a]=c,E(a)}else null!=cd[a]&&(null!=cd[a].parentLocale?cd[a]=cd[a].parentLocale:null!=cd[a]&&delete cd[a]);return cd[a]}function H(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return bd;if(!c(a)){if(b=D(a))return b;a=[a]}return C(a)}function I(){return Object.keys(cd)}function J(a,b){var c=a.toLowerCase();dd[c]=dd[c+"s"]=dd[b]=a}function K(a){return"string"==typeof a?dd[a]||dd[a.toLowerCase()]:void 0}function L(a){var b,c,d={};for(c in a)f(a,c)&&(b=K(c),b&&(d[b]=a[c]));return d}function M(b,c){return function(d){return null!=d?(O(this,b,d),a.updateOffset(this,c),this):N(this,b)}}function N(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function O(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}function P(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=K(a),w(this[a]))return this[a](b);return this}function Q(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function R(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(hd[a]=e),b&&(hd[b[0]]=function(){return Q(e.apply(this,arguments),b[1],b[2])}),c&&(hd[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function S(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function T(a){var b,c,d=a.match(ed);for(b=0,c=d.length;c>b;b++)hd[d[b]]?d[b]=hd[d[b]]:d[b]=S(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function U(a,b){return a.isValid()?(b=V(b,a.localeData()),gd[b]=gd[b]||T(b),gd[b](a)):a.localeData().invalidDate()}function V(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(fd.lastIndex=0;d>=0&&fd.test(a);)a=a.replace(fd,c),fd.lastIndex=0,d-=1;return a}function W(a,b,c){zd[a]=w(b)?b:function(a,d){return a&&c?c:b}}function X(a,b){return f(zd,a)?zd[a](b._strict,b._locale):new RegExp(Y(a))}function Y(a){return Z(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function Z(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function $(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=r(a)}),c=0;c<a.length;c++)Ad[a[c]]=d}function _(a,b){$(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function aa(a,b,c){null!=b&&f(Ad,a)&&Ad[a](b,c._a,c,a)}function ba(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ca(a,b){return c(this._months)?this._months[a.month()]:this._months[Kd.test(b)?"format":"standalone"][a.month()]}function da(a,b){return c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[Kd.test(b)?"format":"standalone"][a.month()]}function ea(a,b,c){var d,e,f;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function fa(a,b){var c;if(!a.isValid())return a;if("string"==typeof b)if(/^\d+$/.test(b))b=r(b);else if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),ba(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ga(b){return null!=b?(fa(this,b),a.updateOffset(this,!0),this):N(this,"Month")}function ha(){return ba(this.year(),this.month())}function ia(a){return this._monthsParseExact?(f(this,"_monthsRegex")||ka.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex}function ja(a){return this._monthsParseExact?(f(this,"_monthsRegex")||ka.call(this),a?this._monthsStrictRegex:this._monthsRegex):this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex}function ka(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;12>b;b++)c=h([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(d.sort(a),e.sort(a),f.sort(a),b=0;12>b;b++)d[b]=Z(d[b]),e[b]=Z(e[b]),f[b]=Z(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")$","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")$","i")}function la(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[Cd]<0||c[Cd]>11?Cd:c[Dd]<1||c[Dd]>ba(c[Bd],c[Cd])?Dd:c[Ed]<0||c[Ed]>24||24===c[Ed]&&(0!==c[Fd]||0!==c[Gd]||0!==c[Hd])?Ed:c[Fd]<0||c[Fd]>59?Fd:c[Gd]<0||c[Gd]>59?Gd:c[Hd]<0||c[Hd]>999?Hd:-1,j(a)._overflowDayOfYear&&(Bd>b||b>Dd)&&(b=Dd),j(a)._overflowWeeks&&-1===b&&(b=Id),j(a)._overflowWeekday&&-1===b&&(b=Jd),j(a).overflow=b),a}function ma(a){var b,c,d,e,f,g,h=a._i,i=Pd.exec(h)||Qd.exec(h);if(i){for(j(a).iso=!0,b=0,c=Sd.length;c>b;b++)if(Sd[b][1].exec(i[1])){e=Sd[b][0],d=Sd[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=Td.length;c>b;b++)if(Td[b][1].exec(i[3])){f=(i[2]||" ")+Td[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!Rd.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),Ba(a)}else a._isValid=!1}function na(b){var c=Ud.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(ma(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function oa(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 100>a&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function pa(a){var b=new Date(Date.UTC.apply(null,arguments));return 100>a&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}function qa(a){return ra(a)?366:365}function ra(a){return a%4===0&&a%100!==0||a%400===0}function sa(){return ra(this.year())}function ta(a,b,c){var d=7+b-c,e=(7+pa(a,0,d).getUTCDay()-b)%7;return-e+d-1}function ua(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ta(a,d,e),j=1+7*(b-1)+h+i;return 0>=j?(f=a-1,g=qa(f)+j):j>qa(a)?(f=a+1,g=j-qa(a)):(f=a,g=j),{year:f,dayOfYear:g}}function va(a,b,c){var d,e,f=ta(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return 1>g?(e=a.year()-1,d=g+wa(e,b,c)):g>wa(a.year(),b,c)?(d=g-wa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function wa(a,b,c){var d=ta(a,b,c),e=ta(a+1,b,c);return(qa(a)-d+e)/7}function xa(a,b,c){return null!=a?a:null!=b?b:c}function ya(b){var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}function za(a){var b,c,d,e,f=[];if(!a._d){for(d=ya(a),a._w&&null==a._a[Dd]&&null==a._a[Cd]&&Aa(a),a._dayOfYear&&(e=xa(a._a[Bd],d[Bd]),a._dayOfYear>qa(e)&&(j(a)._overflowDayOfYear=!0),c=pa(e,0,a._dayOfYear),a._a[Cd]=c.getUTCMonth(),a._a[Dd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[Ed]&&0===a._a[Fd]&&0===a._a[Gd]&&0===a._a[Hd]&&(a._nextDay=!0,a._a[Ed]=0),a._d=(a._useUTC?pa:oa).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[Ed]=24)}}function Aa(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=xa(b.GG,a._a[Bd],va(Ja(),1,4).year),d=xa(b.W,1),e=xa(b.E,1),(1>e||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=xa(b.gg,a._a[Bd],va(Ja(),f,g).year),d=xa(b.w,1),null!=b.d?(e=b.d,(0>e||e>6)&&(i=!0)):null!=b.e?(e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):e=f),1>d||d>wa(c,f,g)?j(a)._overflowWeeks=!0:null!=i?j(a)._overflowWeekday=!0:(h=ua(c,d,e,f,g),a._a[Bd]=h.year,a._dayOfYear=h.dayOfYear)}function Ba(b){if(b._f===a.ISO_8601)return void ma(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=V(b._f,b._locale).match(ed)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(X(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),hd[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),aa(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[Ed]<=12&&b._a[Ed]>0&&(j(b).bigHour=void 0),b._a[Ed]=Ca(b._locale,b._a[Ed],b._meridiem),za(b),la(b)}function Ca(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function Da(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=n({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],Ba(b),k(b)&&(f+=j(b).charsLeftOver,f+=10*j(b).unusedTokens.length,j(b).score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function Ea(a){if(!a._d){var b=L(a._i);a._a=e([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),za(a)}}function Fa(a){var b=new o(la(Ga(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Ga(a){var b=a._i,e=a._f;return a._locale=a._locale||H(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),p(b)?new o(la(b)):(c(e)?Da(a):e?Ba(a):d(b)?a._d=b:Ha(a),k(a)||(a._d=null),a))}function Ha(b){var f=b._i;void 0===f?b._d=new Date(a.now()):d(f)?b._d=new Date(+f):"string"==typeof f?na(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),za(b)):"object"==typeof f?Ea(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ia(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,Fa(f)}function Ja(a,b,c,d){return Ia(a,b,c,d,!1)}function Ka(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Ja();for(d=b[0],e=1;e<b.length;++e)(!b[e].isValid()||b[e][a](d))&&(d=b[e]);return d}function La(){var a=[].slice.call(arguments,0);return Ka("isBefore",a)}function Ma(){var a=[].slice.call(arguments,0);return Ka("isAfter",a)}function Na(a){var b=L(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=H(),this._bubble()}function Oa(a){return a instanceof Na}function Pa(a,b){R(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+Q(~~(a/60),2)+b+Q(~~a%60,2)})}function Qa(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(Zd)||["-",0,0],f=+(60*e[1])+r(e[2]);return"+"===e[0]?f:-f}function Ra(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(p(b)||d(b)?+b:+Ja(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Ja(b).local()}function Sa(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ta(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=Qa(wd,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Sa(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?ib(this,cb(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Sa(this):null!=b?this:NaN}function Ua(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Va(a){return this.utcOffset(0,a)}function Wa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Sa(this),"m")),this}function Xa(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Qa(vd,this._i)),this}function Ya(a){return this.isValid()?(a=a?Ja(a).utcOffset():0,(this.utcOffset()-a)%60===0):!1}function Za(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function $a(){if(!m(this._isDSTShifted))return this._isDSTShifted;var a={};if(n(a,this),a=Ga(a),a._a){var b=a._isUTC?h(a._a):Ja(a._a);this._isDSTShifted=this.isValid()&&s(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function _a(){return this.isValid()?!this._isUTC:!1}function ab(){return this.isValid()?this._isUTC:!1}function bb(){return this.isValid()?this._isUTC&&0===this._offset:!1}function cb(a,b){var c,d,e,g=a,h=null;return Oa(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=$d.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:r(h[Dd])*c,h:r(h[Ed])*c,m:r(h[Fd])*c,s:r(h[Gd])*c,ms:r(h[Hd])*c}):(h=_d.exec(a))?(c="-"===h[1]?-1:1,g={y:db(h[2],c),M:db(h[3],c),w:db(h[4],c),d:db(h[5],c),h:db(h[6],c),m:db(h[7],c),s:db(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=fb(Ja(g.from),Ja(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Na(g),Oa(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function db(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function eb(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function fb(a,b){var c;return a.isValid()&&b.isValid()?(b=Ra(b,a),a.isBefore(b)?c=eb(a,b):(c=eb(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function gb(a){return 0>a?-1*Math.round(-1*a):Math.round(a)}function hb(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(v(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=cb(c,d),ib(this,e,a),this}}function ib(b,c,d,e){var f=c._milliseconds,g=gb(c._days),h=gb(c._months);b.isValid()&&(e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&O(b,"Date",N(b,"Date")+g*d),h&&fa(b,N(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function jb(a,b){var c=a||Ja(),d=Ra(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse",g=b&&(w(b[f])?b[f]():b[f]);return this.format(g||this.localeData().calendar(f,this,Ja(c)))}function kb(){return new o(this)}function lb(a,b){var c=p(a)?a:Ja(a);return this.isValid()&&c.isValid()?(b=K(m(b)?"millisecond":b),"millisecond"===b?+this>+c:+c<+this.clone().startOf(b)):!1}function mb(a,b){var c=p(a)?a:Ja(a);return this.isValid()&&c.isValid()?(b=K(m(b)?"millisecond":b),"millisecond"===b?+c>+this:+this.clone().endOf(b)<+c):!1}function nb(a,b,c){return this.isAfter(a,c)&&this.isBefore(b,c)}function ob(a,b){var c,d=p(a)?a:Ja(a);return this.isValid()&&d.isValid()?(b=K(b||"millisecond"),"millisecond"===b?+this===+d:(c=+d,+this.clone().startOf(b)<=c&&c<=+this.clone().endOf(b))):!1}function pb(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function qb(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function rb(a,b,c){var d,e,f,g;return this.isValid()?(d=Ra(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=K(b),"year"===b||"month"===b||"quarter"===b?(g=sb(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:q(g)):NaN):NaN}function sb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function tb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function ub(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?w(Date.prototype.toISOString)?this.toDate().toISOString():U(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):U(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function vb(b){var c=U(this,b||a.defaultFormat);return this.localeData().postformat(c)}function wb(a,b){return this.isValid()&&(p(a)&&a.isValid()||Ja(a).isValid())?cb({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function xb(a){return this.from(Ja(),a)}function yb(a,b){return this.isValid()&&(p(a)&&a.isValid()||Ja(a).isValid())?cb({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function zb(a){return this.to(Ja(),a)}function Ab(a){var b;return void 0===a?this._locale._abbr:(b=H(a),null!=b&&(this._locale=b),this)}function Bb(){return this._locale}function Cb(a){switch(a=K(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function Db(a){return a=K(a),void 0===a||"millisecond"===a?this:this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms")}function Eb(){return+this._d-6e4*(this._offset||0)}function Fb(){return Math.floor(+this/1e3)}function Gb(){return this._offset?new Date(+this):this._d}function Hb(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function Ib(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function Jb(){return this.isValid()?this.toISOString():null}function Kb(){return k(this)}function Lb(){return g({},j(this))}function Mb(){return j(this).overflow}function Nb(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Ob(a,b){R(0,[a,a.length],0,b)}function Pb(a){return Tb.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function Qb(a){return Tb.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Rb(){return wa(this.year(),1,4)}function Sb(){var a=this.localeData()._week;return wa(this.year(),a.dow,a.doy)}function Tb(a,b,c,d,e){var f;return null==a?va(this,d,e).year:(f=wa(a,d,e),b>f&&(b=f),Ub.call(this,a,b,c,d,e))}function Ub(a,b,c,d,e){var f=ua(a,b,c,d,e),g=pa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}function Vb(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}function Wb(a){return va(a,this._week.dow,this._week.doy).week}function Xb(){return this._week.dow}function Yb(){return this._week.doy}function Zb(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function $b(a){var b=va(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function _b(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function ac(a,b){return c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]}function bc(a){return this._weekdaysShort[a.day()]}function cc(a){return this._weekdaysMin[a.day()]}function dc(a,b,c){var d,e,f;for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;7>d;d++){if(e=Ja([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}function ec(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=_b(a,this.localeData()),this.add(a-b,"d")):b}function fc(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function gc(a){return this.isValid()?null==a?this.day()||7:this.day(this.day()%7?a:a-7):null!=a?this:NaN}function hc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function ic(){return this.hours()%12||12}function jc(a,b){R(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function kc(a,b){return b._meridiemParse}function lc(a){return"p"===(a+"").toLowerCase().charAt(0)}function mc(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function nc(a,b){b[Hd]=r(1e3*("0."+a))}function oc(){return this._isUTC?"UTC":""}function pc(){return this._isUTC?"Coordinated Universal Time":""}function qc(a){return Ja(1e3*a)}function rc(){return Ja.apply(null,arguments).parseZone()}function sc(a,b,c){var d=this._calendar[a];return w(d)?d.call(b,c):d}function tc(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function uc(){return this._invalidDate}function vc(a){return this._ordinal.replace("%d",a)}function wc(a){return a}function xc(a,b,c,d){var e=this._relativeTime[c];return w(e)?e(a,b,c,d):e.replace(/%d/i,a)}function yc(a,b){var c=this._relativeTime[a>0?"future":"past"];return w(c)?c(b):c.replace(/%s/i,b)}function zc(a,b,c,d){var e=H(),f=h().set(d,b);return e[c](f,a)}function Ac(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return zc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=zc(a,f,c,e);return g}function Bc(a,b){return Ac(a,b,"months",12,"month")}function Cc(a,b){return Ac(a,b,"monthsShort",12,"month")}function Dc(a,b){return Ac(a,b,"weekdays",7,"day")}function Ec(a,b){return Ac(a,b,"weekdaysShort",7,"day")}function Fc(a,b){return Ac(a,b,"weekdaysMin",7,"day")}function Gc(){var a=this._data;return this._milliseconds=xe(this._milliseconds),this._days=xe(this._days),this._months=xe(this._months),a.milliseconds=xe(a.milliseconds),a.seconds=xe(a.seconds),a.minutes=xe(a.minutes),a.hours=xe(a.hours),a.months=xe(a.months),a.years=xe(a.years),this}function Hc(a,b,c,d){var e=cb(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function Ic(a,b){return Hc(this,a,b,1)}function Jc(a,b){return Hc(this,a,b,-1)}function Kc(a){return 0>a?Math.floor(a):Math.ceil(a)}function Lc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*Kc(Nc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=q(f/1e3),i.seconds=a%60,b=q(a/60),i.minutes=b%60,c=q(b/60),i.hours=c%24,g+=q(c/24),e=q(Mc(g)),h+=e,g-=Kc(Nc(e)),d=q(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function Mc(a){return 4800*a/146097}function Nc(a){return 146097*a/4800}function Oc(a){var b,c,d=this._milliseconds;if(a=K(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+Mc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(Nc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function Pc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*r(this._months/12)}function Qc(a){return function(){return this.as(a)}}function Rc(a){return a=K(a),this[a+"s"]()}function Sc(a){return function(){return this._data[a]}}function Tc(){return q(this.days()/7)}function Uc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function Vc(a,b,c){var d=cb(a).abs(),e=Ne(d.as("s")),f=Ne(d.as("m")),g=Ne(d.as("h")),h=Ne(d.as("d")),i=Ne(d.as("M")),j=Ne(d.as("y")),k=e<Oe.s&&["s",e]||1>=f&&["m"]||f<Oe.m&&["mm",f]||1>=g&&["h"]||g<Oe.h&&["hh",g]||1>=h&&["d"]||h<Oe.d&&["dd",h]||1>=i&&["M"]||i<Oe.M&&["MM",i]||1>=j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,Uc.apply(null,k)}function Wc(a,b){return void 0===Oe[a]?!1:void 0===b?Oe[a]:(Oe[a]=b,!0)}function Xc(a){var b=this.localeData(),c=Vc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Yc(){var a,b,c,d=Pe(this._milliseconds)/1e3,e=Pe(this._days),f=Pe(this._months);a=q(d/60),b=q(a/60),d%=60,a%=60,c=q(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var Zc,$c=a.momentProperties=[],_c=!1,ad={};a.suppressDeprecationWarnings=!1;var bd,cd={},dd={},ed=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,fd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,gd={},hd={},id=/\d/,jd=/\d\d/,kd=/\d{3}/,ld=/\d{4}/,md=/[+-]?\d{6}/,nd=/\d\d?/,od=/\d\d\d\d?/,pd=/\d\d\d\d\d\d?/,qd=/\d{1,3}/,rd=/\d{1,4}/,sd=/[+-]?\d{1,6}/,td=/\d+/,ud=/[+-]?\d+/,vd=/Z|[+-]\d\d:?\d\d/gi,wd=/Z|[+-]\d\d(?::?\d\d)?/gi,xd=/[+-]?\d+(\.\d{1,3})?/,yd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,zd={},Ad={},Bd=0,Cd=1,Dd=2,Ed=3,Fd=4,Gd=5,Hd=6,Id=7,Jd=8;R("M",["MM",2],"Mo",function(){return this.month()+1}),R("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),R("MMMM",0,0,function(a){return this.localeData().months(this,a)}),J("month","M"),W("M",nd),W("MM",nd,jd),W("MMM",function(a,b){return b.monthsShortRegex(a)}),W("MMMM",function(a,b){return b.monthsRegex(a)}),$(["M","MM"],function(a,b){b[Cd]=r(a)-1}),$(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[Cd]=e:j(c).invalidMonth=a});var Kd=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,Ld="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Md="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),Nd=yd,Od=yd,Pd=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,Qd=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,Rd=/Z|[+-]\d\d(?::?\d\d)?/,Sd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Td=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ud=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=u("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),R("Y",0,0,function(){var a=this.year();return 9999>=a?""+a:"+"+a}),R(0,["YY",2],0,function(){return this.year()%100}),R(0,["YYYY",4],0,"year"),R(0,["YYYYY",5],0,"year"),R(0,["YYYYYY",6,!0],0,"year"),J("year","y"),W("Y",ud),W("YY",nd,jd),W("YYYY",rd,ld),W("YYYYY",sd,md),W("YYYYYY",sd,md),$(["YYYYY","YYYYYY"],Bd),$("YYYY",function(b,c){c[Bd]=2===b.length?a.parseTwoDigitYear(b):r(b); -}),$("YY",function(b,c){c[Bd]=a.parseTwoDigitYear(b)}),$("Y",function(a,b){b[Bd]=parseInt(a,10)}),a.parseTwoDigitYear=function(a){return r(a)+(r(a)>68?1900:2e3)};var Vd=M("FullYear",!1);a.ISO_8601=function(){};var Wd=u("moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Ja.apply(null,arguments);return this.isValid()&&a.isValid()?this>a?this:a:l()}),Xd=u("moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Ja.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:l()}),Yd=function(){return Date.now?Date.now():+new Date};Pa("Z",":"),Pa("ZZ",""),W("Z",wd),W("ZZ",wd),$(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Qa(wd,a)});var Zd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var $d=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,_d=/^(-)?P(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)W)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?$/;cb.fn=Na.prototype;var ae=hb(1,"add"),be=hb(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var ce=u("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});R(0,["gg",2],0,function(){return this.weekYear()%100}),R(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Ob("gggg","weekYear"),Ob("ggggg","weekYear"),Ob("GGGG","isoWeekYear"),Ob("GGGGG","isoWeekYear"),J("weekYear","gg"),J("isoWeekYear","GG"),W("G",ud),W("g",ud),W("GG",nd,jd),W("gg",nd,jd),W("GGGG",rd,ld),W("gggg",rd,ld),W("GGGGG",sd,md),W("ggggg",sd,md),_(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=r(a)}),_(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),R("Q",0,"Qo","quarter"),J("quarter","Q"),W("Q",id),$("Q",function(a,b){b[Cd]=3*(r(a)-1)}),R("w",["ww",2],"wo","week"),R("W",["WW",2],"Wo","isoWeek"),J("week","w"),J("isoWeek","W"),W("w",nd),W("ww",nd,jd),W("W",nd),W("WW",nd,jd),_(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=r(a)});var de={dow:0,doy:6};R("D",["DD",2],"Do","date"),J("date","D"),W("D",nd),W("DD",nd,jd),W("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),$(["D","DD"],Dd),$("Do",function(a,b){b[Dd]=r(a.match(nd)[0],10)});var ee=M("Date",!0);R("d",0,"do","day"),R("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),R("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),R("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),R("e",0,0,"weekday"),R("E",0,0,"isoWeekday"),J("day","d"),J("weekday","e"),J("isoWeekday","E"),W("d",nd),W("e",nd),W("E",nd),W("dd",yd),W("ddd",yd),W("dddd",yd),_(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);null!=e?b.d=e:j(c).invalidWeekday=a}),_(["d","e","E"],function(a,b,c,d){b[d]=r(a)});var fe="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),ge="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),he="Su_Mo_Tu_We_Th_Fr_Sa".split("_");R("DDD",["DDDD",3],"DDDo","dayOfYear"),J("dayOfYear","DDD"),W("DDD",qd),W("DDDD",kd),$(["DDD","DDDD"],function(a,b,c){c._dayOfYear=r(a)}),R("H",["HH",2],0,"hour"),R("h",["hh",2],0,ic),R("hmm",0,0,function(){return""+ic.apply(this)+Q(this.minutes(),2)}),R("hmmss",0,0,function(){return""+ic.apply(this)+Q(this.minutes(),2)+Q(this.seconds(),2)}),R("Hmm",0,0,function(){return""+this.hours()+Q(this.minutes(),2)}),R("Hmmss",0,0,function(){return""+this.hours()+Q(this.minutes(),2)+Q(this.seconds(),2)}),jc("a",!0),jc("A",!1),J("hour","h"),W("a",kc),W("A",kc),W("H",nd),W("h",nd),W("HH",nd,jd),W("hh",nd,jd),W("hmm",od),W("hmmss",pd),W("Hmm",od),W("Hmmss",pd),$(["H","HH"],Ed),$(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),$(["h","hh"],function(a,b,c){b[Ed]=r(a),j(c).bigHour=!0}),$("hmm",function(a,b,c){var d=a.length-2;b[Ed]=r(a.substr(0,d)),b[Fd]=r(a.substr(d)),j(c).bigHour=!0}),$("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Ed]=r(a.substr(0,d)),b[Fd]=r(a.substr(d,2)),b[Gd]=r(a.substr(e)),j(c).bigHour=!0}),$("Hmm",function(a,b,c){var d=a.length-2;b[Ed]=r(a.substr(0,d)),b[Fd]=r(a.substr(d))}),$("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Ed]=r(a.substr(0,d)),b[Fd]=r(a.substr(d,2)),b[Gd]=r(a.substr(e))});var ie=/[ap]\.?m?\.?/i,je=M("Hours",!0);R("m",["mm",2],0,"minute"),J("minute","m"),W("m",nd),W("mm",nd,jd),$(["m","mm"],Fd);var ke=M("Minutes",!1);R("s",["ss",2],0,"second"),J("second","s"),W("s",nd),W("ss",nd,jd),$(["s","ss"],Gd);var le=M("Seconds",!1);R("S",0,0,function(){return~~(this.millisecond()/100)}),R(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),R(0,["SSS",3],0,"millisecond"),R(0,["SSSS",4],0,function(){return 10*this.millisecond()}),R(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),R(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),R(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),R(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),R(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),J("millisecond","ms"),W("S",qd,id),W("SS",qd,jd),W("SSS",qd,kd);var me;for(me="SSSS";me.length<=9;me+="S")W(me,td);for(me="S";me.length<=9;me+="S")$(me,nc);var ne=M("Milliseconds",!1);R("z",0,0,"zoneAbbr"),R("zz",0,0,"zoneName");var oe=o.prototype;oe.add=ae,oe.calendar=jb,oe.clone=kb,oe.diff=rb,oe.endOf=Db,oe.format=vb,oe.from=wb,oe.fromNow=xb,oe.to=yb,oe.toNow=zb,oe.get=P,oe.invalidAt=Mb,oe.isAfter=lb,oe.isBefore=mb,oe.isBetween=nb,oe.isSame=ob,oe.isSameOrAfter=pb,oe.isSameOrBefore=qb,oe.isValid=Kb,oe.lang=ce,oe.locale=Ab,oe.localeData=Bb,oe.max=Xd,oe.min=Wd,oe.parsingFlags=Lb,oe.set=P,oe.startOf=Cb,oe.subtract=be,oe.toArray=Hb,oe.toObject=Ib,oe.toDate=Gb,oe.toISOString=ub,oe.toJSON=Jb,oe.toString=tb,oe.unix=Fb,oe.valueOf=Eb,oe.creationData=Nb,oe.year=Vd,oe.isLeapYear=sa,oe.weekYear=Pb,oe.isoWeekYear=Qb,oe.quarter=oe.quarters=Vb,oe.month=ga,oe.daysInMonth=ha,oe.week=oe.weeks=Zb,oe.isoWeek=oe.isoWeeks=$b,oe.weeksInYear=Sb,oe.isoWeeksInYear=Rb,oe.date=ee,oe.day=oe.days=ec,oe.weekday=fc,oe.isoWeekday=gc,oe.dayOfYear=hc,oe.hour=oe.hours=je,oe.minute=oe.minutes=ke,oe.second=oe.seconds=le,oe.millisecond=oe.milliseconds=ne,oe.utcOffset=Ta,oe.utc=Va,oe.local=Wa,oe.parseZone=Xa,oe.hasAlignedHourOffset=Ya,oe.isDST=Za,oe.isDSTShifted=$a,oe.isLocal=_a,oe.isUtcOffset=ab,oe.isUtc=bb,oe.isUTC=bb,oe.zoneAbbr=oc,oe.zoneName=pc,oe.dates=u("dates accessor is deprecated. Use date instead.",ee),oe.months=u("months accessor is deprecated. Use month instead",ga),oe.years=u("years accessor is deprecated. Use year instead",Vd),oe.zone=u("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Ua);var pe=oe,qe={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},re={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},se="Invalid date",te="%d",ue=/\d{1,2}/,ve={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},we=A.prototype;we._calendar=qe,we.calendar=sc,we._longDateFormat=re,we.longDateFormat=tc,we._invalidDate=se,we.invalidDate=uc,we._ordinal=te,we.ordinal=vc,we._ordinalParse=ue,we.preparse=wc,we.postformat=wc,we._relativeTime=ve,we.relativeTime=xc,we.pastFuture=yc,we.set=y,we.months=ca,we._months=Ld,we.monthsShort=da,we._monthsShort=Md,we.monthsParse=ea,we._monthsRegex=Od,we.monthsRegex=ja,we._monthsShortRegex=Nd,we.monthsShortRegex=ia,we.week=Wb,we._week=de,we.firstDayOfYear=Yb,we.firstDayOfWeek=Xb,we.weekdays=ac,we._weekdays=fe,we.weekdaysMin=cc,we._weekdaysMin=he,we.weekdaysShort=bc,we._weekdaysShort=ge,we.weekdaysParse=dc,we.isPM=lc,we._meridiemParse=ie,we.meridiem=mc,E("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===r(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=u("moment.lang is deprecated. Use moment.locale instead.",E),a.langData=u("moment.langData is deprecated. Use moment.localeData instead.",H);var xe=Math.abs,ye=Qc("ms"),ze=Qc("s"),Ae=Qc("m"),Be=Qc("h"),Ce=Qc("d"),De=Qc("w"),Ee=Qc("M"),Fe=Qc("y"),Ge=Sc("milliseconds"),He=Sc("seconds"),Ie=Sc("minutes"),Je=Sc("hours"),Ke=Sc("days"),Le=Sc("months"),Me=Sc("years"),Ne=Math.round,Oe={s:45,m:45,h:22,d:26,M:11},Pe=Math.abs,Qe=Na.prototype;Qe.abs=Gc,Qe.add=Ic,Qe.subtract=Jc,Qe.as=Oc,Qe.asMilliseconds=ye,Qe.asSeconds=ze,Qe.asMinutes=Ae,Qe.asHours=Be,Qe.asDays=Ce,Qe.asWeeks=De,Qe.asMonths=Ee,Qe.asYears=Fe,Qe.valueOf=Pc,Qe._bubble=Lc,Qe.get=Rc,Qe.milliseconds=Ge,Qe.seconds=He,Qe.minutes=Ie,Qe.hours=Je,Qe.days=Ke,Qe.weeks=Tc,Qe.months=Le,Qe.years=Me,Qe.humanize=Xc,Qe.toISOString=Yc,Qe.toString=Yc,Qe.toJSON=Yc,Qe.locale=Ab,Qe.localeData=Bb,Qe.toIsoString=u("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Yc),Qe.lang=ce,R("X",0,0,"unix"),R("x",0,0,"valueOf"),W("x",ud),W("X",xd),$("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),$("x",function(a,b,c){c._d=new Date(r(a))}),a.version="2.12.0",b(Ja),a.fn=pe,a.min=La,a.max=Ma,a.now=Yd,a.utc=h,a.unix=qc,a.months=Bc,a.isDate=d,a.locale=E,a.invalid=l,a.duration=cb,a.isMoment=p,a.weekdays=Dc,a.parseZone=rc,a.localeData=H,a.isDuration=Oa,a.monthsShort=Cc,a.weekdaysMin=Fc,a.defineLocale=F,a.updateLocale=G,a.locales=I,a.weekdaysShort=Ec,a.normalizeUnits=K,a.relativeTimeThreshold=Wc,a.prototype=pe;var Re=a;return Re}); \ No newline at end of file +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return fd.apply(null,arguments)}function b(a){fd=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function f(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function g(a,b){for(var c in b)f(b,c)&&(a[c]=b[c]);return f(b,"toString")&&(a.toString=b.toString),f(b,"valueOf")&&(a.valueOf=b.valueOf),a}function h(a,b,c,d){return Ja(a,b,c,d,!0).utc()}function i(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function j(a){return null==a._pf&&(a._pf=i()),a._pf}function k(a){if(null==a._isValid){var b=j(a),c=gd.call(b.parsedDateParts,function(a){return null!=a});a._isValid=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c),a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function l(a){var b=h(NaN);return null!=a?g(j(b),a):j(b).userInvalidated=!0,b}function m(a){return void 0===a}function n(a,b){var c,d,e;if(m(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),m(b._i)||(a._i=b._i),m(b._f)||(a._f=b._f),m(b._l)||(a._l=b._l),m(b._strict)||(a._strict=b._strict),m(b._tzm)||(a._tzm=b._tzm),m(b._isUTC)||(a._isUTC=b._isUTC),m(b._offset)||(a._offset=b._offset),m(b._pf)||(a._pf=j(b)),m(b._locale)||(a._locale=b._locale),hd.length>0)for(c in hd)d=hd[c],e=b[d],m(e)||(a[d]=e);return a}function o(b){n(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),id===!1&&(id=!0,a.updateOffset(this),id=!1)}function p(a){return a instanceof o||null!=a&&null!=a._isAMomentObject}function q(a){return 0>a?Math.ceil(a):Math.floor(a)}function r(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=q(b)),c}function s(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&r(a[d])!==r(b[d]))&&g++;return g+f}function t(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function u(b,c){var d=!0;return g(function(){return null!=a.deprecationHandler&&a.deprecationHandler(null,b),d&&(t(b+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),d=!1),c.apply(this,arguments)},c)}function v(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),jd[b]||(t(c),jd[b]=!0)}function w(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function x(a){return"[object Object]"===Object.prototype.toString.call(a)}function y(a){var b,c;for(c in a)b=a[c],w(b)?this[c]=b:this["_"+c]=b;this._config=a,this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function z(a,b){var c,d=g({},a);for(c in b)f(b,c)&&(x(a[c])&&x(b[c])?(d[c]={},g(d[c],a[c]),g(d[c],b[c])):null!=b[c]?d[c]=b[c]:delete d[c]);return d}function A(a){null!=a&&this.set(a)}function B(a){return a?a.toLowerCase().replace("_","-"):a}function C(a){for(var b,c,d,e,f=0;f<a.length;){for(e=B(a[f]).split("-"),b=e.length,c=B(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=D(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&s(e,c,!0)>=b-1)break;b--}f++}return null}function D(a){var b=null;if(!nd[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=ld._abbr,require("./locale/"+a),E(b)}catch(c){}return nd[a]}function E(a,b){var c;return a&&(c=m(b)?H(a):F(a,b),c&&(ld=c)),ld._abbr}function F(a,b){return null!==b?(b.abbr=a,null!=nd[a]?(v("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale"),b=z(nd[a]._config,b)):null!=b.parentLocale&&(null!=nd[b.parentLocale]?b=z(nd[b.parentLocale]._config,b):v("parentLocaleUndefined","specified parentLocale is not defined yet")),nd[a]=new A(b),E(a),nd[a]):(delete nd[a],null)}function G(a,b){if(null!=b){var c;null!=nd[a]&&(b=z(nd[a]._config,b)),c=new A(b),c.parentLocale=nd[a],nd[a]=c,E(a)}else null!=nd[a]&&(null!=nd[a].parentLocale?nd[a]=nd[a].parentLocale:null!=nd[a]&&delete nd[a]);return nd[a]}function H(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return ld;if(!c(a)){if(b=D(a))return b;a=[a]}return C(a)}function I(){return kd(nd)}function J(a,b){var c=a.toLowerCase();od[c]=od[c+"s"]=od[b]=a}function K(a){return"string"==typeof a?od[a]||od[a.toLowerCase()]:void 0}function L(a){var b,c,d={};for(c in a)f(a,c)&&(b=K(c),b&&(d[b]=a[c]));return d}function M(b,c){return function(d){return null!=d?(O(this,b,d),a.updateOffset(this,c),this):N(this,b)}}function N(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function O(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}function P(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=K(a),w(this[a]))return this[a](b);return this}function Q(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function R(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(sd[a]=e),b&&(sd[b[0]]=function(){return Q(e.apply(this,arguments),b[1],b[2])}),c&&(sd[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function S(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function T(a){var b,c,d=a.match(pd);for(b=0,c=d.length;c>b;b++)sd[d[b]]?d[b]=sd[d[b]]:d[b]=S(d[b]);return function(b){var e,f="";for(e=0;c>e;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}}function U(a,b){return a.isValid()?(b=V(b,a.localeData()),rd[b]=rd[b]||T(b),rd[b](a)):a.localeData().invalidDate()}function V(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(qd.lastIndex=0;d>=0&&qd.test(a);)a=a.replace(qd,c),qd.lastIndex=0,d-=1;return a}function W(a,b,c){Kd[a]=w(b)?b:function(a,d){return a&&c?c:b}}function X(a,b){return f(Kd,a)?Kd[a](b._strict,b._locale):new RegExp(Y(a))}function Y(a){return Z(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function Z(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function $(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=r(a)}),c=0;c<a.length;c++)Ld[a[c]]=d}function _(a,b){$(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function aa(a,b,c){null!=b&&f(Ld,a)&&Ld[a](b,c._a,c,a)}function ba(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ca(a,b){return c(this._months)?this._months[a.month()]:this._months[Vd.test(b)?"format":"standalone"][a.month()]}function da(a,b){return c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[Vd.test(b)?"format":"standalone"][a.month()]}function ea(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;12>d;++d)f=h([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=md.call(this._shortMonthsParse,g),-1!==e?e:null):(e=md.call(this._longMonthsParse,g),-1!==e?e:null):"MMM"===b?(e=md.call(this._shortMonthsParse,g),-1!==e?e:(e=md.call(this._longMonthsParse,g),-1!==e?e:null)):(e=md.call(this._longMonthsParse,g),-1!==e?e:(e=md.call(this._shortMonthsParse,g),-1!==e?e:null))}function fa(a,b,c){var d,e,f;if(this._monthsParseExact)return ea.call(this,a,b,c);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function ga(a,b){var c;if(!a.isValid())return a;if("string"==typeof b)if(/^\d+$/.test(b))b=r(b);else if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),ba(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ha(b){return null!=b?(ga(this,b),a.updateOffset(this,!0),this):N(this,"Month")}function ia(){return ba(this.year(),this.month())}function ja(a){return this._monthsParseExact?(f(this,"_monthsRegex")||la.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex}function ka(a){return this._monthsParseExact?(f(this,"_monthsRegex")||la.call(this),a?this._monthsStrictRegex:this._monthsRegex):this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex}function la(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;12>b;b++)c=h([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(d.sort(a),e.sort(a),f.sort(a),b=0;12>b;b++)d[b]=Z(d[b]),e[b]=Z(e[b]),f[b]=Z(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")}function ma(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[Nd]<0||c[Nd]>11?Nd:c[Od]<1||c[Od]>ba(c[Md],c[Nd])?Od:c[Pd]<0||c[Pd]>24||24===c[Pd]&&(0!==c[Qd]||0!==c[Rd]||0!==c[Sd])?Pd:c[Qd]<0||c[Qd]>59?Qd:c[Rd]<0||c[Rd]>59?Rd:c[Sd]<0||c[Sd]>999?Sd:-1,j(a)._overflowDayOfYear&&(Md>b||b>Od)&&(b=Od),j(a)._overflowWeeks&&-1===b&&(b=Td),j(a)._overflowWeekday&&-1===b&&(b=Ud),j(a).overflow=b),a}function na(a){var b,c,d,e,f,g,h=a._i,i=$d.exec(h)||_d.exec(h);if(i){for(j(a).iso=!0,b=0,c=be.length;c>b;b++)if(be[b][1].exec(i[1])){e=be[b][0],d=be[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=ce.length;c>b;b++)if(ce[b][1].exec(i[3])){f=(i[2]||" ")+ce[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!ae.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),Ca(a)}else a._isValid=!1}function oa(b){var c=de.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(na(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function pa(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 100>a&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function qa(a){var b=new Date(Date.UTC.apply(null,arguments));return 100>a&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}function ra(a){return sa(a)?366:365}function sa(a){return a%4===0&&a%100!==0||a%400===0}function ta(){return sa(this.year())}function ua(a,b,c){var d=7+b-c,e=(7+qa(a,0,d).getUTCDay()-b)%7;return-e+d-1}function va(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ua(a,d,e),j=1+7*(b-1)+h+i;return 0>=j?(f=a-1,g=ra(f)+j):j>ra(a)?(f=a+1,g=j-ra(a)):(f=a,g=j),{year:f,dayOfYear:g}}function wa(a,b,c){var d,e,f=ua(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return 1>g?(e=a.year()-1,d=g+xa(e,b,c)):g>xa(a.year(),b,c)?(d=g-xa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function xa(a,b,c){var d=ua(a,b,c),e=ua(a+1,b,c);return(ra(a)-d+e)/7}function ya(a,b,c){return null!=a?a:null!=b?b:c}function za(b){var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}function Aa(a){var b,c,d,e,f=[];if(!a._d){for(d=za(a),a._w&&null==a._a[Od]&&null==a._a[Nd]&&Ba(a),a._dayOfYear&&(e=ya(a._a[Md],d[Md]),a._dayOfYear>ra(e)&&(j(a)._overflowDayOfYear=!0),c=qa(e,0,a._dayOfYear),a._a[Nd]=c.getUTCMonth(),a._a[Od]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[Pd]&&0===a._a[Qd]&&0===a._a[Rd]&&0===a._a[Sd]&&(a._nextDay=!0,a._a[Pd]=0),a._d=(a._useUTC?qa:pa).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[Pd]=24)}}function Ba(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ya(b.GG,a._a[Md],wa(Ka(),1,4).year),d=ya(b.W,1),e=ya(b.E,1),(1>e||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ya(b.gg,a._a[Md],wa(Ka(),f,g).year),d=ya(b.w,1),null!=b.d?(e=b.d,(0>e||e>6)&&(i=!0)):null!=b.e?(e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):e=f),1>d||d>xa(c,f,g)?j(a)._overflowWeeks=!0:null!=i?j(a)._overflowWeekday=!0:(h=va(c,d,e,f,g),a._a[Md]=h.year,a._dayOfYear=h.dayOfYear)}function Ca(b){if(b._f===a.ISO_8601)return void na(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=V(b._f,b._locale).match(pd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(X(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),sd[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),aa(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[Pd]<=12&&b._a[Pd]>0&&(j(b).bigHour=void 0),j(b).parsedDateParts=b._a.slice(0),j(b).meridiem=b._meridiem,b._a[Pd]=Da(b._locale,b._a[Pd],b._meridiem),Aa(b),ma(b)}function Da(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function Ea(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=n({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],Ca(b),k(b)&&(f+=j(b).charsLeftOver,f+=10*j(b).unusedTokens.length,j(b).score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function Fa(a){if(!a._d){var b=L(a._i);a._a=e([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),Aa(a)}}function Ga(a){var b=new o(ma(Ha(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Ha(a){var b=a._i,e=a._f;return a._locale=a._locale||H(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),p(b)?new o(ma(b)):(c(e)?Ea(a):e?Ca(a):d(b)?a._d=b:Ia(a),k(a)||(a._d=null),a))}function Ia(b){var f=b._i;void 0===f?b._d=new Date(a.now()):d(f)?b._d=new Date(f.valueOf()):"string"==typeof f?oa(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),Aa(b)):"object"==typeof f?Fa(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ja(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,Ga(f)}function Ka(a,b,c,d){return Ja(a,b,c,d,!1)}function La(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Ka();for(d=b[0],e=1;e<b.length;++e)(!b[e].isValid()||b[e][a](d))&&(d=b[e]);return d}function Ma(){var a=[].slice.call(arguments,0);return La("isBefore",a)}function Na(){var a=[].slice.call(arguments,0);return La("isAfter",a)}function Oa(a){var b=L(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+1e3*h*60*60,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=H(),this._bubble()}function Pa(a){return a instanceof Oa}function Qa(a,b){R(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+Q(~~(a/60),2)+b+Q(~~a%60,2)})}function Ra(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(ie)||["-",0,0],f=+(60*e[1])+r(e[2]);return"+"===e[0]?f:-f}function Sa(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(p(b)||d(b)?b.valueOf():Ka(b).valueOf())-e.valueOf(),e._d.setTime(e._d.valueOf()+f),a.updateOffset(e,!1),e):Ka(b).local()}function Ta(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ua(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=Ra(Hd,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ta(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?jb(this,db(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ta(this):null!=b?this:NaN}function Va(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Wa(a){return this.utcOffset(0,a)}function Xa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ta(this),"m")),this}function Ya(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ra(Gd,this._i)),this}function Za(a){return this.isValid()?(a=a?Ka(a).utcOffset():0,(this.utcOffset()-a)%60===0):!1}function $a(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function _a(){if(!m(this._isDSTShifted))return this._isDSTShifted;var a={};if(n(a,this),a=Ha(a),a._a){var b=a._isUTC?h(a._a):Ka(a._a);this._isDSTShifted=this.isValid()&&s(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function ab(){return this.isValid()?!this._isUTC:!1}function bb(){return this.isValid()?this._isUTC:!1}function cb(){return this.isValid()?this._isUTC&&0===this._offset:!1}function db(a,b){var c,d,e,g=a,h=null;return Pa(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=je.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:r(h[Od])*c,h:r(h[Pd])*c,m:r(h[Qd])*c,s:r(h[Rd])*c,ms:r(h[Sd])*c}):(h=ke.exec(a))?(c="-"===h[1]?-1:1,g={y:eb(h[2],c),M:eb(h[3],c),w:eb(h[4],c),d:eb(h[5],c),h:eb(h[6],c),m:eb(h[7],c),s:eb(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=gb(Ka(g.from),Ka(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Oa(g),Pa(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function eb(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function fb(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function gb(a,b){var c;return a.isValid()&&b.isValid()?(b=Sa(b,a),a.isBefore(b)?c=fb(a,b):(c=fb(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function hb(a){return 0>a?-1*Math.round(-1*a):Math.round(a)}function ib(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(v(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=db(c,d),jb(this,e,a),this}}function jb(b,c,d,e){var f=c._milliseconds,g=hb(c._days),h=hb(c._months);b.isValid()&&(e=null==e?!0:e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&O(b,"Date",N(b,"Date")+g*d),h&&ga(b,N(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function kb(a,b){var c=a||Ka(),d=Sa(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse",g=b&&(w(b[f])?b[f]():b[f]);return this.format(g||this.localeData().calendar(f,this,Ka(c)))}function lb(){return new o(this)}function mb(a,b){var c=p(a)?a:Ka(a);return this.isValid()&&c.isValid()?(b=K(m(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf()):!1}function nb(a,b){var c=p(a)?a:Ka(a);return this.isValid()&&c.isValid()?(b=K(m(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf()):!1}function ob(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function pb(a,b){var c,d=p(a)?a:Ka(a);return this.isValid()&&d.isValid()?(b=K(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf())):!1}function qb(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function rb(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function sb(a,b,c){var d,e,f,g;return this.isValid()?(d=Sa(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=K(b),"year"===b||"month"===b||"quarter"===b?(g=tb(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:q(g)):NaN):NaN}function tb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function ub(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function vb(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?w(Date.prototype.toISOString)?this.toDate().toISOString():U(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):U(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function wb(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=U(this,b);return this.localeData().postformat(c)}function xb(a,b){return this.isValid()&&(p(a)&&a.isValid()||Ka(a).isValid())?db({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function yb(a){return this.from(Ka(),a)}function zb(a,b){return this.isValid()&&(p(a)&&a.isValid()||Ka(a).isValid())?db({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function Ab(a){return this.to(Ka(),a)}function Bb(a){var b;return void 0===a?this._locale._abbr:(b=H(a),null!=b&&(this._locale=b),this)}function Cb(){return this._locale}function Db(a){switch(a=K(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function Eb(a){return a=K(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function Fb(){return this._d.valueOf()-6e4*(this._offset||0)}function Gb(){return Math.floor(this.valueOf()/1e3)}function Hb(){return this._offset?new Date(this.valueOf()):this._d}function Ib(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function Jb(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function Kb(){return this.isValid()?this.toISOString():null}function Lb(){return k(this)}function Mb(){return g({},j(this))}function Nb(){return j(this).overflow}function Ob(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Pb(a,b){R(0,[a,a.length],0,b)}function Qb(a){return Ub.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function Rb(a){return Ub.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Sb(){return xa(this.year(),1,4)}function Tb(){var a=this.localeData()._week;return xa(this.year(),a.dow,a.doy)}function Ub(a,b,c,d,e){var f;return null==a?wa(this,d,e).year:(f=xa(a,d,e),b>f&&(b=f),Vb.call(this,a,b,c,d,e))}function Vb(a,b,c,d,e){var f=va(a,b,c,d,e),g=qa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}function Wb(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}function Xb(a){return wa(a,this._week.dow,this._week.doy).week}function Yb(){return this._week.dow}function Zb(){return this._week.doy}function $b(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function _b(a){var b=wa(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function ac(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function bc(a,b){return c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]}function cc(a){return this._weekdaysShort[a.day()]}function dc(a){return this._weekdaysMin[a.day()]}function ec(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;7>d;++d)f=h([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=md.call(this._weekdaysParse,g),-1!==e?e:null):"ddd"===b?(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:null):(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null):"dddd"===b?(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null))):"ddd"===b?(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null))):(e=md.call(this._minWeekdaysParse,g),-1!==e?e:(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:null)))}function fc(a,b,c){var d,e,f;if(this._weekdaysParseExact)return ec.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;7>d;d++){if(e=h([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}function gc(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=ac(a,this.localeData()),this.add(a-b,"d")):b}function hc(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function ic(a){return this.isValid()?null==a?this.day()||7:this.day(this.day()%7?a:a-7):null!=a?this:NaN}function jc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex}function kc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex}function lc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex}function mc(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],i=[],j=[],k=[];for(b=0;7>b;b++)c=h([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),i.push(e),j.push(f),k.push(d),k.push(e),k.push(f);for(g.sort(a),i.sort(a),j.sort(a),k.sort(a),b=0;7>b;b++)i[b]=Z(i[b]),j[b]=Z(j[b]),k[b]=Z(k[b]);this._weekdaysRegex=new RegExp("^("+k.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+j.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")}function nc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function oc(){return this.hours()%12||12}function pc(){return this.hours()||24}function qc(a,b){R(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function rc(a,b){return b._meridiemParse}function sc(a){return"p"===(a+"").toLowerCase().charAt(0)}function tc(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function uc(a,b){b[Sd]=r(1e3*("0."+a))}function vc(){return this._isUTC?"UTC":""}function wc(){return this._isUTC?"Coordinated Universal Time":""}function xc(a){return Ka(1e3*a)}function yc(){return Ka.apply(null,arguments).parseZone()}function zc(a,b,c){var d=this._calendar[a];return w(d)?d.call(b,c):d}function Ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function Bc(){return this._invalidDate}function Cc(a){return this._ordinal.replace("%d",a)}function Dc(a){return a}function Ec(a,b,c,d){var e=this._relativeTime[c];return w(e)?e(a,b,c,d):e.replace(/%d/i,a)}function Fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return w(c)?c(b):c.replace(/%s/i,b)}function Gc(a,b,c,d){var e=H(),f=h().set(d,b);return e[c](f,a)}function Hc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return Gc(a,b,c,"month");var d,e=[];for(d=0;12>d;d++)e[d]=Gc(a,d,c,"month");return e}function Ic(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,"number"==typeof b&&(c=b,b=void 0),b=b||"");var e=H(),f=a?e._week.dow:0;if(null!=c)return Gc(b,(c+f)%7,d,"day");var g,h=[];for(g=0;7>g;g++)h[g]=Gc(b,(g+f)%7,d,"day");return h}function Jc(a,b){return Hc(a,b,"months")}function Kc(a,b){return Hc(a,b,"monthsShort")}function Lc(a,b,c){return Ic(a,b,c,"weekdays")}function Mc(a,b,c){return Ic(a,b,c,"weekdaysShort")}function Nc(a,b,c){return Ic(a,b,c,"weekdaysMin")}function Oc(){var a=this._data;return this._milliseconds=Le(this._milliseconds),this._days=Le(this._days),this._months=Le(this._months),a.milliseconds=Le(a.milliseconds),a.seconds=Le(a.seconds),a.minutes=Le(a.minutes),a.hours=Le(a.hours),a.months=Le(a.months),a.years=Le(a.years),this}function Pc(a,b,c,d){var e=db(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function Qc(a,b){return Pc(this,a,b,1)}function Rc(a,b){return Pc(this,a,b,-1)}function Sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function Tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*Sc(Vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=q(f/1e3),i.seconds=a%60,b=q(a/60),i.minutes=b%60,c=q(b/60),i.hours=c%24,g+=q(c/24),e=q(Uc(g)),h+=e,g-=Sc(Vc(e)),d=q(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function Uc(a){return 4800*a/146097}function Vc(a){return 146097*a/4800}function Wc(a){var b,c,d=this._milliseconds;if(a=K(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+Uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(Vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function Xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*r(this._months/12)}function Yc(a){return function(){return this.as(a)}}function Zc(a){ +return a=K(a),this[a+"s"]()}function $c(a){return function(){return this._data[a]}}function _c(){return q(this.days()/7)}function ad(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function bd(a,b,c){var d=db(a).abs(),e=_e(d.as("s")),f=_e(d.as("m")),g=_e(d.as("h")),h=_e(d.as("d")),i=_e(d.as("M")),j=_e(d.as("y")),k=e<af.s&&["s",e]||1>=f&&["m"]||f<af.m&&["mm",f]||1>=g&&["h"]||g<af.h&&["hh",g]||1>=h&&["d"]||h<af.d&&["dd",h]||1>=i&&["M"]||i<af.M&&["MM",i]||1>=j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,ad.apply(null,k)}function cd(a,b){return void 0===af[a]?!1:void 0===b?af[a]:(af[a]=b,!0)}function dd(a){var b=this.localeData(),c=bd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function ed(){var a,b,c,d=bf(this._milliseconds)/1e3,e=bf(this._days),f=bf(this._months);a=q(d/60),b=q(a/60),d%=60,a%=60,c=q(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var fd,gd;gd=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;c>d;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1};var hd=a.momentProperties=[],id=!1,jd={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var kd;kd=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)f(a,b)&&c.push(b);return c};var ld,md,nd={},od={},pd=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,qd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,rd={},sd={},td=/\d/,ud=/\d\d/,vd=/\d{3}/,wd=/\d{4}/,xd=/[+-]?\d{6}/,yd=/\d\d?/,zd=/\d\d\d\d?/,Ad=/\d\d\d\d\d\d?/,Bd=/\d{1,3}/,Cd=/\d{1,4}/,Dd=/[+-]?\d{1,6}/,Ed=/\d+/,Fd=/[+-]?\d+/,Gd=/Z|[+-]\d\d:?\d\d/gi,Hd=/Z|[+-]\d\d(?::?\d\d)?/gi,Id=/[+-]?\d+(\.\d{1,3})?/,Jd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Kd={},Ld={},Md=0,Nd=1,Od=2,Pd=3,Qd=4,Rd=5,Sd=6,Td=7,Ud=8;md=Array.prototype.indexOf?Array.prototype.indexOf:function(a){var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1},R("M",["MM",2],"Mo",function(){return this.month()+1}),R("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),R("MMMM",0,0,function(a){return this.localeData().months(this,a)}),J("month","M"),W("M",yd),W("MM",yd,ud),W("MMM",function(a,b){return b.monthsShortRegex(a)}),W("MMMM",function(a,b){return b.monthsRegex(a)}),$(["M","MM"],function(a,b){b[Nd]=r(a)-1}),$(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[Nd]=e:j(c).invalidMonth=a});var Vd=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,Wd="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Xd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),Yd=Jd,Zd=Jd,$d=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,_d=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ae=/Z|[+-]\d\d(?::?\d\d)?/,be=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],ce=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],de=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=u("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),R("Y",0,0,function(){var a=this.year();return 9999>=a?""+a:"+"+a}),R(0,["YY",2],0,function(){return this.year()%100}),R(0,["YYYY",4],0,"year"),R(0,["YYYYY",5],0,"year"),R(0,["YYYYYY",6,!0],0,"year"),J("year","y"),W("Y",Fd),W("YY",yd,ud),W("YYYY",Cd,wd),W("YYYYY",Dd,xd),W("YYYYYY",Dd,xd),$(["YYYYY","YYYYYY"],Md),$("YYYY",function(b,c){c[Md]=2===b.length?a.parseTwoDigitYear(b):r(b)}),$("YY",function(b,c){c[Md]=a.parseTwoDigitYear(b)}),$("Y",function(a,b){b[Md]=parseInt(a,10)}),a.parseTwoDigitYear=function(a){return r(a)+(r(a)>68?1900:2e3)};var ee=M("FullYear",!0);a.ISO_8601=function(){};var fe=u("moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Ka.apply(null,arguments);return this.isValid()&&a.isValid()?this>a?this:a:l()}),ge=u("moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Ka.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:l()}),he=function(){return Date.now?Date.now():+new Date};Qa("Z",":"),Qa("ZZ",""),W("Z",Hd),W("ZZ",Hd),$(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ra(Hd,a)});var ie=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var je=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,ke=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;db.fn=Oa.prototype;var le=ib(1,"add"),me=ib(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var ne=u("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});R(0,["gg",2],0,function(){return this.weekYear()%100}),R(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Pb("gggg","weekYear"),Pb("ggggg","weekYear"),Pb("GGGG","isoWeekYear"),Pb("GGGGG","isoWeekYear"),J("weekYear","gg"),J("isoWeekYear","GG"),W("G",Fd),W("g",Fd),W("GG",yd,ud),W("gg",yd,ud),W("GGGG",Cd,wd),W("gggg",Cd,wd),W("GGGGG",Dd,xd),W("ggggg",Dd,xd),_(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=r(a)}),_(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),R("Q",0,"Qo","quarter"),J("quarter","Q"),W("Q",td),$("Q",function(a,b){b[Nd]=3*(r(a)-1)}),R("w",["ww",2],"wo","week"),R("W",["WW",2],"Wo","isoWeek"),J("week","w"),J("isoWeek","W"),W("w",yd),W("ww",yd,ud),W("W",yd),W("WW",yd,ud),_(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=r(a)});var oe={dow:0,doy:6};R("D",["DD",2],"Do","date"),J("date","D"),W("D",yd),W("DD",yd,ud),W("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),$(["D","DD"],Od),$("Do",function(a,b){b[Od]=r(a.match(yd)[0],10)});var pe=M("Date",!0);R("d",0,"do","day"),R("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),R("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),R("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),R("e",0,0,"weekday"),R("E",0,0,"isoWeekday"),J("day","d"),J("weekday","e"),J("isoWeekday","E"),W("d",yd),W("e",yd),W("E",yd),W("dd",function(a,b){return b.weekdaysMinRegex(a)}),W("ddd",function(a,b){return b.weekdaysShortRegex(a)}),W("dddd",function(a,b){return b.weekdaysRegex(a)}),_(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);null!=e?b.d=e:j(c).invalidWeekday=a}),_(["d","e","E"],function(a,b,c,d){b[d]=r(a)});var qe="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),re="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),se="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),te=Jd,ue=Jd,ve=Jd;R("DDD",["DDDD",3],"DDDo","dayOfYear"),J("dayOfYear","DDD"),W("DDD",Bd),W("DDDD",vd),$(["DDD","DDDD"],function(a,b,c){c._dayOfYear=r(a)}),R("H",["HH",2],0,"hour"),R("h",["hh",2],0,oc),R("k",["kk",2],0,pc),R("hmm",0,0,function(){return""+oc.apply(this)+Q(this.minutes(),2)}),R("hmmss",0,0,function(){return""+oc.apply(this)+Q(this.minutes(),2)+Q(this.seconds(),2)}),R("Hmm",0,0,function(){return""+this.hours()+Q(this.minutes(),2)}),R("Hmmss",0,0,function(){return""+this.hours()+Q(this.minutes(),2)+Q(this.seconds(),2)}),qc("a",!0),qc("A",!1),J("hour","h"),W("a",rc),W("A",rc),W("H",yd),W("h",yd),W("HH",yd,ud),W("hh",yd,ud),W("hmm",zd),W("hmmss",Ad),W("Hmm",zd),W("Hmmss",Ad),$(["H","HH"],Pd),$(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),$(["h","hh"],function(a,b,c){b[Pd]=r(a),j(c).bigHour=!0}),$("hmm",function(a,b,c){var d=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d)),j(c).bigHour=!0}),$("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d,2)),b[Rd]=r(a.substr(e)),j(c).bigHour=!0}),$("Hmm",function(a,b,c){var d=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d))}),$("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d,2)),b[Rd]=r(a.substr(e))});var we=/[ap]\.?m?\.?/i,xe=M("Hours",!0);R("m",["mm",2],0,"minute"),J("minute","m"),W("m",yd),W("mm",yd,ud),$(["m","mm"],Qd);var ye=M("Minutes",!1);R("s",["ss",2],0,"second"),J("second","s"),W("s",yd),W("ss",yd,ud),$(["s","ss"],Rd);var ze=M("Seconds",!1);R("S",0,0,function(){return~~(this.millisecond()/100)}),R(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),R(0,["SSS",3],0,"millisecond"),R(0,["SSSS",4],0,function(){return 10*this.millisecond()}),R(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),R(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),R(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),R(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),R(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),J("millisecond","ms"),W("S",Bd,td),W("SS",Bd,ud),W("SSS",Bd,vd);var Ae;for(Ae="SSSS";Ae.length<=9;Ae+="S")W(Ae,Ed);for(Ae="S";Ae.length<=9;Ae+="S")$(Ae,uc);var Be=M("Milliseconds",!1);R("z",0,0,"zoneAbbr"),R("zz",0,0,"zoneName");var Ce=o.prototype;Ce.add=le,Ce.calendar=kb,Ce.clone=lb,Ce.diff=sb,Ce.endOf=Eb,Ce.format=wb,Ce.from=xb,Ce.fromNow=yb,Ce.to=zb,Ce.toNow=Ab,Ce.get=P,Ce.invalidAt=Nb,Ce.isAfter=mb,Ce.isBefore=nb,Ce.isBetween=ob,Ce.isSame=pb,Ce.isSameOrAfter=qb,Ce.isSameOrBefore=rb,Ce.isValid=Lb,Ce.lang=ne,Ce.locale=Bb,Ce.localeData=Cb,Ce.max=ge,Ce.min=fe,Ce.parsingFlags=Mb,Ce.set=P,Ce.startOf=Db,Ce.subtract=me,Ce.toArray=Ib,Ce.toObject=Jb,Ce.toDate=Hb,Ce.toISOString=vb,Ce.toJSON=Kb,Ce.toString=ub,Ce.unix=Gb,Ce.valueOf=Fb,Ce.creationData=Ob,Ce.year=ee,Ce.isLeapYear=ta,Ce.weekYear=Qb,Ce.isoWeekYear=Rb,Ce.quarter=Ce.quarters=Wb,Ce.month=ha,Ce.daysInMonth=ia,Ce.week=Ce.weeks=$b,Ce.isoWeek=Ce.isoWeeks=_b,Ce.weeksInYear=Tb,Ce.isoWeeksInYear=Sb,Ce.date=pe,Ce.day=Ce.days=gc,Ce.weekday=hc,Ce.isoWeekday=ic,Ce.dayOfYear=nc,Ce.hour=Ce.hours=xe,Ce.minute=Ce.minutes=ye,Ce.second=Ce.seconds=ze,Ce.millisecond=Ce.milliseconds=Be,Ce.utcOffset=Ua,Ce.utc=Wa,Ce.local=Xa,Ce.parseZone=Ya,Ce.hasAlignedHourOffset=Za,Ce.isDST=$a,Ce.isDSTShifted=_a,Ce.isLocal=ab,Ce.isUtcOffset=bb,Ce.isUtc=cb,Ce.isUTC=cb,Ce.zoneAbbr=vc,Ce.zoneName=wc,Ce.dates=u("dates accessor is deprecated. Use date instead.",pe),Ce.months=u("months accessor is deprecated. Use month instead",ha),Ce.years=u("years accessor is deprecated. Use year instead",ee),Ce.zone=u("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Va);var De=Ce,Ee={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Fe={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Ge="Invalid date",He="%d",Ie=/\d{1,2}/,Je={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Ke=A.prototype;Ke._calendar=Ee,Ke.calendar=zc,Ke._longDateFormat=Fe,Ke.longDateFormat=Ac,Ke._invalidDate=Ge,Ke.invalidDate=Bc,Ke._ordinal=He,Ke.ordinal=Cc,Ke._ordinalParse=Ie,Ke.preparse=Dc,Ke.postformat=Dc,Ke._relativeTime=Je,Ke.relativeTime=Ec,Ke.pastFuture=Fc,Ke.set=y,Ke.months=ca,Ke._months=Wd,Ke.monthsShort=da,Ke._monthsShort=Xd,Ke.monthsParse=fa,Ke._monthsRegex=Zd,Ke.monthsRegex=ka,Ke._monthsShortRegex=Yd,Ke.monthsShortRegex=ja,Ke.week=Xb,Ke._week=oe,Ke.firstDayOfYear=Zb,Ke.firstDayOfWeek=Yb,Ke.weekdays=bc,Ke._weekdays=qe,Ke.weekdaysMin=dc,Ke._weekdaysMin=se,Ke.weekdaysShort=cc,Ke._weekdaysShort=re,Ke.weekdaysParse=fc,Ke._weekdaysRegex=te,Ke.weekdaysRegex=jc,Ke._weekdaysShortRegex=ue,Ke.weekdaysShortRegex=kc,Ke._weekdaysMinRegex=ve,Ke.weekdaysMinRegex=lc,Ke.isPM=sc,Ke._meridiemParse=we,Ke.meridiem=tc,E("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===r(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=u("moment.lang is deprecated. Use moment.locale instead.",E),a.langData=u("moment.langData is deprecated. Use moment.localeData instead.",H);var Le=Math.abs,Me=Yc("ms"),Ne=Yc("s"),Oe=Yc("m"),Pe=Yc("h"),Qe=Yc("d"),Re=Yc("w"),Se=Yc("M"),Te=Yc("y"),Ue=$c("milliseconds"),Ve=$c("seconds"),We=$c("minutes"),Xe=$c("hours"),Ye=$c("days"),Ze=$c("months"),$e=$c("years"),_e=Math.round,af={s:45,m:45,h:22,d:26,M:11},bf=Math.abs,cf=Oa.prototype;cf.abs=Oc,cf.add=Qc,cf.subtract=Rc,cf.as=Wc,cf.asMilliseconds=Me,cf.asSeconds=Ne,cf.asMinutes=Oe,cf.asHours=Pe,cf.asDays=Qe,cf.asWeeks=Re,cf.asMonths=Se,cf.asYears=Te,cf.valueOf=Xc,cf._bubble=Tc,cf.get=Zc,cf.milliseconds=Ue,cf.seconds=Ve,cf.minutes=We,cf.hours=Xe,cf.days=Ye,cf.weeks=_c,cf.months=Ze,cf.years=$e,cf.humanize=dd,cf.toISOString=ed,cf.toString=ed,cf.toJSON=ed,cf.locale=Bb,cf.localeData=Cb,cf.toIsoString=u("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ed),cf.lang=ne,R("X",0,0,"unix"),R("x",0,0,"valueOf"),W("x",Fd),W("X",Id),$("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),$("x",function(a,b,c){c._d=new Date(r(a))}),a.version="2.13.0",b(Ka),a.fn=De,a.min=Ma,a.max=Na,a.now=he,a.utc=h,a.unix=xc,a.months=Jc,a.isDate=d,a.locale=E,a.invalid=l,a.duration=db,a.isMoment=p,a.weekdays=Lc,a.parseZone=yc,a.localeData=H,a.isDuration=Pa,a.monthsShort=Kc,a.weekdaysMin=Nc,a.defineLocale=F,a.updateLocale=G,a.locales=I,a.weekdaysShort=Mc,a.normalizeUnits=K,a.relativeTimeThreshold=cd,a.prototype=De;var df=a;return df}); \ No newline at end of file -- cgit v1.2.3