ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Sabre\CardDAV\Plugin Class Reference

CardDAV plugin. More...

+ Inheritance diagram for Sabre\CardDAV\Plugin:
+ Collaboration diagram for Sabre\CardDAV\Plugin:

Public Member Functions

 initialize (DAV\Server $server)
 Initializes the plugin. More...
 
 getFeatures ()
 Returns a list of supported features. More...
 
 getSupportedReportSet ($uri)
 Returns a list of reports this plugin supports. More...
 
 propFindEarly (DAV\PropFind $propFind, DAV\INode $node)
 Adds all CardDAV-specific properties. More...
 
 report ($reportName, $dom, $path)
 This functions handles REPORT requests specific to CardDAV. More...
 
 addressbookMultiGetReport ($report)
 This function handles the addressbook-multiget REPORT. More...
 
 beforeWriteContent ($path, DAV\IFile $node, &$data, &$modified)
 This method is triggered before a file gets updated with new content. More...
 
 beforeCreateFile ($path, &$data, DAV\ICollection $parentNode, &$modified)
 This method is triggered before a new file is created. More...
 
 validateFilters ($vcardData, array $filters, $test)
 Validates if a vcard makes it throught a list of filters. More...
 
 propFindLate (DAV\PropFind $propFind, DAV\INode $node)
 This event is triggered when fetching properties. More...
 
 htmlActionsPanel (DAV\INode $node, &$output)
 This method is used to generate HTML output for the Sabre\DAV\Browser\Plugin. More...
 
 httpAfterGet (RequestInterface $request, ResponseInterface $response)
 This event is triggered after GET requests. More...
 
 getPluginName ()
 Returns a plugin name. More...
 
 getPluginInfo ()
 Returns a bunch of meta-data about the plugin. More...
 
- Public Member Functions inherited from Sabre\DAV\ServerPlugin
 initialize (Server $server)
 This initializes the plugin. More...
 
 getFeatures ()
 This method should return a list of server-features. More...
 
 getHTTPMethods ($path)
 Use this method to tell the server this plugin defines additional HTTP methods. More...
 
 getPluginName ()
 Returns a plugin name. More...
 
 getSupportedReportSet ($uri)
 Returns a list of reports this plugin supports. More...
 
 getPluginInfo ()
 Returns a bunch of meta-data about the plugin. More...
 

Data Fields

const ADDRESSBOOK_ROOT = 'addressbooks'
 Url to the addressbooks. More...
 
const NS_CARDDAV = 'urn:ietf:params:xml:ns:carddav'
 xml namespace for CardDAV elements More...
 
 $directories = []
 

Protected Member Functions

 getAddressbookHomeForPrincipal ($principal)
 Returns the addressbook home for a given principal. More...
 
 validateVCard (&$data, &$modified)
 Checks if the submitted iCalendar data is in fact, valid. More...
 
 addressbookQueryReport ($report)
 This function handles the addressbook-query REPORT. More...
 
 validateParamFilters (array $vProperties, array $filters, $test)
 Validates if a param-filter can be applied to a specific property. More...
 
 validateTextMatches (array $texts, array $filters, $test)
 Validates if a text-filter can be applied to a specific property. More...
 
 negotiateVCard ($input, &$mimeType=null)
 This helper function performs the content-type negotiation for vcards. More...
 
 convertVCard ($data, $target, array $propertiesFilter=null)
 Converts a vcard blob to a different version, or jcard. More...
 

Protected Attributes

 $server
 
 $maxResourceSize = 10000000
 The default PDO storage uses a MySQL MEDIUMBLOB for iCalendar data, which can hold up to 2^24 = 16777216 bytes. More...
 

Detailed Description

CardDAV plugin.

The CardDAV plugin adds CardDAV functionality to the WebDAV server

Author
Evert Pot (http://evertpot.com/) @license http://sabre.io/license/ Modified BSD License

Definition at line 23 of file Plugin.php.

Member Function Documentation

◆ addressbookMultiGetReport()

Sabre\CardDAV\Plugin::addressbookMultiGetReport (   $report)

This function handles the addressbook-multiget REPORT.

This report is used by the client to fetch the content of a series of urls. Effectively avoiding a lot of redundant requests.

Parameters
Xml\Request\AddressBookMultiGetReport$report
Returns
void

Definition at line 236 of file Plugin.php.

236 {
237
238 $contentType = $report->contentType;
239 $version = $report->version;
240 if ($version) {
241 $contentType .= '; version=' . $version;
242 }
243
244 $vcardType = $this->negotiateVCard(
246 );
247
248 $propertyList = [];
249 $paths = array_map(
250 [$this->server, 'calculateUri'],
251 $report->hrefs
252 );
253 foreach ($this->server->getPropertiesForMultiplePaths($paths, $report->properties) as $props) {
254
255 if (isset($props['200']['{' . self::NS_CARDDAV . '}address-data'])) {
256
257 $props['200']['{' . self::NS_CARDDAV . '}address-data'] = $this->convertVCard(
258 $props[200]['{' . self::NS_CARDDAV . '}address-data'],
259 $vcardType
260 );
261
262 }
263 $propertyList[] = $props;
264
265 }
266
267 $prefer = $this->server->getHTTPPrefer();
268
269 $this->server->httpResponse->setStatus(207);
270 $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
271 $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
272 $this->server->httpResponse->setBody($this->server->generateMultiStatus($propertyList, $prefer['return'] === 'minimal'));
273
274 }
$version
Definition: build.php:27
convertVCard($data, $target, array $propertiesFilter=null)
Converts a vcard blob to a different version, or jcard.
Definition: Plugin.php:852
negotiateVCard($input, &$mimeType=null)
This helper function performs the content-type negotiation for vcards.
Definition: Plugin.php:805
if($argc< 2) $paths
Definition: migrateto20.php:44
if( $path[strlen( $path) - 1]==='/') if(is_dir($path)) if(!file_exists( $path)) if(preg_match('#\.php$#D', mb_strtolower($path, 'UTF-8'))) $contentType
Definition: module.php:144

References $contentType, $paths, $version, Sabre\CardDAV\Plugin\convertVCard(), and Sabre\CardDAV\Plugin\negotiateVCard().

Referenced by Sabre\CardDAV\Plugin\report().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ addressbookQueryReport()

Sabre\CardDAV\Plugin::addressbookQueryReport (   $report)
protected

This function handles the addressbook-query REPORT.

This report is used by the client to filter an addressbook based on a complex query.

Parameters
Xml\Request\AddressBookQueryReport$report
Returns
void

Definition at line 430 of file Plugin.php.

430 {
431
432 $depth = $this->server->getHTTPDepth(0);
433
434 if ($depth == 0) {
435 $candidateNodes = [
436 $this->server->tree->getNodeForPath($this->server->getRequestUri())
437 ];
438 if (!$candidateNodes[0] instanceof ICard) {
439 throw new ReportNotSupported('The addressbook-query report is not supported on this url with Depth: 0');
440 }
441 } else {
442 $candidateNodes = $this->server->tree->getChildren($this->server->getRequestUri());
443 }
444
445 $contentType = $report->contentType;
446 if ($report->version) {
447 $contentType .= '; version=' . $report->version;
448 }
449
450 $vcardType = $this->negotiateVCard(
452 );
453
454 $validNodes = [];
455 foreach ($candidateNodes as $node) {
456
457 if (!$node instanceof ICard)
458 continue;
459
460 $blob = $node->get();
461 if (is_resource($blob)) {
462 $blob = stream_get_contents($blob);
463 }
464
465 if (!$this->validateFilters($blob, $report->filters, $report->test)) {
466 continue;
467 }
468
469 $validNodes[] = $node;
470
471 if ($report->limit && $report->limit <= count($validNodes)) {
472 // We hit the maximum number of items, we can stop now.
473 break;
474 }
475
476 }
477
478 $result = [];
479 foreach ($validNodes as $validNode) {
480
481 if ($depth == 0) {
482 $href = $this->server->getRequestUri();
483 } else {
484 $href = $this->server->getRequestUri() . '/' . $validNode->getName();
485 }
486
487 list($props) = $this->server->getPropertiesForPath($href, $report->properties, 0);
488
489 if (isset($props[200]['{' . self::NS_CARDDAV . '}address-data'])) {
490
491 $props[200]['{' . self::NS_CARDDAV . '}address-data'] = $this->convertVCard(
492 $props[200]['{' . self::NS_CARDDAV . '}address-data'],
493 $vcardType,
494 $report->addressDataProperties
495 );
496
497 }
498 $result[] = $props;
499
500 }
501
502 $prefer = $this->server->getHTTPPrefer();
503
504 $this->server->httpResponse->setStatus(207);
505 $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
506 $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
507 $this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return'] === 'minimal'));
508
509 }
$result
validateFilters($vcardData, array $filters, $test)
Validates if a vcard makes it throught a list of filters.
Definition: Plugin.php:519

References $contentType, $result, Sabre\CardDAV\Plugin\convertVCard(), Sabre\CardDAV\Plugin\negotiateVCard(), and Sabre\CardDAV\Plugin\validateFilters().

+ Here is the call graph for this function:

◆ beforeCreateFile()

Sabre\CardDAV\Plugin::beforeCreateFile (   $path,
$data,
DAV\ICollection  $parentNode,
$modified 
)

This method is triggered before a new file is created.

This plugin uses this method to ensure that Card nodes receive valid vcard data.

Parameters
string$path
resource$data
DAV\ICollection$parentNode
bool$modifiedShould be set to true, if this event handler changed &$data.
Returns
void

Definition at line 311 of file Plugin.php.

311 {
312
313 if (!$parentNode instanceof IAddressBook)
314 return;
315
316 $this->validateVCard($data, $modified);
317
318 }
validateVCard(&$data, &$modified)
Checks if the submitted iCalendar data is in fact, valid.
Definition: Plugin.php:330
$data
Definition: bench.php:6

References $data, and Sabre\CardDAV\Plugin\validateVCard().

+ Here is the call graph for this function:

◆ beforeWriteContent()

Sabre\CardDAV\Plugin::beforeWriteContent (   $path,
DAV\IFile  $node,
$data,
$modified 
)

This method is triggered before a file gets updated with new content.

This plugin uses this method to ensure that Card nodes receive valid vcard data.

Parameters
string$path
DAV\IFile$node
resource$data
bool$modifiedShould be set to true, if this event handler changed &$data.
Returns
void

Definition at line 289 of file Plugin.php.

289 {
290
291 if (!$node instanceof ICard)
292 return;
293
294 $this->validateVCard($data, $modified);
295
296 }

References $data, and Sabre\CardDAV\Plugin\validateVCard().

+ Here is the call graph for this function:

◆ convertVCard()

Sabre\CardDAV\Plugin::convertVCard (   $data,
  $target,
array  $propertiesFilter = null 
)
protected

Converts a vcard blob to a different version, or jcard.

Parameters
string | resource$data
string$target
array$propertiesFilter
Returns
string

Definition at line 852 of file Plugin.php.

852 {
853
854 if (is_resource($data)) {
855 $data = stream_get_contents($data);
856 }
858 if (!empty($propertiesFilter)) {
859 $propertiesFilter = array_merge(['UID', 'VERSION', 'FN'], $propertiesFilter);
860 $keys = array_unique(array_map(function($child) {
861 return $child->name;
862 }, $input->children()));
863 $keys = array_diff($keys, $propertiesFilter);
864 foreach ($keys as $key) {
865 unset($input->$key);
866 }
867 $data = $input->serialize();
868 }
869 $output = null;
870 try {
871
872 switch ($target) {
873 default :
874 case 'vcard3' :
875 if ($input->getDocumentType() === VObject\Document::VCARD30) {
876 // Do nothing
877 return $data;
878 }
879 $output = $input->convert(VObject\Document::VCARD30);
880 return $output->serialize();
881 case 'vcard4' :
882 if ($input->getDocumentType() === VObject\Document::VCARD40) {
883 // Do nothing
884 return $data;
885 }
886 $output = $input->convert(VObject\Document::VCARD40);
887 return $output->serialize();
888 case 'jcard' :
889 $output = $input->convert(VObject\Document::VCARD40);
890 return json_encode($output);
891
892 }
893
894 } finally {
895
896 // Destroy circular references to PHP will GC the object.
897 $input->destroy();
898 if (!is_null($output)) {
899 $output->destroy();
900 }
901 }
902
903 }
const VCARD30
vCard 3.0.
Definition: Document.php:44
const VCARD40
vCard 4.0.
Definition: Document.php:49
static read($data, $options=0, $charset='UTF-8')
Parses a vCard or iCalendar object, and returns the top component.
Definition: Reader.php:42
$key
Definition: croninfo.php:18
$target
Definition: test.php:19
$keys

References $data, $input, $key, $keys, Sabre\VObject\$output, $target, Sabre\VObject\Reader\read(), Sabre\VObject\Document\VCARD30, and Sabre\VObject\Document\VCARD40.

Referenced by Sabre\CardDAV\Plugin\addressbookMultiGetReport(), and Sabre\CardDAV\Plugin\addressbookQueryReport().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getAddressbookHomeForPrincipal()

Sabre\CardDAV\Plugin::getAddressbookHomeForPrincipal (   $principal)
protected

Returns the addressbook home for a given principal.

Parameters
string$principal
Returns
string

Definition at line 219 of file Plugin.php.

219 {
220
221 list(, $principalId) = \Sabre\HTTP\URLUtil::splitPath($principal);
222 return self::ADDRESSBOOK_ROOT . '/' . $principalId;
223
224 }
static splitPath($path)
Returns the 'dirname' and 'basename' for a path.
Definition: URLUtil.php:83

References Sabre\HTTP\URLUtil\splitPath().

+ Here is the call graph for this function:

◆ getFeatures()

Sabre\CardDAV\Plugin::getFeatures ( )

Returns a list of supported features.

This is used in the DAV: header in the OPTIONS and PROPFIND requests.

Returns
array

Reimplemented from Sabre\DAV\ServerPlugin.

Definition at line 102 of file Plugin.php.

102 {
103
104 return ['addressbook'];
105
106 }

◆ getPluginInfo()

Sabre\CardDAV\Plugin::getPluginInfo ( )

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.

Returns
array

Reimplemented from Sabre\DAV\ServerPlugin.

Definition at line 930 of file Plugin.php.

930 {
931
932 return [
933 'name' => $this->getPluginName(),
934 'description' => 'Adds support for CardDAV (rfc6352)',
935 'link' => 'http://sabre.io/dav/carddav/',
936 ];
937
938 }
getPluginName()
Returns a plugin name.
Definition: Plugin.php:913

◆ getPluginName()

Sabre\CardDAV\Plugin::getPluginName ( )

Returns a plugin name.

Using this name other plugins will be able to access other plugins using DAV\Server::getPlugin

Returns
string

Reimplemented from Sabre\DAV\ServerPlugin.

Definition at line 913 of file Plugin.php.

913 {
914
915 return 'carddav';
916
917 }

◆ getSupportedReportSet()

Sabre\CardDAV\Plugin::getSupportedReportSet (   $uri)

Returns a list of reports this plugin supports.

This will be used in the {DAV:}supported-report-set property. Note that you still need to subscribe to the 'report' event to actually implement them

Parameters
string$uri
Returns
array

Reimplemented from Sabre\DAV\ServerPlugin.

Definition at line 118 of file Plugin.php.

118 {
119
120 $node = $this->server->tree->getNodeForPath($uri);
121 if ($node instanceof IAddressBook || $node instanceof ICard) {
122 return [
123 '{' . self::NS_CARDDAV . '}addressbook-multiget',
124 '{' . self::NS_CARDDAV . '}addressbook-query',
125 ];
126 }
127 return [];
128
129 }

◆ htmlActionsPanel()

Sabre\CardDAV\Plugin::htmlActionsPanel ( DAV\INode  $node,
$output 
)

This method is used to generate HTML output for the Sabre\DAV\Browser\Plugin.

This allows us to generate an interface users can use to create new addressbooks.

Parameters
DAV\INode$node
string$output
Returns
bool

Definition at line 744 of file Plugin.php.

744 {
745
746 if (!$node instanceof AddressBookHome)
747 return;
748
749 $output .= '<tr><td colspan="2"><form method="post" action="">
750 <h3>Create new address book</h3>
751 <input type="hidden" name="sabreAction" value="mkcol" />
752 <input type="hidden" name="resourceType" value="{DAV:}collection,{' . self::NS_CARDDAV . '}addressbook" />
753 <label>Name (uri):</label> <input type="text" name="name" /><br />
754 <label>Display name:</label> <input type="text" name="{DAV:}displayname" /><br />
755 <input type="submit" value="create" />
756 </form>
757 </td></tr>';
758
759 return false;
760
761 }

References Sabre\VObject\$output.

◆ httpAfterGet()

Sabre\CardDAV\Plugin::httpAfterGet ( RequestInterface  $request,
ResponseInterface  $response 
)

This event is triggered after GET requests.

This is used to transform data into jCal, if this was requested.

Parameters
RequestInterface$request
ResponseInterface$response
Returns
void

Definition at line 772 of file Plugin.php.

772 {
773
774 if (strpos($response->getHeader('Content-Type'), 'text/vcard') === false) {
775 return;
776 }
777
778 $target = $this->negotiateVCard($request->getHeader('Accept'), $mimeType);
779
780 $newBody = $this->convertVCard(
781 $response->getBody(),
782 $target
783 );
784
785 $response->setBody($newBody);
786 $response->setHeader('Content-Type', $mimeType . '; charset=utf-8');
787 $response->setHeader('Content-Length', strlen($newBody));
788
789 }
getBody()
Returns the message body, as it's internal representation.
getHeader($name)
Returns a specific HTTP header, based on it's name.
$response

References $request, $response, and $target.

◆ initialize()

Sabre\CardDAV\Plugin::initialize ( DAV\Server  $server)

Initializes the plugin.

Parameters
DAV\Server$server
Returns
void

Definition at line 63 of file Plugin.php.

63 {
64
65 /* Events */
66 $server->on('propFind', [$this, 'propFindEarly']);
67 $server->on('propFind', [$this, 'propFindLate'], 150);
68 $server->on('report', [$this, 'report']);
69 $server->on('onHTMLActionsPanel', [$this, 'htmlActionsPanel']);
70 $server->on('beforeWriteContent', [$this, 'beforeWriteContent']);
71 $server->on('beforeCreateFile', [$this, 'beforeCreateFile']);
72 $server->on('afterMethod:GET', [$this, 'httpAfterGet']);
73
74 $server->xml->namespaceMap[self::NS_CARDDAV] = 'card';
75
76 $server->xml->elementMap['{' . self::NS_CARDDAV . '}addressbook-query'] = 'Sabre\\CardDAV\\Xml\\Request\\AddressBookQueryReport';
77 $server->xml->elementMap['{' . self::NS_CARDDAV . '}addressbook-multiget'] = 'Sabre\\CardDAV\\Xml\\Request\\AddressBookMultiGetReport';
78
79 /* Mapping Interfaces to {DAV:}resourcetype values */
80 $server->resourceTypeMapping['Sabre\\CardDAV\\IAddressBook'] = '{' . self::NS_CARDDAV . '}addressbook';
81 $server->resourceTypeMapping['Sabre\\CardDAV\\IDirectory'] = '{' . self::NS_CARDDAV . '}directory';
82
83 /* Adding properties that may never be changed */
84 $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-address-data';
85 $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}max-resource-size';
86 $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}addressbook-home-set';
87 $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-collation-set';
88
89 $server->xml->elementMap['{http://calendarserver.org/ns/}me-card'] = 'Sabre\\DAV\\Xml\\Property\\Href';
90
91 $this->server = $server;
92
93 }
const NS_CARDDAV
xml namespace for CardDAV elements
Definition: Plugin.php:33

References Sabre\CardDAV\Plugin\$server, and Sabre\CardDAV\Plugin\NS_CARDDAV.

◆ negotiateVCard()

Sabre\CardDAV\Plugin::negotiateVCard (   $input,
$mimeType = null 
)
protected

This helper function performs the content-type negotiation for vcards.

It will return one of the following strings:

  1. vcard3
  2. vcard4
  3. jcard

It defaults to vcard3.

Parameters
string$input
string$mimeType
Returns
string

Definition at line 805 of file Plugin.php.

805 {
806
808 $input,
809 [
810 // Most often used mime-type. Version 3
811 'text/x-vcard',
812 // The correct standard mime-type. Defaults to version 3 as
813 // well.
814 'text/vcard',
815 // vCard 4
816 'text/vcard; version=4.0',
817 // vCard 3
818 'text/vcard; version=3.0',
819 // jCard
820 'application/vcard+json',
821 ]
822 );
823
824 $mimeType = $result;
825 switch ($result) {
826
827 default :
828 case 'text/x-vcard' :
829 case 'text/vcard' :
830 case 'text/vcard; version=3.0' :
831 $mimeType = 'text/vcard';
832 return 'vcard3';
833 case 'text/vcard; version=4.0' :
834 return 'vcard4';
835 case 'application/vcard+json' :
836 return 'jcard';
837
838 // @codeCoverageIgnoreStart
839 }
840 // @codeCoverageIgnoreEnd
841
842 }
static negotiate($acceptHeaderValue, array $availableOptions)
Deprecated! Use negotiateContentType.
Definition: Util.php:38

References $input, $result, and Sabre\HTTP\Util\negotiate().

Referenced by Sabre\CardDAV\Plugin\addressbookMultiGetReport(), and Sabre\CardDAV\Plugin\addressbookQueryReport().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ propFindEarly()

Sabre\CardDAV\Plugin::propFindEarly ( DAV\PropFind  $propFind,
DAV\INode  $node 
)

Adds all CardDAV-specific properties.

Parameters
DAV\PropFind$propFind
DAV\INode$node
Returns
void

Definition at line 139 of file Plugin.php.

139 {
140
141 $ns = '{' . self::NS_CARDDAV . '}';
142
143 if ($node instanceof IAddressBook) {
144
145 $propFind->handle($ns . 'max-resource-size', $this->maxResourceSize);
146 $propFind->handle($ns . 'supported-address-data', function() {
147 return new Xml\Property\SupportedAddressData();
148 });
149 $propFind->handle($ns . 'supported-collation-set', function() {
150 return new Xml\Property\SupportedCollationSet();
151 });
152
153 }
154 if ($node instanceof DAVACL\IPrincipal) {
155
156 $path = $propFind->getPath();
157
158 $propFind->handle('{' . self::NS_CARDDAV . '}addressbook-home-set', function() use ($path) {
159 return new LocalHref($this->getAddressBookHomeForPrincipal($path) . '/');
160 });
161
162 if ($this->directories) $propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function() {
163 return new LocalHref($this->directories);
164 });
165
166 }
167
168 if ($node instanceof ICard) {
169
170 // The address-data property is not supposed to be a 'real'
171 // property, but in large chunks of the spec it does act as such.
172 // Therefore we simply expose it as a property.
173 $propFind->handle('{' . self::NS_CARDDAV . '}address-data', function() use ($node) {
174 $val = $node->get();
175 if (is_resource($val))
176 $val = stream_get_contents($val);
177
178 return $val;
179
180 });
181
182 }
183
184 }
$path
Definition: aliased.php:25

References $path.

◆ propFindLate()

Sabre\CardDAV\Plugin::propFindLate ( DAV\PropFind  $propFind,
DAV\INode  $node 
)

This event is triggered when fetching properties.

This event is scheduled late in the process, after most work for propfind has been done.

Parameters
DAV\PropFind$propFind
DAV\INode$node
Returns
void

Definition at line 718 of file Plugin.php.

718 {
719
720 // If the request was made using the SOGO connector, we must rewrite
721 // the content-type property. By default SabreDAV will send back
722 // text/x-vcard; charset=utf-8, but for SOGO we must strip that last
723 // part.
724 if (strpos($this->server->httpRequest->getHeader('User-Agent'), 'Thunderbird') === false) {
725 return;
726 }
727 $contentType = $propFind->get('{DAV:}getcontenttype');
728 list($part) = explode(';', $contentType);
729 if ($part === 'text/x-vcard' || $part === 'text/vcard') {
730 $propFind->set('{DAV:}getcontenttype', 'text/x-vcard');
731 }
732
733 }

References $contentType.

◆ report()

Sabre\CardDAV\Plugin::report (   $reportName,
  $dom,
  $path 
)

This functions handles REPORT requests specific to CardDAV.

Parameters
string$reportName
\DOMNode$dom
mixed$path
Returns
bool

Definition at line 194 of file Plugin.php.

194 {
195
196 switch ($reportName) {
197 case '{' . self::NS_CARDDAV . '}addressbook-multiget' :
198 $this->server->transactionType = 'report-addressbook-multiget';
199 $this->addressbookMultiGetReport($dom);
200 return false;
201 case '{' . self::NS_CARDDAV . '}addressbook-query' :
202 $this->server->transactionType = 'report-addressbook-query';
203 $this->addressBookQueryReport($dom);
204 return false;
205 default :
206 return;
207
208 }
209
210
211 }
addressbookMultiGetReport($report)
This function handles the addressbook-multiget REPORT.
Definition: Plugin.php:236

References Sabre\CardDAV\Plugin\addressbookMultiGetReport().

+ Here is the call graph for this function:

◆ validateFilters()

Sabre\CardDAV\Plugin::validateFilters (   $vcardData,
array  $filters,
  $test 
)

Validates if a vcard makes it throught a list of filters.

Parameters
string$vcardData
array$filters
string$testanyof or allof (which means OR or AND)
Returns
bool

Definition at line 519 of file Plugin.php.

519 {
520
521
522 if (!$filters) return true;
523 $vcard = VObject\Reader::read($vcardData);
524
525 foreach ($filters as $filter) {
526
527 $isDefined = isset($vcard->{$filter['name']});
528 if ($filter['is-not-defined']) {
529 if ($isDefined) {
530 $success = false;
531 } else {
532 $success = true;
533 }
534 } elseif ((!$filter['param-filters'] && !$filter['text-matches']) || !$isDefined) {
535
536 // We only need to check for existence
537 $success = $isDefined;
538
539 } else {
540
541 $vProperties = $vcard->select($filter['name']);
542
543 $results = [];
544 if ($filter['param-filters']) {
545 $results[] = $this->validateParamFilters($vProperties, $filter['param-filters'], $filter['test']);
546 }
547 if ($filter['text-matches']) {
548 $texts = [];
549 foreach ($vProperties as $vProperty)
550 $texts[] = $vProperty->getValue();
551
552 $results[] = $this->validateTextMatches($texts, $filter['text-matches'], $filter['test']);
553 }
554
555 if (count($results) === 1) {
556 $success = $results[0];
557 } else {
558 if ($filter['test'] === 'anyof') {
559 $success = $results[0] || $results[1];
560 } else {
561 $success = $results[0] && $results[1];
562 }
563 }
564
565 } // else
566
567 // There are two conditions where we can already determine whether
568 // or not this filter succeeds.
569 if ($test === 'anyof' && $success) {
570
571 // Destroy circular references to PHP will GC the object.
572 $vcard->destroy();
573
574 return true;
575 }
576 if ($test === 'allof' && !$success) {
577
578 // Destroy circular references to PHP will GC the object.
579 $vcard->destroy();
580
581 return false;
582 }
583
584 } // foreach
585
586
587 // Destroy circular references to PHP will GC the object.
588 $vcard->destroy();
589
590 // If we got all the way here, it means we haven't been able to
591 // determine early if the test failed or not.
592 //
593 // This implies for 'anyof' that the test failed, and for 'allof' that
594 // we succeeded. Sounds weird, but makes sense.
595 return $test === 'allof';
596
597 }
$test
Definition: Utf8Test.php:84
$success
Definition: Utf8Test.php:86
validateParamFilters(array $vProperties, array $filters, $test)
Validates if a param-filter can be applied to a specific property.
Definition: Plugin.php:610
validateTextMatches(array $texts, array $filters, $test)
Validates if a text-filter can be applied to a specific property.
Definition: Plugin.php:675
$results
Definition: svg-scanner.php:47

References $results, $success, $test, Sabre\VObject\Reader\read(), Sabre\CardDAV\Plugin\validateParamFilters(), and Sabre\CardDAV\Plugin\validateTextMatches().

Referenced by Sabre\CardDAV\Plugin\addressbookQueryReport().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validateParamFilters()

Sabre\CardDAV\Plugin::validateParamFilters ( array  $vProperties,
array  $filters,
  $test 
)
protected

Validates if a param-filter can be applied to a specific property.

Todo:
currently we're only validating the first parameter of the passed property. Any subsequence parameters with the same name are ignored.
Parameters
array$vProperties
array$filters
string$test
Returns
bool

Definition at line 610 of file Plugin.php.

610 {
611
612 foreach ($filters as $filter) {
613
614 $isDefined = false;
615 foreach ($vProperties as $vProperty) {
616 $isDefined = isset($vProperty[$filter['name']]);
617 if ($isDefined) break;
618 }
619
620 if ($filter['is-not-defined']) {
621 if ($isDefined) {
622 $success = false;
623 } else {
624 $success = true;
625 }
626
627 // If there's no text-match, we can just check for existence
628 } elseif (!$filter['text-match'] || !$isDefined) {
629
630 $success = $isDefined;
631
632 } else {
633
634 $success = false;
635 foreach ($vProperties as $vProperty) {
636 // If we got all the way here, we'll need to validate the
637 // text-match filter.
638 $success = DAV\StringUtil::textMatch($vProperty[$filter['name']]->getValue(), $filter['text-match']['value'], $filter['text-match']['collation'], $filter['text-match']['match-type']);
639 if ($success) break;
640 }
641 if ($filter['text-match']['negate-condition']) {
643 }
644
645 } // else
646
647 // There are two conditions where we can already determine whether
648 // or not this filter succeeds.
649 if ($test === 'anyof' && $success) {
650 return true;
651 }
652 if ($test === 'allof' && !$success) {
653 return false;
654 }
655
656 }
657
658 // If we got all the way here, it means we haven't been able to
659 // determine early if the test failed or not.
660 //
661 // This implies for 'anyof' that the test failed, and for 'allof' that
662 // we succeeded. Sounds weird, but makes sense.
663 return $test === 'allof';
664
665 }
static textMatch($haystack, $needle, $collation, $matchType='contains')
Checks if a needle occurs in a haystack ;)
Definition: StringUtil.php:27

References $success, $test, and Sabre\DAV\StringUtil\textMatch().

Referenced by Sabre\CardDAV\Plugin\validateFilters().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validateTextMatches()

Sabre\CardDAV\Plugin::validateTextMatches ( array  $texts,
array  $filters,
  $test 
)
protected

Validates if a text-filter can be applied to a specific property.

Parameters
array$texts
array$filters
string$test
Returns
bool

Definition at line 675 of file Plugin.php.

675 {
676
677 foreach ($filters as $filter) {
678
679 $success = false;
680 foreach ($texts as $haystack) {
681 $success = DAV\StringUtil::textMatch($haystack, $filter['value'], $filter['collation'], $filter['match-type']);
682
683 // Breaking on the first match
684 if ($success) break;
685 }
686 if ($filter['negate-condition']) {
688 }
689
690 if ($success && $test === 'anyof')
691 return true;
692
693 if (!$success && $test == 'allof')
694 return false;
695
696
697 }
698
699 // If we got all the way here, it means we haven't been able to
700 // determine early if the test failed or not.
701 //
702 // This implies for 'anyof' that the test failed, and for 'allof' that
703 // we succeeded. Sounds weird, but makes sense.
704 return $test === 'allof';
705
706 }

References $success, $test, and Sabre\DAV\StringUtil\textMatch().

Referenced by Sabre\CardDAV\Plugin\validateFilters().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validateVCard()

Sabre\CardDAV\Plugin::validateVCard ( $data,
$modified 
)
protected

Checks if the submitted iCalendar data is in fact, valid.

An exception is thrown if it's not.

Parameters
resource | string$data
bool$modifiedShould be set to true, if this event handler changed &$data.
Returns
void

Definition at line 330 of file Plugin.php.

330 {
331
332 // If it's a stream, we convert it to a string first.
333 if (is_resource($data)) {
334 $data = stream_get_contents($data);
335 }
336
337 $before = $data;
338
339 try {
340
341 // If the data starts with a [, we can reasonably assume we're dealing
342 // with a jCal object.
343 if (substr($data, 0, 1) === '[') {
345
346 // Converting $data back to iCalendar, as that's what we
347 // technically support everywhere.
348 $data = $vobj->serialize();
349 $modified = true;
350 } else {
352 }
353
354 } catch (VObject\ParseException $e) {
355
356 throw new DAV\Exception\UnsupportedMediaType('This resource only supports valid vCard or jCard data. Parse error: ' . $e->getMessage());
357
358 }
359
360 if ($vobj->name !== 'VCARD') {
361 throw new DAV\Exception\UnsupportedMediaType('This collection can only support vcard objects.');
362 }
363
365 $prefer = $this->server->getHTTPPrefer();
366
367 if ($prefer['handling'] !== 'strict') {
369 }
370
371 $messages = $vobj->validate($options);
372
373 $highestLevel = 0;
374 $warningMessage = null;
375
376 // $messages contains a list of problems with the vcard, along with
377 // their severity.
378 foreach ($messages as $message) {
379
380 if ($message['level'] > $highestLevel) {
381 // Recording the highest reported error level.
382 $highestLevel = $message['level'];
383 $warningMessage = $message['message'];
384 }
385
386 switch ($message['level']) {
387
388 case 1 :
389 // Level 1 means that there was a problem, but it was repaired.
390 $modified = true;
391 break;
392 case 2 :
393 // Level 2 means a warning, but not critical
394 break;
395 case 3 :
396 // Level 3 means a critical error
397 throw new DAV\Exception\UnsupportedMediaType('Validation error in vCard: ' . $message['message']);
398
399 }
400
401 }
402 if ($warningMessage) {
403 $this->server->httpResponse->setHeader(
404 'X-Sabre-Ew-Gross',
405 'vCard validation warning: ' . $warningMessage
406 );
407
408 // Re-serializing object.
409 $data = $vobj->serialize();
410 if (!$modified && strcmp($data, $before) !== 0) {
411 // This ensures that the system does not send an ETag back.
412 $modified = true;
413 }
414 }
415
416 // Destroy circular references to PHP will GC the object.
417 $vobj->destroy();
418 }
const PROFILE_CARDDAV
If this option is set, the validator will operate on the vcards on the assumption that the vcards nee...
Definition: Node.php:36
const REPAIR
The following constants are used by the validate() method.
Definition: Node.php:27
static readJson($data, $options=0)
Parses a jCard or jCal object, and returns the top component.
Definition: Reader.php:67
$messages
Definition: en.php:5
catch(Exception $e) $message
$vobj
Definition: rrulebench.php:21

References $data, $message, $messages, PHPMailer\PHPMailer\$options, $vobj, Sabre\VObject\Node\PROFILE_CARDDAV, Sabre\VObject\Reader\read(), Sabre\VObject\Reader\readJson(), and Sabre\VObject\Node\REPAIR.

Referenced by Sabre\CardDAV\Plugin\beforeCreateFile(), and Sabre\CardDAV\Plugin\beforeWriteContent().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $directories

Sabre\CardDAV\Plugin::$directories = []

Definition at line 41 of file Plugin.php.

◆ $maxResourceSize

Sabre\CardDAV\Plugin::$maxResourceSize = 10000000
protected

The default PDO storage uses a MySQL MEDIUMBLOB for iCalendar data, which can hold up to 2^24 = 16777216 bytes.

This is plenty. We're capping it to 10M here.

Definition at line 55 of file Plugin.php.

◆ $server

Sabre\CardDAV\Plugin::$server
protected

Definition at line 48 of file Plugin.php.

Referenced by Sabre\CardDAV\Plugin\initialize().

◆ ADDRESSBOOK_ROOT

const Sabre\CardDAV\Plugin::ADDRESSBOOK_ROOT = 'addressbooks'

Url to the addressbooks.

Definition at line 28 of file Plugin.php.

Referenced by Sabre\CardDAV\AddressBookRoot\getName().

◆ NS_CARDDAV

const Sabre\CardDAV\Plugin::NS_CARDDAV = 'urn:ietf:params:xml:ns:carddav'

xml namespace for CardDAV elements

Definition at line 33 of file Plugin.php.

Referenced by Sabre\CardDAV\Backend\PDO\createAddressBook(), Sabre\CardDAV\VCFExportPlugin\generateVCF(), Sabre\CardDAV\Backend\PDO\getAddressBooksForUser(), Sabre\CardDAV\VCFExportPlugin\httpGet(), Sabre\CardDAV\Plugin\initialize(), Sabre\CardDAV\PluginTest\testAddressBookHomeSet(), Sabre\CardDAV\PluginTest\testAddressbookPluginProperties(), Sabre\CardDAV\PluginTest\testConstruct(), Sabre\CardDAV\Backend\AbstractPDOTest\testCreateAddressBookSuccess(), Sabre\CardDAV\AddressBookHomeTest\testCreateExtendedCollection(), Sabre\CardDAV\PluginTest\testDirectoryGateway(), Sabre\CardDAV\Backend\AbstractPDOTest\testGetAddressBooksForUser(), Sabre\CardDAV\IDirectoryTest\testResourceType(), Sabre\CardDAV\Xml\Property\SupportedAddressDataTest\testSerialize(), Sabre\CardDAV\Xml\Property\SupportedCollationSetTest\testSerialize(), Sabre\CardDAV\PluginTest\testSupportedReportSet(), Sabre\CardDAV\Backend\AbstractPDOTest\testUpdateAddressBookInvalidProp(), Sabre\CardDAV\Backend\AbstractPDOTest\testUpdateAddressBookNoProps(), Sabre\CardDAV\Backend\AbstractPDOTest\testUpdateAddressBookSuccess(), Sabre\CardDAV\Backend\PDO\updateAddressBook(), Sabre\CardDAV\Xml\Filter\ParamFilter\xmlDeserialize(), Sabre\CardDAV\Xml\Filter\PropFilter\xmlDeserialize(), Sabre\CardDAV\Xml\Request\AddressBookMultiGetReport\xmlDeserialize(), Sabre\CardDAV\Xml\Request\AddressBookQueryReport\xmlDeserialize(), and Sabre\CardDAV\Xml\Property\SupportedAddressData\xmlSerialize().


The documentation for this class was generated from the following file: