Completed
Pull Request — developer (#4001)
by Thom
542:26 queued 508:45
created
libraries/SabreDAV/CalDAV/Xml/Request/InviteReply.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -97,7 +97,7 @@
 block discarded – undo
97 97
      * the next element.
98 98
      *
99 99
      * @param Reader $reader
100
-     * @return mixed
100
+     * @return InviteReply
101 101
      */
102 102
     static function xmlDeserialize(Reader $reader) {
103 103
 
Please login to merge, or discard this patch.
Unused Use Statements   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -2,12 +2,12 @@
 block discarded – undo
2 2
 
3 3
 namespace Sabre\CalDAV\Xml\Request;
4 4
 
5
-use Sabre\Xml\Reader;
6
-use Sabre\Xml\XmlDeserializable;
7
-use Sabre\Xml\Element\KeyValue;
8
-use Sabre\DAV\Exception\BadRequest;
9 5
 use Sabre\CalDAV\Plugin;
10 6
 use Sabre\CalDAV\SharingPlugin;
7
+use Sabre\DAV\Exception\BadRequest;
8
+use Sabre\Xml\Element\KeyValue;
9
+use Sabre\Xml\Reader;
10
+use Sabre\Xml\XmlDeserializable;
11 11
 
12 12
 /**
13 13
  * Invite-reply POST request parser
Please login to merge, or discard this patch.
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -22,128 +22,128 @@
 block discarded – undo
22 22
  */
23 23
 class InviteReply implements XmlDeserializable {
24 24
 
25
-    /**
26
-     * The sharee calendar user address.
27
-     *
28
-     * This is the address that the original invite was set to
29
-     *
30
-     * @var string
31
-     */
32
-    public $href;
33
-
34
-    /**
35
-     * The uri to the calendar that was being shared.
36
-     *
37
-     * @var string
38
-     */
39
-    public $calendarUri;
40
-
41
-    /**
42
-     * The id of the invite message that's being responded to
43
-     *
44
-     * @var string
45
-     */
46
-    public $inReplyTo;
47
-
48
-    /**
49
-     * An optional message
50
-     *
51
-     * @var string
52
-     */
53
-    public $summary;
54
-
55
-    /**
56
-     * Either SharingPlugin::STATUS_ACCEPTED or SharingPlugin::STATUS_DECLINED.
57
-     *
58
-     * @var int
59
-     */
60
-    public $status;
61
-
62
-    /**
63
-     * Constructor
64
-     *
65
-     * @param string $href
66
-     * @param string $calendarUri
67
-     * @param string $inReplyTo
68
-     * @param string $summary
69
-     * @param int $status
70
-     */
71
-    public function __construct($href, $calendarUri, $inReplyTo, $summary, $status) {
72
-
73
-        $this->href = $href;
74
-        $this->calendarUri = $calendarUri;
75
-        $this->inReplyTo = $inReplyTo;
76
-        $this->summary = $summary;
77
-        $this->status = $status;
78
-
79
-    }
80
-
81
-    /**
82
-     * The deserialize method is called during xml parsing.
83
-     *
84
-     * This method is called statictly, this is because in theory this method
85
-     * may be used as a type of constructor, or factory method.
86
-     *
87
-     * Often you want to return an instance of the current class, but you are
88
-     * free to return other data as well.
89
-     *
90
-     * You are responsible for advancing the reader to the next element. Not
91
-     * doing anything will result in a never-ending loop.
92
-     *
93
-     * If you just want to skip parsing for this element altogether, you can
94
-     * just call $reader->next();
95
-     *
96
-     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
97
-     * the next element.
98
-     *
99
-     * @param Reader $reader
100
-     * @return mixed
101
-     */
102
-    static function xmlDeserialize(Reader $reader) {
103
-
104
-        $elems = KeyValue::xmlDeserialize($reader);
105
-
106
-        $href = null;
107
-        $calendarUri = null;
108
-        $inReplyTo = null;
109
-        $summary = null;
110
-        $status = null;
111
-
112
-        foreach ($elems as $name => $value) {
113
-
114
-            switch ($name) {
115
-
116
-                case '{' . Plugin::NS_CALENDARSERVER . '}hosturl' :
117
-                    foreach ($value as $bla) {
118
-                        if ($bla['name'] === '{DAV:}href') {
119
-                            $calendarUri = $bla['value'];
120
-                        }
121
-                    }
122
-                    break;
123
-                case '{' . Plugin::NS_CALENDARSERVER . '}invite-accepted' :
124
-                    $status = SharingPlugin::STATUS_ACCEPTED;
125
-                    break;
126
-                case '{' . Plugin::NS_CALENDARSERVER . '}invite-declined' :
127
-                    $status = SharingPlugin::STATUS_DECLINED;
128
-                    break;
129
-                case '{' . Plugin::NS_CALENDARSERVER . '}in-reply-to' :
130
-                    $inReplyTo = $value;
131
-                    break;
132
-                case '{' . Plugin::NS_CALENDARSERVER . '}summary' :
133
-                    $summary = $value;
134
-                    break;
135
-                case '{DAV:}href' :
136
-                    $href = $value;
137
-                    break;
138
-            }
139
-
140
-        }
141
-        if (is_null($calendarUri)) {
142
-            throw new BadRequest('The {http://calendarserver.org/ns/}hosturl/{DAV:}href element must exist');
143
-        }
144
-
145
-        return new self($href, $calendarUri, $inReplyTo, $summary, $status);
146
-
147
-    }
25
+	/**
26
+	 * The sharee calendar user address.
27
+	 *
28
+	 * This is the address that the original invite was set to
29
+	 *
30
+	 * @var string
31
+	 */
32
+	public $href;
33
+
34
+	/**
35
+	 * The uri to the calendar that was being shared.
36
+	 *
37
+	 * @var string
38
+	 */
39
+	public $calendarUri;
40
+
41
+	/**
42
+	 * The id of the invite message that's being responded to
43
+	 *
44
+	 * @var string
45
+	 */
46
+	public $inReplyTo;
47
+
48
+	/**
49
+	 * An optional message
50
+	 *
51
+	 * @var string
52
+	 */
53
+	public $summary;
54
+
55
+	/**
56
+	 * Either SharingPlugin::STATUS_ACCEPTED or SharingPlugin::STATUS_DECLINED.
57
+	 *
58
+	 * @var int
59
+	 */
60
+	public $status;
61
+
62
+	/**
63
+	 * Constructor
64
+	 *
65
+	 * @param string $href
66
+	 * @param string $calendarUri
67
+	 * @param string $inReplyTo
68
+	 * @param string $summary
69
+	 * @param int $status
70
+	 */
71
+	public function __construct($href, $calendarUri, $inReplyTo, $summary, $status) {
72
+
73
+		$this->href = $href;
74
+		$this->calendarUri = $calendarUri;
75
+		$this->inReplyTo = $inReplyTo;
76
+		$this->summary = $summary;
77
+		$this->status = $status;
78
+
79
+	}
80
+
81
+	/**
82
+	 * The deserialize method is called during xml parsing.
83
+	 *
84
+	 * This method is called statictly, this is because in theory this method
85
+	 * may be used as a type of constructor, or factory method.
86
+	 *
87
+	 * Often you want to return an instance of the current class, but you are
88
+	 * free to return other data as well.
89
+	 *
90
+	 * You are responsible for advancing the reader to the next element. Not
91
+	 * doing anything will result in a never-ending loop.
92
+	 *
93
+	 * If you just want to skip parsing for this element altogether, you can
94
+	 * just call $reader->next();
95
+	 *
96
+	 * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
97
+	 * the next element.
98
+	 *
99
+	 * @param Reader $reader
100
+	 * @return mixed
101
+	 */
102
+	static function xmlDeserialize(Reader $reader) {
103
+
104
+		$elems = KeyValue::xmlDeserialize($reader);
105
+
106
+		$href = null;
107
+		$calendarUri = null;
108
+		$inReplyTo = null;
109
+		$summary = null;
110
+		$status = null;
111
+
112
+		foreach ($elems as $name => $value) {
113
+
114
+			switch ($name) {
115
+
116
+				case '{' . Plugin::NS_CALENDARSERVER . '}hosturl' :
117
+					foreach ($value as $bla) {
118
+						if ($bla['name'] === '{DAV:}href') {
119
+							$calendarUri = $bla['value'];
120
+						}
121
+					}
122
+					break;
123
+				case '{' . Plugin::NS_CALENDARSERVER . '}invite-accepted' :
124
+					$status = SharingPlugin::STATUS_ACCEPTED;
125
+					break;
126
+				case '{' . Plugin::NS_CALENDARSERVER . '}invite-declined' :
127
+					$status = SharingPlugin::STATUS_DECLINED;
128
+					break;
129
+				case '{' . Plugin::NS_CALENDARSERVER . '}in-reply-to' :
130
+					$inReplyTo = $value;
131
+					break;
132
+				case '{' . Plugin::NS_CALENDARSERVER . '}summary' :
133
+					$summary = $value;
134
+					break;
135
+				case '{DAV:}href' :
136
+					$href = $value;
137
+					break;
138
+			}
139
+
140
+		}
141
+		if (is_null($calendarUri)) {
142
+			throw new BadRequest('The {http://calendarserver.org/ns/}hosturl/{DAV:}href element must exist');
143
+		}
144
+
145
+		return new self($href, $calendarUri, $inReplyTo, $summary, $status);
146
+
147
+	}
148 148
 
149 149
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/CalDAV/Xml/Request/MkCalendar.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@
 block discarded – undo
55 55
      * the next element.
56 56
      *
57 57
      * @param Reader $reader
58
-     * @return mixed
58
+     * @return MkCalendar
59 59
      */
60 60
     static function xmlDeserialize(Reader $reader) {
61 61
 
Please login to merge, or discard this patch.
Indentation   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -18,62 +18,62 @@
 block discarded – undo
18 18
  */
19 19
 class MkCalendar implements XmlDeserializable {
20 20
 
21
-    /**
22
-     * The list of properties that will be set.
23
-     *
24
-     * @var array
25
-     */
26
-    public $properties = [];
21
+	/**
22
+	 * The list of properties that will be set.
23
+	 *
24
+	 * @var array
25
+	 */
26
+	public $properties = [];
27 27
 
28
-    /**
29
-     * Returns the list of properties the calendar will be initialized with.
30
-     *
31
-     * @return array
32
-     */
33
-    public function getProperties() {
28
+	/**
29
+	 * Returns the list of properties the calendar will be initialized with.
30
+	 *
31
+	 * @return array
32
+	 */
33
+	public function getProperties() {
34 34
 
35
-        return $this->properties;
35
+		return $this->properties;
36 36
 
37
-    }
37
+	}
38 38
 
39
-    /**
40
-     * The deserialize method is called during xml parsing.
41
-     *
42
-     * This method is called statictly, this is because in theory this method
43
-     * may be used as a type of constructor, or factory method.
44
-     *
45
-     * Often you want to return an instance of the current class, but you are
46
-     * free to return other data as well.
47
-     *
48
-     * You are responsible for advancing the reader to the next element. Not
49
-     * doing anything will result in a never-ending loop.
50
-     *
51
-     * If you just want to skip parsing for this element altogether, you can
52
-     * just call $reader->next();
53
-     *
54
-     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
55
-     * the next element.
56
-     *
57
-     * @param Reader $reader
58
-     * @return mixed
59
-     */
60
-    static function xmlDeserialize(Reader $reader) {
39
+	/**
40
+	 * The deserialize method is called during xml parsing.
41
+	 *
42
+	 * This method is called statictly, this is because in theory this method
43
+	 * may be used as a type of constructor, or factory method.
44
+	 *
45
+	 * Often you want to return an instance of the current class, but you are
46
+	 * free to return other data as well.
47
+	 *
48
+	 * You are responsible for advancing the reader to the next element. Not
49
+	 * doing anything will result in a never-ending loop.
50
+	 *
51
+	 * If you just want to skip parsing for this element altogether, you can
52
+	 * just call $reader->next();
53
+	 *
54
+	 * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
55
+	 * the next element.
56
+	 *
57
+	 * @param Reader $reader
58
+	 * @return mixed
59
+	 */
60
+	static function xmlDeserialize(Reader $reader) {
61 61
 
62
-        $self = new self();
62
+		$self = new self();
63 63
 
64
-        $elementMap = $reader->elementMap;
65
-        $elementMap['{DAV:}prop']   = 'Sabre\DAV\Xml\Element\Prop';
66
-        $elementMap['{DAV:}set']    = 'Sabre\Xml\Element\KeyValue';
67
-        $elems = $reader->parseInnerTree($elementMap);
64
+		$elementMap = $reader->elementMap;
65
+		$elementMap['{DAV:}prop']   = 'Sabre\DAV\Xml\Element\Prop';
66
+		$elementMap['{DAV:}set']    = 'Sabre\Xml\Element\KeyValue';
67
+		$elems = $reader->parseInnerTree($elementMap);
68 68
 
69
-        foreach ($elems as $elem) {
70
-            if ($elem['name'] === '{DAV:}set') {
71
-                $self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']);
72
-            }
73
-        }
69
+		foreach ($elems as $elem) {
70
+			if ($elem['name'] === '{DAV:}set') {
71
+				$self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']);
72
+			}
73
+		}
74 74
 
75
-        return $self;
75
+		return $self;
76 76
 
77
-    }
77
+	}
78 78
 
79 79
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/CalDAV/Xml/Request/Share.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -73,7 +73,7 @@
 block discarded – undo
73 73
      * the next element.
74 74
      *
75 75
      * @param Reader $reader
76
-     * @return mixed
76
+     * @return Share
77 77
      */
78 78
     static function xmlDeserialize(Reader $reader) {
79 79
 
Please login to merge, or discard this patch.
Unused Use Statements   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -2,9 +2,9 @@
 block discarded – undo
2 2
 
3 3
 namespace Sabre\CalDAV\Xml\Request;
4 4
 
5
+use Sabre\CalDAV\Plugin;
5 6
 use Sabre\Xml\Reader;
6 7
 use Sabre\Xml\XmlDeserializable;
7
-use Sabre\CalDAV\Plugin;
8 8
 
9 9
 /**
10 10
  * Share POST request parser
Please login to merge, or discard this patch.
Indentation   +93 added lines, -93 removed lines patch added patch discarded remove patch
@@ -19,98 +19,98 @@
 block discarded – undo
19 19
  */
20 20
 class Share implements XmlDeserializable {
21 21
 
22
-    /**
23
-     * The list of new people added or updated.
24
-     *
25
-     * Every element has the following keys:
26
-     * 1. href - An email address
27
-     * 2. commonName - Some name
28
-     * 3. summary - An optional description of the share
29
-     * 4. readOnly - true or false
30
-     *
31
-     * @var array
32
-     */
33
-    public $set = [];
34
-
35
-    /**
36
-     * List of people removed from the share list.
37
-     *
38
-     * The list is a flat list of email addresses (including mailto:).
39
-     *
40
-     * @var array
41
-     */
42
-    public $remove = [];
43
-
44
-    /**
45
-     * Constructor
46
-     *
47
-     * @param array $set
48
-     * @param array $remove
49
-     */
50
-    public function __construct(array $set, array $remove) {
51
-
52
-        $this->set = $set;
53
-        $this->remove = $remove;
54
-
55
-    }
56
-
57
-    /**
58
-     * The deserialize method is called during xml parsing.
59
-     *
60
-     * This method is called statictly, this is because in theory this method
61
-     * may be used as a type of constructor, or factory method.
62
-     *
63
-     * Often you want to return an instance of the current class, but you are
64
-     * free to return other data as well.
65
-     *
66
-     * You are responsible for advancing the reader to the next element. Not
67
-     * doing anything will result in a never-ending loop.
68
-     *
69
-     * If you just want to skip parsing for this element altogether, you can
70
-     * just call $reader->next();
71
-     *
72
-     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
73
-     * the next element.
74
-     *
75
-     * @param Reader $reader
76
-     * @return mixed
77
-     */
78
-    static function xmlDeserialize(Reader $reader) {
79
-
80
-        $elems = $reader->parseInnerTree([
81
-            '{' . Plugin::NS_CALENDARSERVER . '}set'    => 'Sabre\\Xml\\Element\\KeyValue',
82
-            '{' . Plugin::NS_CALENDARSERVER . '}remove' => 'Sabre\\Xml\\Element\\KeyValue',
83
-        ]);
84
-
85
-        $set = [];
86
-        $remove = [];
87
-
88
-        foreach ($elems as $elem) {
89
-            switch ($elem['name']) {
90
-
91
-                case '{' . Plugin::NS_CALENDARSERVER . '}set' :
92
-                    $sharee = $elem['value'];
93
-
94
-                    $sumElem = '{' . Plugin::NS_CALENDARSERVER . '}summary';
95
-                    $commonName = '{' . Plugin::NS_CALENDARSERVER . '}common-name';
96
-
97
-                    $set[] = [
98
-                        'href'       => $sharee['{DAV:}href'],
99
-                        'commonName' => isset($sharee[$commonName]) ? $sharee[$commonName] : null,
100
-                        'summary'    => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null,
101
-                        'readOnly'   => !array_key_exists('{' . Plugin::NS_CALENDARSERVER . '}read-write', $sharee),
102
-                    ];
103
-                    break;
104
-
105
-                case '{' . Plugin::NS_CALENDARSERVER . '}remove' :
106
-                    $remove[] = $elem['value']['{DAV:}href'];
107
-                    break;
108
-
109
-            }
110
-        }
111
-
112
-        return new self($set, $remove);
113
-
114
-    }
22
+	/**
23
+	 * The list of new people added or updated.
24
+	 *
25
+	 * Every element has the following keys:
26
+	 * 1. href - An email address
27
+	 * 2. commonName - Some name
28
+	 * 3. summary - An optional description of the share
29
+	 * 4. readOnly - true or false
30
+	 *
31
+	 * @var array
32
+	 */
33
+	public $set = [];
34
+
35
+	/**
36
+	 * List of people removed from the share list.
37
+	 *
38
+	 * The list is a flat list of email addresses (including mailto:).
39
+	 *
40
+	 * @var array
41
+	 */
42
+	public $remove = [];
43
+
44
+	/**
45
+	 * Constructor
46
+	 *
47
+	 * @param array $set
48
+	 * @param array $remove
49
+	 */
50
+	public function __construct(array $set, array $remove) {
51
+
52
+		$this->set = $set;
53
+		$this->remove = $remove;
54
+
55
+	}
56
+
57
+	/**
58
+	 * The deserialize method is called during xml parsing.
59
+	 *
60
+	 * This method is called statictly, this is because in theory this method
61
+	 * may be used as a type of constructor, or factory method.
62
+	 *
63
+	 * Often you want to return an instance of the current class, but you are
64
+	 * free to return other data as well.
65
+	 *
66
+	 * You are responsible for advancing the reader to the next element. Not
67
+	 * doing anything will result in a never-ending loop.
68
+	 *
69
+	 * If you just want to skip parsing for this element altogether, you can
70
+	 * just call $reader->next();
71
+	 *
72
+	 * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
73
+	 * the next element.
74
+	 *
75
+	 * @param Reader $reader
76
+	 * @return mixed
77
+	 */
78
+	static function xmlDeserialize(Reader $reader) {
79
+
80
+		$elems = $reader->parseInnerTree([
81
+			'{' . Plugin::NS_CALENDARSERVER . '}set'    => 'Sabre\\Xml\\Element\\KeyValue',
82
+			'{' . Plugin::NS_CALENDARSERVER . '}remove' => 'Sabre\\Xml\\Element\\KeyValue',
83
+		]);
84
+
85
+		$set = [];
86
+		$remove = [];
87
+
88
+		foreach ($elems as $elem) {
89
+			switch ($elem['name']) {
90
+
91
+				case '{' . Plugin::NS_CALENDARSERVER . '}set' :
92
+					$sharee = $elem['value'];
93
+
94
+					$sumElem = '{' . Plugin::NS_CALENDARSERVER . '}summary';
95
+					$commonName = '{' . Plugin::NS_CALENDARSERVER . '}common-name';
96
+
97
+					$set[] = [
98
+						'href'       => $sharee['{DAV:}href'],
99
+						'commonName' => isset($sharee[$commonName]) ? $sharee[$commonName] : null,
100
+						'summary'    => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null,
101
+						'readOnly'   => !array_key_exists('{' . Plugin::NS_CALENDARSERVER . '}read-write', $sharee),
102
+					];
103
+					break;
104
+
105
+				case '{' . Plugin::NS_CALENDARSERVER . '}remove' :
106
+					$remove[] = $elem['value']['{DAV:}href'];
107
+					break;
108
+
109
+			}
110
+		}
111
+
112
+		return new self($set, $remove);
113
+
114
+	}
115 115
 
116 116
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/CardDAV/AddressBookHome.php 3 patches
Unused Use Statements   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -3,8 +3,8 @@
 block discarded – undo
3 3
 namespace Sabre\CardDAV;
4 4
 
5 5
 use Sabre\DAV;
6
-use Sabre\DAV\MkCol;
7 6
 use Sabre\DAVACL;
7
+use Sabre\DAV\MkCol;
8 8
 use Sabre\Uri;
9 9
 
10 10
 /**
Please login to merge, or discard this patch.
Indentation   +240 added lines, -240 removed lines patch added patch discarded remove patch
@@ -18,245 +18,245 @@
 block discarded – undo
18 18
  */
19 19
 class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection, DAVACL\IACL {
20 20
 
21
-    /**
22
-     * Principal uri
23
-     *
24
-     * @var array
25
-     */
26
-    protected $principalUri;
27
-
28
-    /**
29
-     * carddavBackend
30
-     *
31
-     * @var Backend\BackendInterface
32
-     */
33
-    protected $carddavBackend;
34
-
35
-    /**
36
-     * Constructor
37
-     *
38
-     * @param Backend\BackendInterface $carddavBackend
39
-     * @param string $principalUri
40
-     */
41
-    public function __construct(Backend\BackendInterface $carddavBackend, $principalUri) {
42
-
43
-        $this->carddavBackend = $carddavBackend;
44
-        $this->principalUri = $principalUri;
45
-
46
-    }
47
-
48
-    /**
49
-     * Returns the name of this object
50
-     *
51
-     * @return string
52
-     */
53
-    public function getName() {
54
-
55
-        list(, $name) = Uri\split($this->principalUri);
56
-        return $name;
57
-
58
-    }
59
-
60
-    /**
61
-     * Updates the name of this object
62
-     *
63
-     * @param string $name
64
-     * @return void
65
-     */
66
-    public function setName($name) {
67
-
68
-        throw new DAV\Exception\MethodNotAllowed();
69
-
70
-    }
71
-
72
-    /**
73
-     * Deletes this object
74
-     *
75
-     * @return void
76
-     */
77
-    public function delete() {
78
-
79
-        throw new DAV\Exception\MethodNotAllowed();
80
-
81
-    }
82
-
83
-    /**
84
-     * Returns the last modification date
85
-     *
86
-     * @return int
87
-     */
88
-    public function getLastModified() {
89
-
90
-        return null;
91
-
92
-    }
93
-
94
-    /**
95
-     * Creates a new file under this object.
96
-     *
97
-     * This is currently not allowed
98
-     *
99
-     * @param string $filename
100
-     * @param resource $data
101
-     * @return void
102
-     */
103
-    public function createFile($filename, $data = null) {
104
-
105
-        throw new DAV\Exception\MethodNotAllowed('Creating new files in this collection is not supported');
106
-
107
-    }
108
-
109
-    /**
110
-     * Creates a new directory under this object.
111
-     *
112
-     * This is currently not allowed.
113
-     *
114
-     * @param string $filename
115
-     * @return void
116
-     */
117
-    public function createDirectory($filename) {
118
-
119
-        throw new DAV\Exception\MethodNotAllowed('Creating new collections in this collection is not supported');
120
-
121
-    }
122
-
123
-    /**
124
-     * Returns a single addressbook, by name
125
-     *
126
-     * @param string $name
127
-     * @return \AddressBook
128
-     */
129
-    public function getChild($name) {
130
-
131
-        foreach ($this->getChildren() as $child) {
132
-            if ($name == $child->getName())
133
-                return $child;
134
-
135
-        }
136
-        throw new DAV\Exception\NotFound('Addressbook with name \'' . $name . '\' could not be found');
137
-
138
-    }
139
-
140
-    /**
141
-     * Returns a list of addressbooks
142
-     *
143
-     * @return array
144
-     */
145
-    public function getChildren() {
146
-
147
-        $addressbooks = $this->carddavBackend->getAddressBooksForUser($this->principalUri);
148
-        $objs = [];
149
-        foreach ($addressbooks as $addressbook) {
150
-            $objs[] = new AddressBook($this->carddavBackend, $addressbook);
151
-        }
152
-        return $objs;
153
-
154
-    }
155
-
156
-    /**
157
-     * Creates a new address book.
158
-     *
159
-     * @param string $name
160
-     * @param MkCol $mkCol
161
-     * @throws DAV\Exception\InvalidResourceType
162
-     * @return void
163
-     */
164
-    public function createExtendedCollection($name, MkCol $mkCol) {
165
-
166
-        if (!$mkCol->hasResourceType('{' . Plugin::NS_CARDDAV . '}addressbook')) {
167
-            throw new DAV\Exception\InvalidResourceType('Unknown resourceType for this collection');
168
-        }
169
-        $properties = $mkCol->getRemainingValues();
170
-        $mkCol->setRemainingResultCode(201);
171
-        $this->carddavBackend->createAddressBook($this->principalUri, $name, $properties);
172
-
173
-    }
174
-
175
-    /**
176
-     * Returns the owner principal
177
-     *
178
-     * This must be a url to a principal, or null if there's no owner
179
-     *
180
-     * @return string|null
181
-     */
182
-    public function getOwner() {
183
-
184
-        return $this->principalUri;
185
-
186
-    }
187
-
188
-    /**
189
-     * Returns a group principal
190
-     *
191
-     * This must be a url to a principal, or null if there's no owner
192
-     *
193
-     * @return string|null
194
-     */
195
-    public function getGroup() {
196
-
197
-        return null;
198
-
199
-    }
200
-
201
-    /**
202
-     * Returns a list of ACE's for this node.
203
-     *
204
-     * Each ACE has the following properties:
205
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
206
-     *     currently the only supported privileges
207
-     *   * 'principal', a url to the principal who owns the node
208
-     *   * 'protected' (optional), indicating that this ACE is not allowed to
209
-     *      be updated.
210
-     *
211
-     * @return array
212
-     */
213
-    public function getACL() {
214
-
215
-        return [
216
-            [
217
-                'privilege' => '{DAV:}read',
218
-                'principal' => $this->principalUri,
219
-                'protected' => true,
220
-            ],
221
-            [
222
-                'privilege' => '{DAV:}write',
223
-                'principal' => $this->principalUri,
224
-                'protected' => true,
225
-            ],
226
-        ];
227
-
228
-    }
229
-
230
-    /**
231
-     * Updates the ACL
232
-     *
233
-     * This method will receive a list of new ACE's.
234
-     *
235
-     * @param array $acl
236
-     * @return void
237
-     */
238
-    public function setACL(array $acl) {
239
-
240
-        throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
241
-
242
-    }
243
-
244
-    /**
245
-     * Returns the list of supported privileges for this node.
246
-     *
247
-     * The returned data structure is a list of nested privileges.
248
-     * See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
249
-     * standard structure.
250
-     *
251
-     * If null is returned from this method, the default privilege set is used,
252
-     * which is fine for most common usecases.
253
-     *
254
-     * @return array|null
255
-     */
256
-    public function getSupportedPrivilegeSet() {
257
-
258
-        return null;
259
-
260
-    }
21
+	/**
22
+	 * Principal uri
23
+	 *
24
+	 * @var array
25
+	 */
26
+	protected $principalUri;
27
+
28
+	/**
29
+	 * carddavBackend
30
+	 *
31
+	 * @var Backend\BackendInterface
32
+	 */
33
+	protected $carddavBackend;
34
+
35
+	/**
36
+	 * Constructor
37
+	 *
38
+	 * @param Backend\BackendInterface $carddavBackend
39
+	 * @param string $principalUri
40
+	 */
41
+	public function __construct(Backend\BackendInterface $carddavBackend, $principalUri) {
42
+
43
+		$this->carddavBackend = $carddavBackend;
44
+		$this->principalUri = $principalUri;
45
+
46
+	}
47
+
48
+	/**
49
+	 * Returns the name of this object
50
+	 *
51
+	 * @return string
52
+	 */
53
+	public function getName() {
54
+
55
+		list(, $name) = Uri\split($this->principalUri);
56
+		return $name;
57
+
58
+	}
59
+
60
+	/**
61
+	 * Updates the name of this object
62
+	 *
63
+	 * @param string $name
64
+	 * @return void
65
+	 */
66
+	public function setName($name) {
67
+
68
+		throw new DAV\Exception\MethodNotAllowed();
69
+
70
+	}
71
+
72
+	/**
73
+	 * Deletes this object
74
+	 *
75
+	 * @return void
76
+	 */
77
+	public function delete() {
78
+
79
+		throw new DAV\Exception\MethodNotAllowed();
80
+
81
+	}
82
+
83
+	/**
84
+	 * Returns the last modification date
85
+	 *
86
+	 * @return int
87
+	 */
88
+	public function getLastModified() {
89
+
90
+		return null;
91
+
92
+	}
93
+
94
+	/**
95
+	 * Creates a new file under this object.
96
+	 *
97
+	 * This is currently not allowed
98
+	 *
99
+	 * @param string $filename
100
+	 * @param resource $data
101
+	 * @return void
102
+	 */
103
+	public function createFile($filename, $data = null) {
104
+
105
+		throw new DAV\Exception\MethodNotAllowed('Creating new files in this collection is not supported');
106
+
107
+	}
108
+
109
+	/**
110
+	 * Creates a new directory under this object.
111
+	 *
112
+	 * This is currently not allowed.
113
+	 *
114
+	 * @param string $filename
115
+	 * @return void
116
+	 */
117
+	public function createDirectory($filename) {
118
+
119
+		throw new DAV\Exception\MethodNotAllowed('Creating new collections in this collection is not supported');
120
+
121
+	}
122
+
123
+	/**
124
+	 * Returns a single addressbook, by name
125
+	 *
126
+	 * @param string $name
127
+	 * @return \AddressBook
128
+	 */
129
+	public function getChild($name) {
130
+
131
+		foreach ($this->getChildren() as $child) {
132
+			if ($name == $child->getName())
133
+				return $child;
134
+
135
+		}
136
+		throw new DAV\Exception\NotFound('Addressbook with name \'' . $name . '\' could not be found');
137
+
138
+	}
139
+
140
+	/**
141
+	 * Returns a list of addressbooks
142
+	 *
143
+	 * @return array
144
+	 */
145
+	public function getChildren() {
146
+
147
+		$addressbooks = $this->carddavBackend->getAddressBooksForUser($this->principalUri);
148
+		$objs = [];
149
+		foreach ($addressbooks as $addressbook) {
150
+			$objs[] = new AddressBook($this->carddavBackend, $addressbook);
151
+		}
152
+		return $objs;
153
+
154
+	}
155
+
156
+	/**
157
+	 * Creates a new address book.
158
+	 *
159
+	 * @param string $name
160
+	 * @param MkCol $mkCol
161
+	 * @throws DAV\Exception\InvalidResourceType
162
+	 * @return void
163
+	 */
164
+	public function createExtendedCollection($name, MkCol $mkCol) {
165
+
166
+		if (!$mkCol->hasResourceType('{' . Plugin::NS_CARDDAV . '}addressbook')) {
167
+			throw new DAV\Exception\InvalidResourceType('Unknown resourceType for this collection');
168
+		}
169
+		$properties = $mkCol->getRemainingValues();
170
+		$mkCol->setRemainingResultCode(201);
171
+		$this->carddavBackend->createAddressBook($this->principalUri, $name, $properties);
172
+
173
+	}
174
+
175
+	/**
176
+	 * Returns the owner principal
177
+	 *
178
+	 * This must be a url to a principal, or null if there's no owner
179
+	 *
180
+	 * @return string|null
181
+	 */
182
+	public function getOwner() {
183
+
184
+		return $this->principalUri;
185
+
186
+	}
187
+
188
+	/**
189
+	 * Returns a group principal
190
+	 *
191
+	 * This must be a url to a principal, or null if there's no owner
192
+	 *
193
+	 * @return string|null
194
+	 */
195
+	public function getGroup() {
196
+
197
+		return null;
198
+
199
+	}
200
+
201
+	/**
202
+	 * Returns a list of ACE's for this node.
203
+	 *
204
+	 * Each ACE has the following properties:
205
+	 *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
206
+	 *     currently the only supported privileges
207
+	 *   * 'principal', a url to the principal who owns the node
208
+	 *   * 'protected' (optional), indicating that this ACE is not allowed to
209
+	 *      be updated.
210
+	 *
211
+	 * @return array
212
+	 */
213
+	public function getACL() {
214
+
215
+		return [
216
+			[
217
+				'privilege' => '{DAV:}read',
218
+				'principal' => $this->principalUri,
219
+				'protected' => true,
220
+			],
221
+			[
222
+				'privilege' => '{DAV:}write',
223
+				'principal' => $this->principalUri,
224
+				'protected' => true,
225
+			],
226
+		];
227
+
228
+	}
229
+
230
+	/**
231
+	 * Updates the ACL
232
+	 *
233
+	 * This method will receive a list of new ACE's.
234
+	 *
235
+	 * @param array $acl
236
+	 * @return void
237
+	 */
238
+	public function setACL(array $acl) {
239
+
240
+		throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
241
+
242
+	}
243
+
244
+	/**
245
+	 * Returns the list of supported privileges for this node.
246
+	 *
247
+	 * The returned data structure is a list of nested privileges.
248
+	 * See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
249
+	 * standard structure.
250
+	 *
251
+	 * If null is returned from this method, the default privilege set is used,
252
+	 * which is fine for most common usecases.
253
+	 *
254
+	 * @return array|null
255
+	 */
256
+	public function getSupportedPrivilegeSet() {
257
+
258
+		return null;
259
+
260
+	}
261 261
 
262 262
 }
Please login to merge, or discard this patch.
Braces   +3 added lines, -2 removed lines patch added patch discarded remove patch
@@ -129,8 +129,9 @@
 block discarded – undo
129 129
     public function getChild($name) {
130 130
 
131 131
         foreach ($this->getChildren() as $child) {
132
-            if ($name == $child->getName())
133
-                return $child;
132
+            if ($name == $child->getName()) {
133
+                            return $child;
134
+            }
134 135
 
135 136
         }
136 137
         throw new DAV\Exception\NotFound('Addressbook with name \'' . $name . '\' could not be found');
Please login to merge, or discard this patch.
libraries/SabreDAV/CardDAV/Card.php 3 patches
Unused Use Statements   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -2,8 +2,8 @@
 block discarded – undo
2 2
 
3 3
 namespace Sabre\CardDAV;
4 4
 
5
-use Sabre\DAVACL;
6 5
 use Sabre\DAV;
6
+use Sabre\DAVACL;
7 7
 
8 8
 /**
9 9
  * The Card object represents a single Card from an addressbook
Please login to merge, or discard this patch.
Indentation   +245 added lines, -245 removed lines patch added patch discarded remove patch
@@ -14,250 +14,250 @@
 block discarded – undo
14 14
  */
15 15
 class Card extends DAV\File implements ICard, DAVACL\IACL {
16 16
 
17
-    /**
18
-     * CardDAV backend
19
-     *
20
-     * @var Backend\BackendInterface
21
-     */
22
-    protected $carddavBackend;
23
-
24
-    /**
25
-     * Array with information about this Card
26
-     *
27
-     * @var array
28
-     */
29
-    protected $cardData;
30
-
31
-    /**
32
-     * Array with information about the containing addressbook
33
-     *
34
-     * @var array
35
-     */
36
-    protected $addressBookInfo;
37
-
38
-    /**
39
-     * Constructor
40
-     *
41
-     * @param Backend\BackendInterface $carddavBackend
42
-     * @param array $addressBookInfo
43
-     * @param array $cardData
44
-     */
45
-    public function __construct(Backend\BackendInterface $carddavBackend, array $addressBookInfo, array $cardData) {
46
-
47
-        $this->carddavBackend = $carddavBackend;
48
-        $this->addressBookInfo = $addressBookInfo;
49
-        $this->cardData = $cardData;
50
-
51
-    }
52
-
53
-    /**
54
-     * Returns the uri for this object
55
-     *
56
-     * @return string
57
-     */
58
-    public function getName() {
59
-
60
-        return $this->cardData['uri'];
61
-
62
-    }
63
-
64
-    /**
65
-     * Returns the VCard-formatted object
66
-     *
67
-     * @return string
68
-     */
69
-    public function get() {
70
-
71
-        // Pre-populating 'carddata' is optional. If we don't yet have it
72
-        // already, we fetch it from the backend.
73
-        if (!isset($this->cardData['carddata'])) {
74
-            $this->cardData = $this->carddavBackend->getCard($this->addressBookInfo['id'], $this->cardData['uri']);
75
-        }
76
-        return $this->cardData['carddata'];
77
-
78
-    }
79
-
80
-    /**
81
-     * Updates the VCard-formatted object
82
-     *
83
-     * @param string $cardData
84
-     * @return string|null
85
-     */
86
-    public function put($cardData) {
87
-
88
-        if (is_resource($cardData))
89
-            $cardData = stream_get_contents($cardData);
90
-
91
-        // Converting to UTF-8, if needed
92
-        $cardData = DAV\StringUtil::ensureUTF8($cardData);
93
-
94
-        $etag = $this->carddavBackend->updateCard($this->addressBookInfo['id'], $this->cardData['uri'], $cardData);
95
-        $this->cardData['carddata'] = $cardData;
96
-        $this->cardData['etag'] = $etag;
97
-
98
-        return $etag;
99
-
100
-    }
101
-
102
-    /**
103
-     * Deletes the card
104
-     *
105
-     * @return void
106
-     */
107
-    public function delete() {
108
-
109
-        $this->carddavBackend->deleteCard($this->addressBookInfo['id'], $this->cardData['uri']);
110
-
111
-    }
112
-
113
-    /**
114
-     * Returns the mime content-type
115
-     *
116
-     * @return string
117
-     */
118
-    public function getContentType() {
119
-
120
-        return 'text/vcard; charset=utf-8';
121
-
122
-    }
123
-
124
-    /**
125
-     * Returns an ETag for this object
126
-     *
127
-     * @return string
128
-     */
129
-    public function getETag() {
130
-
131
-        if (isset($this->cardData['etag'])) {
132
-            return $this->cardData['etag'];
133
-        } else {
134
-            $data = $this->get();
135
-            if (is_string($data)) {
136
-                return '"' . md5($data) . '"';
137
-            } else {
138
-                // We refuse to calculate the md5 if it's a stream.
139
-                return null;
140
-            }
141
-        }
142
-
143
-    }
144
-
145
-    /**
146
-     * Returns the last modification date as a unix timestamp
147
-     *
148
-     * @return int
149
-     */
150
-    public function getLastModified() {
151
-
152
-        return isset($this->cardData['lastmodified']) ? $this->cardData['lastmodified'] : null;
153
-
154
-    }
155
-
156
-    /**
157
-     * Returns the size of this object in bytes
158
-     *
159
-     * @return int
160
-     */
161
-    public function getSize() {
162
-
163
-        if (array_key_exists('size', $this->cardData)) {
164
-            return $this->cardData['size'];
165
-        } else {
166
-            return strlen($this->get());
167
-        }
168
-
169
-    }
170
-
171
-    /**
172
-     * Returns the owner principal
173
-     *
174
-     * This must be a url to a principal, or null if there's no owner
175
-     *
176
-     * @return string|null
177
-     */
178
-    public function getOwner() {
179
-
180
-        return $this->addressBookInfo['principaluri'];
181
-
182
-    }
183
-
184
-    /**
185
-     * Returns a group principal
186
-     *
187
-     * This must be a url to a principal, or null if there's no owner
188
-     *
189
-     * @return string|null
190
-     */
191
-    public function getGroup() {
192
-
193
-        return null;
194
-
195
-    }
196
-
197
-    /**
198
-     * Returns a list of ACE's for this node.
199
-     *
200
-     * Each ACE has the following properties:
201
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
202
-     *     currently the only supported privileges
203
-     *   * 'principal', a url to the principal who owns the node
204
-     *   * 'protected' (optional), indicating that this ACE is not allowed to
205
-     *      be updated.
206
-     *
207
-     * @return array
208
-     */
209
-    public function getACL() {
210
-
211
-        // An alternative acl may be specified through the cardData array.
212
-        if (isset($this->cardData['acl'])) {
213
-            return $this->cardData['acl'];
214
-        }
215
-
216
-        return [
217
-            [
218
-                'privilege' => '{DAV:}read',
219
-                'principal' => $this->addressBookInfo['principaluri'],
220
-                'protected' => true,
221
-            ],
222
-            [
223
-                'privilege' => '{DAV:}write',
224
-                'principal' => $this->addressBookInfo['principaluri'],
225
-                'protected' => true,
226
-            ],
227
-        ];
228
-
229
-    }
230
-
231
-    /**
232
-     * Updates the ACL
233
-     *
234
-     * This method will receive a list of new ACE's.
235
-     *
236
-     * @param array $acl
237
-     * @return void
238
-     */
239
-    public function setACL(array $acl) {
240
-
241
-        throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
242
-
243
-    }
244
-
245
-    /**
246
-     * Returns the list of supported privileges for this node.
247
-     *
248
-     * The returned data structure is a list of nested privileges.
249
-     * See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
250
-     * standard structure.
251
-     *
252
-     * If null is returned from this method, the default privilege set is used,
253
-     * which is fine for most common usecases.
254
-     *
255
-     * @return array|null
256
-     */
257
-    public function getSupportedPrivilegeSet() {
258
-
259
-        return null;
260
-
261
-    }
17
+	/**
18
+	 * CardDAV backend
19
+	 *
20
+	 * @var Backend\BackendInterface
21
+	 */
22
+	protected $carddavBackend;
23
+
24
+	/**
25
+	 * Array with information about this Card
26
+	 *
27
+	 * @var array
28
+	 */
29
+	protected $cardData;
30
+
31
+	/**
32
+	 * Array with information about the containing addressbook
33
+	 *
34
+	 * @var array
35
+	 */
36
+	protected $addressBookInfo;
37
+
38
+	/**
39
+	 * Constructor
40
+	 *
41
+	 * @param Backend\BackendInterface $carddavBackend
42
+	 * @param array $addressBookInfo
43
+	 * @param array $cardData
44
+	 */
45
+	public function __construct(Backend\BackendInterface $carddavBackend, array $addressBookInfo, array $cardData) {
46
+
47
+		$this->carddavBackend = $carddavBackend;
48
+		$this->addressBookInfo = $addressBookInfo;
49
+		$this->cardData = $cardData;
50
+
51
+	}
52
+
53
+	/**
54
+	 * Returns the uri for this object
55
+	 *
56
+	 * @return string
57
+	 */
58
+	public function getName() {
59
+
60
+		return $this->cardData['uri'];
61
+
62
+	}
63
+
64
+	/**
65
+	 * Returns the VCard-formatted object
66
+	 *
67
+	 * @return string
68
+	 */
69
+	public function get() {
70
+
71
+		// Pre-populating 'carddata' is optional. If we don't yet have it
72
+		// already, we fetch it from the backend.
73
+		if (!isset($this->cardData['carddata'])) {
74
+			$this->cardData = $this->carddavBackend->getCard($this->addressBookInfo['id'], $this->cardData['uri']);
75
+		}
76
+		return $this->cardData['carddata'];
77
+
78
+	}
79
+
80
+	/**
81
+	 * Updates the VCard-formatted object
82
+	 *
83
+	 * @param string $cardData
84
+	 * @return string|null
85
+	 */
86
+	public function put($cardData) {
87
+
88
+		if (is_resource($cardData))
89
+			$cardData = stream_get_contents($cardData);
90
+
91
+		// Converting to UTF-8, if needed
92
+		$cardData = DAV\StringUtil::ensureUTF8($cardData);
93
+
94
+		$etag = $this->carddavBackend->updateCard($this->addressBookInfo['id'], $this->cardData['uri'], $cardData);
95
+		$this->cardData['carddata'] = $cardData;
96
+		$this->cardData['etag'] = $etag;
97
+
98
+		return $etag;
99
+
100
+	}
101
+
102
+	/**
103
+	 * Deletes the card
104
+	 *
105
+	 * @return void
106
+	 */
107
+	public function delete() {
108
+
109
+		$this->carddavBackend->deleteCard($this->addressBookInfo['id'], $this->cardData['uri']);
110
+
111
+	}
112
+
113
+	/**
114
+	 * Returns the mime content-type
115
+	 *
116
+	 * @return string
117
+	 */
118
+	public function getContentType() {
119
+
120
+		return 'text/vcard; charset=utf-8';
121
+
122
+	}
123
+
124
+	/**
125
+	 * Returns an ETag for this object
126
+	 *
127
+	 * @return string
128
+	 */
129
+	public function getETag() {
130
+
131
+		if (isset($this->cardData['etag'])) {
132
+			return $this->cardData['etag'];
133
+		} else {
134
+			$data = $this->get();
135
+			if (is_string($data)) {
136
+				return '"' . md5($data) . '"';
137
+			} else {
138
+				// We refuse to calculate the md5 if it's a stream.
139
+				return null;
140
+			}
141
+		}
142
+
143
+	}
144
+
145
+	/**
146
+	 * Returns the last modification date as a unix timestamp
147
+	 *
148
+	 * @return int
149
+	 */
150
+	public function getLastModified() {
151
+
152
+		return isset($this->cardData['lastmodified']) ? $this->cardData['lastmodified'] : null;
153
+
154
+	}
155
+
156
+	/**
157
+	 * Returns the size of this object in bytes
158
+	 *
159
+	 * @return int
160
+	 */
161
+	public function getSize() {
162
+
163
+		if (array_key_exists('size', $this->cardData)) {
164
+			return $this->cardData['size'];
165
+		} else {
166
+			return strlen($this->get());
167
+		}
168
+
169
+	}
170
+
171
+	/**
172
+	 * Returns the owner principal
173
+	 *
174
+	 * This must be a url to a principal, or null if there's no owner
175
+	 *
176
+	 * @return string|null
177
+	 */
178
+	public function getOwner() {
179
+
180
+		return $this->addressBookInfo['principaluri'];
181
+
182
+	}
183
+
184
+	/**
185
+	 * Returns a group principal
186
+	 *
187
+	 * This must be a url to a principal, or null if there's no owner
188
+	 *
189
+	 * @return string|null
190
+	 */
191
+	public function getGroup() {
192
+
193
+		return null;
194
+
195
+	}
196
+
197
+	/**
198
+	 * Returns a list of ACE's for this node.
199
+	 *
200
+	 * Each ACE has the following properties:
201
+	 *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
202
+	 *     currently the only supported privileges
203
+	 *   * 'principal', a url to the principal who owns the node
204
+	 *   * 'protected' (optional), indicating that this ACE is not allowed to
205
+	 *      be updated.
206
+	 *
207
+	 * @return array
208
+	 */
209
+	public function getACL() {
210
+
211
+		// An alternative acl may be specified through the cardData array.
212
+		if (isset($this->cardData['acl'])) {
213
+			return $this->cardData['acl'];
214
+		}
215
+
216
+		return [
217
+			[
218
+				'privilege' => '{DAV:}read',
219
+				'principal' => $this->addressBookInfo['principaluri'],
220
+				'protected' => true,
221
+			],
222
+			[
223
+				'privilege' => '{DAV:}write',
224
+				'principal' => $this->addressBookInfo['principaluri'],
225
+				'protected' => true,
226
+			],
227
+		];
228
+
229
+	}
230
+
231
+	/**
232
+	 * Updates the ACL
233
+	 *
234
+	 * This method will receive a list of new ACE's.
235
+	 *
236
+	 * @param array $acl
237
+	 * @return void
238
+	 */
239
+	public function setACL(array $acl) {
240
+
241
+		throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
242
+
243
+	}
244
+
245
+	/**
246
+	 * Returns the list of supported privileges for this node.
247
+	 *
248
+	 * The returned data structure is a list of nested privileges.
249
+	 * See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
250
+	 * standard structure.
251
+	 *
252
+	 * If null is returned from this method, the default privilege set is used,
253
+	 * which is fine for most common usecases.
254
+	 *
255
+	 * @return array|null
256
+	 */
257
+	public function getSupportedPrivilegeSet() {
258
+
259
+		return null;
260
+
261
+	}
262 262
 
263 263
 }
Please login to merge, or discard this patch.
Braces   +3 added lines, -2 removed lines patch added patch discarded remove patch
@@ -85,8 +85,9 @@
 block discarded – undo
85 85
      */
86 86
     public function put($cardData) {
87 87
 
88
-        if (is_resource($cardData))
89
-            $cardData = stream_get_contents($cardData);
88
+        if (is_resource($cardData)) {
89
+                    $cardData = stream_get_contents($cardData);
90
+        }
90 91
 
91 92
         // Converting to UTF-8, if needed
92 93
         $cardData = DAV\StringUtil::ensureUTF8($cardData);
Please login to merge, or discard this patch.
libraries/SabreDAV/CardDAV/Plugin.php 5 patches
Unused Use Statements   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -3,9 +3,9 @@
 block discarded – undo
3 3
 namespace Sabre\CardDAV;
4 4
 
5 5
 use Sabre\DAV;
6
+use Sabre\DAVACL;
6 7
 use Sabre\DAV\Exception\ReportNotSupported;
7 8
 use Sabre\DAV\Xml\Property\Href;
8
-use Sabre\DAVACL;
9 9
 use Sabre\HTTP;
10 10
 use Sabre\HTTP\RequestInterface;
11 11
 use Sabre\HTTP\ResponseInterface;
Please login to merge, or discard this patch.
Indentation   +815 added lines, -815 removed lines patch added patch discarded remove patch
@@ -22,686 +22,686 @@  discard block
 block discarded – undo
22 22
  */
23 23
 class Plugin extends DAV\ServerPlugin {
24 24
 
25
-    /**
26
-     * Url to the addressbooks
27
-     */
28
-    const ADDRESSBOOK_ROOT = 'addressbooks';
29
-
30
-    /**
31
-     * xml namespace for CardDAV elements
32
-     */
33
-    const NS_CARDDAV = 'urn:ietf:params:xml:ns:carddav';
34
-
35
-    /**
36
-     * Add urls to this property to have them automatically exposed as
37
-     * 'directories' to the user.
38
-     *
39
-     * @var array
40
-     */
41
-    public $directories = [];
42
-
43
-    /**
44
-     * Server class
45
-     *
46
-     * @var Sabre\DAV\Server
47
-     */
48
-    protected $server;
49
-
50
-    /**
51
-     * The default PDO storage uses a MySQL MEDIUMBLOB for iCalendar data,
52
-     * which can hold up to 2^24 = 16777216 bytes. This is plenty. We're
53
-     * capping it to 10M here.
54
-     */
55
-    protected $maxResourceSize = 10000000;
56
-
57
-    /**
58
-     * Initializes the plugin
59
-     *
60
-     * @param DAV\Server $server
61
-     * @return void
62
-     */
63
-    public function initialize(DAV\Server $server) {
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
-    }
94
-
95
-    /**
96
-     * Returns a list of supported features.
97
-     *
98
-     * This is used in the DAV: header in the OPTIONS and PROPFIND requests.
99
-     *
100
-     * @return array
101
-     */
102
-    public function getFeatures() {
103
-
104
-        return ['addressbook'];
105
-
106
-    }
107
-
108
-    /**
109
-     * Returns a list of reports this plugin supports.
110
-     *
111
-     * This will be used in the {DAV:}supported-report-set property.
112
-     * Note that you still need to subscribe to the 'report' event to actually
113
-     * implement them
114
-     *
115
-     * @param string $uri
116
-     * @return array
117
-     */
118
-    public function getSupportedReportSet($uri) {
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
-    }
130
-
131
-
132
-    /**
133
-     * Adds all CardDAV-specific properties
134
-     *
135
-     * @param DAV\PropFind $propFind
136
-     * @param DAV\INode $node
137
-     * @return void
138
-     */
139
-    public function propFindEarly(DAV\PropFind $propFind, DAV\INode $node) {
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 Href($this->getAddressBookHomeForPrincipal($path) . '/');
160
-            });
161
-
162
-            if ($this->directories) $propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function() {
163
-                return new Href($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
-    }
185
-
186
-    /**
187
-     * This functions handles REPORT requests specific to CardDAV
188
-     *
189
-     * @param string $reportName
190
-     * @param \DOMNode $dom
191
-     * @param mixed $path
192
-     * @return bool
193
-     */
194
-    public function report($reportName, $dom, $path) {
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
-    }
212
-
213
-    /**
214
-     * Returns the addressbook home for a given principal
215
-     *
216
-     * @param string $principal
217
-     * @return string
218
-     */
219
-    protected function getAddressbookHomeForPrincipal($principal) {
220
-
221
-        list(, $principalId) = \Sabre\HTTP\URLUtil::splitPath($principal);
222
-        return self::ADDRESSBOOK_ROOT . '/' . $principalId;
223
-
224
-    }
225
-
226
-
227
-    /**
228
-     * This function handles the addressbook-multiget REPORT.
229
-     *
230
-     * This report is used by the client to fetch the content of a series
231
-     * of urls. Effectively avoiding a lot of redundant requests.
232
-     *
233
-     * @param Xml\Request\AddressBookMultiGetReport $report
234
-     * @return void
235
-     */
236
-    public function addressbookMultiGetReport($report) {
237
-
238
-        $contentType = $report->contentType;
239
-        $version = $report->version;
240
-        if ($version) {
241
-            $contentType .= '; version=' . $version;
242
-        }
243
-
244
-        $vcardType = $this->negotiateVCard(
245
-            $contentType
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
-    }
275
-
276
-    /**
277
-     * This method is triggered before a file gets updated with new content.
278
-     *
279
-     * This plugin uses this method to ensure that Card nodes receive valid
280
-     * vcard data.
281
-     *
282
-     * @param string $path
283
-     * @param DAV\IFile $node
284
-     * @param resource $data
285
-     * @param bool $modified Should be set to true, if this event handler
286
-     *                       changed &$data.
287
-     * @return void
288
-     */
289
-    public function beforeWriteContent($path, DAV\IFile $node, &$data, &$modified) {
290
-
291
-        if (!$node instanceof ICard)
292
-            return;
293
-
294
-        $this->validateVCard($data, $modified);
295
-
296
-    }
297
-
298
-    /**
299
-     * This method is triggered before a new file is created.
300
-     *
301
-     * This plugin uses this method to ensure that Card nodes receive valid
302
-     * vcard data.
303
-     *
304
-     * @param string $path
305
-     * @param resource $data
306
-     * @param DAV\ICollection $parentNode
307
-     * @param bool $modified Should be set to true, if this event handler
308
-     *                       changed &$data.
309
-     * @return void
310
-     */
311
-    public function beforeCreateFile($path, &$data, DAV\ICollection $parentNode, &$modified) {
312
-
313
-        if (!$parentNode instanceof IAddressBook)
314
-            return;
315
-
316
-        $this->validateVCard($data, $modified);
317
-
318
-    }
319
-
320
-    /**
321
-     * Checks if the submitted iCalendar data is in fact, valid.
322
-     *
323
-     * An exception is thrown if it's not.
324
-     *
325
-     * @param resource|string $data
326
-     * @param bool $modified Should be set to true, if this event handler
327
-     *                       changed &$data.
328
-     * @return void
329
-     */
330
-    protected function validateVCard(&$data, &$modified) {
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 = md5($data);
338
-
339
-        // Converting the data to unicode, if needed.
340
-        $data = DAV\StringUtil::ensureUTF8($data);
341
-
342
-        if (md5($data) !== $before) $modified = true;
343
-
344
-        try {
345
-
346
-            // If the data starts with a [, we can reasonably assume we're dealing
347
-            // with a jCal object.
348
-            if (substr($data, 0, 1) === '[') {
349
-                $vobj = VObject\Reader::readJson($data);
350
-
351
-                // Converting $data back to iCalendar, as that's what we
352
-                // technically support everywhere.
353
-                $data = $vobj->serialize();
354
-                $modified = true;
355
-            } else {
356
-                $vobj = VObject\Reader::read($data);
357
-            }
358
-
359
-        } catch (VObject\ParseException $e) {
360
-
361
-            throw new DAV\Exception\UnsupportedMediaType('This resource only supports valid vCard or jCard data. Parse error: ' . $e->getMessage());
362
-
363
-        }
364
-
365
-        if ($vobj->name !== 'VCARD') {
366
-            throw new DAV\Exception\UnsupportedMediaType('This collection can only support vcard objects.');
367
-        }
368
-
369
-        if (!isset($vobj->UID)) {
370
-            // No UID in vcards is invalid, but we'll just add it in anyway.
371
-            $vobj->add('UID', DAV\UUIDUtil::getUUID());
372
-            $data = $vobj->serialize();
373
-            $modified = true;
374
-        }
375
-
376
-        // Destroy circular references to PHP will GC the object.
377
-        $vobj->destroy();
378
-    }
379
-
380
-
381
-    /**
382
-     * This function handles the addressbook-query REPORT
383
-     *
384
-     * This report is used by the client to filter an addressbook based on a
385
-     * complex query.
386
-     *
387
-     * @param Xml\Request\AddressBookQueryReport $report
388
-     * @return void
389
-     */
390
-    protected function addressbookQueryReport($report) {
391
-
392
-        $depth = $this->server->getHTTPDepth(0);
393
-
394
-        if ($depth == 0) {
395
-            $candidateNodes = [
396
-                $this->server->tree->getNodeForPath($this->server->getRequestUri())
397
-            ];
398
-            if (!$candidateNodes[0] instanceof ICard) {
399
-                throw new ReportNotSupported('The addressbook-query report is not supported on this url with Depth: 0');
400
-            }
401
-        } else {
402
-            $candidateNodes = $this->server->tree->getChildren($this->server->getRequestUri());
403
-        }
404
-
405
-        $contentType = $report->contentType;
406
-        if ($report->version) {
407
-            $contentType .= '; version=' . $report->version;
408
-        }
409
-
410
-        $vcardType = $this->negotiateVCard(
411
-            $contentType
412
-        );
25
+	/**
26
+	 * Url to the addressbooks
27
+	 */
28
+	const ADDRESSBOOK_ROOT = 'addressbooks';
29
+
30
+	/**
31
+	 * xml namespace for CardDAV elements
32
+	 */
33
+	const NS_CARDDAV = 'urn:ietf:params:xml:ns:carddav';
34
+
35
+	/**
36
+	 * Add urls to this property to have them automatically exposed as
37
+	 * 'directories' to the user.
38
+	 *
39
+	 * @var array
40
+	 */
41
+	public $directories = [];
42
+
43
+	/**
44
+	 * Server class
45
+	 *
46
+	 * @var Sabre\DAV\Server
47
+	 */
48
+	protected $server;
49
+
50
+	/**
51
+	 * The default PDO storage uses a MySQL MEDIUMBLOB for iCalendar data,
52
+	 * which can hold up to 2^24 = 16777216 bytes. This is plenty. We're
53
+	 * capping it to 10M here.
54
+	 */
55
+	protected $maxResourceSize = 10000000;
56
+
57
+	/**
58
+	 * Initializes the plugin
59
+	 *
60
+	 * @param DAV\Server $server
61
+	 * @return void
62
+	 */
63
+	public function initialize(DAV\Server $server) {
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
+	}
94
+
95
+	/**
96
+	 * Returns a list of supported features.
97
+	 *
98
+	 * This is used in the DAV: header in the OPTIONS and PROPFIND requests.
99
+	 *
100
+	 * @return array
101
+	 */
102
+	public function getFeatures() {
103
+
104
+		return ['addressbook'];
105
+
106
+	}
107
+
108
+	/**
109
+	 * Returns a list of reports this plugin supports.
110
+	 *
111
+	 * This will be used in the {DAV:}supported-report-set property.
112
+	 * Note that you still need to subscribe to the 'report' event to actually
113
+	 * implement them
114
+	 *
115
+	 * @param string $uri
116
+	 * @return array
117
+	 */
118
+	public function getSupportedReportSet($uri) {
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
+	}
130
+
131
+
132
+	/**
133
+	 * Adds all CardDAV-specific properties
134
+	 *
135
+	 * @param DAV\PropFind $propFind
136
+	 * @param DAV\INode $node
137
+	 * @return void
138
+	 */
139
+	public function propFindEarly(DAV\PropFind $propFind, DAV\INode $node) {
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 Href($this->getAddressBookHomeForPrincipal($path) . '/');
160
+			});
161
+
162
+			if ($this->directories) $propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function() {
163
+				return new Href($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
+	}
185
+
186
+	/**
187
+	 * This functions handles REPORT requests specific to CardDAV
188
+	 *
189
+	 * @param string $reportName
190
+	 * @param \DOMNode $dom
191
+	 * @param mixed $path
192
+	 * @return bool
193
+	 */
194
+	public function report($reportName, $dom, $path) {
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
+	}
212
+
213
+	/**
214
+	 * Returns the addressbook home for a given principal
215
+	 *
216
+	 * @param string $principal
217
+	 * @return string
218
+	 */
219
+	protected function getAddressbookHomeForPrincipal($principal) {
220
+
221
+		list(, $principalId) = \Sabre\HTTP\URLUtil::splitPath($principal);
222
+		return self::ADDRESSBOOK_ROOT . '/' . $principalId;
223
+
224
+	}
225
+
226
+
227
+	/**
228
+	 * This function handles the addressbook-multiget REPORT.
229
+	 *
230
+	 * This report is used by the client to fetch the content of a series
231
+	 * of urls. Effectively avoiding a lot of redundant requests.
232
+	 *
233
+	 * @param Xml\Request\AddressBookMultiGetReport $report
234
+	 * @return void
235
+	 */
236
+	public function addressbookMultiGetReport($report) {
237
+
238
+		$contentType = $report->contentType;
239
+		$version = $report->version;
240
+		if ($version) {
241
+			$contentType .= '; version=' . $version;
242
+		}
243
+
244
+		$vcardType = $this->negotiateVCard(
245
+			$contentType
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
+	}
275
+
276
+	/**
277
+	 * This method is triggered before a file gets updated with new content.
278
+	 *
279
+	 * This plugin uses this method to ensure that Card nodes receive valid
280
+	 * vcard data.
281
+	 *
282
+	 * @param string $path
283
+	 * @param DAV\IFile $node
284
+	 * @param resource $data
285
+	 * @param bool $modified Should be set to true, if this event handler
286
+	 *                       changed &$data.
287
+	 * @return void
288
+	 */
289
+	public function beforeWriteContent($path, DAV\IFile $node, &$data, &$modified) {
290
+
291
+		if (!$node instanceof ICard)
292
+			return;
293
+
294
+		$this->validateVCard($data, $modified);
295
+
296
+	}
297
+
298
+	/**
299
+	 * This method is triggered before a new file is created.
300
+	 *
301
+	 * This plugin uses this method to ensure that Card nodes receive valid
302
+	 * vcard data.
303
+	 *
304
+	 * @param string $path
305
+	 * @param resource $data
306
+	 * @param DAV\ICollection $parentNode
307
+	 * @param bool $modified Should be set to true, if this event handler
308
+	 *                       changed &$data.
309
+	 * @return void
310
+	 */
311
+	public function beforeCreateFile($path, &$data, DAV\ICollection $parentNode, &$modified) {
312
+
313
+		if (!$parentNode instanceof IAddressBook)
314
+			return;
315
+
316
+		$this->validateVCard($data, $modified);
317
+
318
+	}
319
+
320
+	/**
321
+	 * Checks if the submitted iCalendar data is in fact, valid.
322
+	 *
323
+	 * An exception is thrown if it's not.
324
+	 *
325
+	 * @param resource|string $data
326
+	 * @param bool $modified Should be set to true, if this event handler
327
+	 *                       changed &$data.
328
+	 * @return void
329
+	 */
330
+	protected function validateVCard(&$data, &$modified) {
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 = md5($data);
338
+
339
+		// Converting the data to unicode, if needed.
340
+		$data = DAV\StringUtil::ensureUTF8($data);
341
+
342
+		if (md5($data) !== $before) $modified = true;
343
+
344
+		try {
345
+
346
+			// If the data starts with a [, we can reasonably assume we're dealing
347
+			// with a jCal object.
348
+			if (substr($data, 0, 1) === '[') {
349
+				$vobj = VObject\Reader::readJson($data);
350
+
351
+				// Converting $data back to iCalendar, as that's what we
352
+				// technically support everywhere.
353
+				$data = $vobj->serialize();
354
+				$modified = true;
355
+			} else {
356
+				$vobj = VObject\Reader::read($data);
357
+			}
358
+
359
+		} catch (VObject\ParseException $e) {
360
+
361
+			throw new DAV\Exception\UnsupportedMediaType('This resource only supports valid vCard or jCard data. Parse error: ' . $e->getMessage());
362
+
363
+		}
364
+
365
+		if ($vobj->name !== 'VCARD') {
366
+			throw new DAV\Exception\UnsupportedMediaType('This collection can only support vcard objects.');
367
+		}
368
+
369
+		if (!isset($vobj->UID)) {
370
+			// No UID in vcards is invalid, but we'll just add it in anyway.
371
+			$vobj->add('UID', DAV\UUIDUtil::getUUID());
372
+			$data = $vobj->serialize();
373
+			$modified = true;
374
+		}
375
+
376
+		// Destroy circular references to PHP will GC the object.
377
+		$vobj->destroy();
378
+	}
379
+
380
+
381
+	/**
382
+	 * This function handles the addressbook-query REPORT
383
+	 *
384
+	 * This report is used by the client to filter an addressbook based on a
385
+	 * complex query.
386
+	 *
387
+	 * @param Xml\Request\AddressBookQueryReport $report
388
+	 * @return void
389
+	 */
390
+	protected function addressbookQueryReport($report) {
391
+
392
+		$depth = $this->server->getHTTPDepth(0);
393
+
394
+		if ($depth == 0) {
395
+			$candidateNodes = [
396
+				$this->server->tree->getNodeForPath($this->server->getRequestUri())
397
+			];
398
+			if (!$candidateNodes[0] instanceof ICard) {
399
+				throw new ReportNotSupported('The addressbook-query report is not supported on this url with Depth: 0');
400
+			}
401
+		} else {
402
+			$candidateNodes = $this->server->tree->getChildren($this->server->getRequestUri());
403
+		}
404
+
405
+		$contentType = $report->contentType;
406
+		if ($report->version) {
407
+			$contentType .= '; version=' . $report->version;
408
+		}
409
+
410
+		$vcardType = $this->negotiateVCard(
411
+			$contentType
412
+		);
413 413
 
414
-        $validNodes = [];
415
-        foreach ($candidateNodes as $node) {
416
-
417
-            if (!$node instanceof ICard)
418
-                continue;
419
-
420
-            $blob = $node->get();
421
-            if (is_resource($blob)) {
422
-                $blob = stream_get_contents($blob);
423
-            }
424
-
425
-            if (!$this->validateFilters($blob, $report->filters, $report->test)) {
426
-                continue;
427
-            }
428
-
429
-            $validNodes[] = $node;
414
+		$validNodes = [];
415
+		foreach ($candidateNodes as $node) {
416
+
417
+			if (!$node instanceof ICard)
418
+				continue;
419
+
420
+			$blob = $node->get();
421
+			if (is_resource($blob)) {
422
+				$blob = stream_get_contents($blob);
423
+			}
424
+
425
+			if (!$this->validateFilters($blob, $report->filters, $report->test)) {
426
+				continue;
427
+			}
428
+
429
+			$validNodes[] = $node;
430 430
 
431
-            if ($report->limit && $report->limit <= count($validNodes)) {
432
-                // We hit the maximum number of items, we can stop now.
433
-                break;
434
-            }
431
+			if ($report->limit && $report->limit <= count($validNodes)) {
432
+				// We hit the maximum number of items, we can stop now.
433
+				break;
434
+			}
435 435
 
436
-        }
436
+		}
437 437
 
438
-        $result = [];
439
-        foreach ($validNodes as $validNode) {
438
+		$result = [];
439
+		foreach ($validNodes as $validNode) {
440 440
 
441
-            if ($depth == 0) {
442
-                $href = $this->server->getRequestUri();
443
-            } else {
444
-                $href = $this->server->getRequestUri() . '/' . $validNode->getName();
445
-            }
441
+			if ($depth == 0) {
442
+				$href = $this->server->getRequestUri();
443
+			} else {
444
+				$href = $this->server->getRequestUri() . '/' . $validNode->getName();
445
+			}
446 446
 
447
-            list($props) = $this->server->getPropertiesForPath($href, $report->properties, 0);
447
+			list($props) = $this->server->getPropertiesForPath($href, $report->properties, 0);
448 448
 
449
-            if (isset($props[200]['{' . self::NS_CARDDAV . '}address-data'])) {
449
+			if (isset($props[200]['{' . self::NS_CARDDAV . '}address-data'])) {
450 450
 
451
-                $props[200]['{' . self::NS_CARDDAV . '}address-data'] = $this->convertVCard(
452
-                    $props[200]['{' . self::NS_CARDDAV . '}address-data'],
453
-                    $vcardType
454
-                );
451
+				$props[200]['{' . self::NS_CARDDAV . '}address-data'] = $this->convertVCard(
452
+					$props[200]['{' . self::NS_CARDDAV . '}address-data'],
453
+					$vcardType
454
+				);
455 455
 
456
-            }
457
-            $result[] = $props;
456
+			}
457
+			$result[] = $props;
458 458
 
459
-        }
459
+		}
460 460
 
461
-        $prefer = $this->server->getHTTPPrefer();
461
+		$prefer = $this->server->getHTTPPrefer();
462 462
 
463
-        $this->server->httpResponse->setStatus(207);
464
-        $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
465
-        $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
466
-        $this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return'] === 'minimal'));
467
-
468
-    }
469
-
470
-    /**
471
-     * Validates if a vcard makes it throught a list of filters.
472
-     *
473
-     * @param string $vcardData
474
-     * @param array $filters
475
-     * @param string $test anyof or allof (which means OR or AND)
476
-     * @return bool
477
-     */
478
-    public function validateFilters($vcardData, array $filters, $test) {
479
-
480
-
481
-        if (!$filters) return true;
482
-        $vcard = VObject\Reader::read($vcardData);
483
-
484
-        foreach ($filters as $filter) {
485
-
486
-            $isDefined = isset($vcard->{$filter['name']});
487
-            if ($filter['is-not-defined']) {
488
-                if ($isDefined) {
489
-                    $success = false;
490
-                } else {
491
-                    $success = true;
492
-                }
493
-            } elseif ((!$filter['param-filters'] && !$filter['text-matches']) || !$isDefined) {
494
-
495
-                // We only need to check for existence
496
-                $success = $isDefined;
497
-
498
-            } else {
463
+		$this->server->httpResponse->setStatus(207);
464
+		$this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
465
+		$this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
466
+		$this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return'] === 'minimal'));
467
+
468
+	}
469
+
470
+	/**
471
+	 * Validates if a vcard makes it throught a list of filters.
472
+	 *
473
+	 * @param string $vcardData
474
+	 * @param array $filters
475
+	 * @param string $test anyof or allof (which means OR or AND)
476
+	 * @return bool
477
+	 */
478
+	public function validateFilters($vcardData, array $filters, $test) {
479
+
480
+
481
+		if (!$filters) return true;
482
+		$vcard = VObject\Reader::read($vcardData);
483
+
484
+		foreach ($filters as $filter) {
485
+
486
+			$isDefined = isset($vcard->{$filter['name']});
487
+			if ($filter['is-not-defined']) {
488
+				if ($isDefined) {
489
+					$success = false;
490
+				} else {
491
+					$success = true;
492
+				}
493
+			} elseif ((!$filter['param-filters'] && !$filter['text-matches']) || !$isDefined) {
494
+
495
+				// We only need to check for existence
496
+				$success = $isDefined;
497
+
498
+			} else {
499 499
 
500
-                $vProperties = $vcard->select($filter['name']);
500
+				$vProperties = $vcard->select($filter['name']);
501 501
 
502
-                $results = [];
503
-                if ($filter['param-filters']) {
504
-                    $results[] = $this->validateParamFilters($vProperties, $filter['param-filters'], $filter['test']);
505
-                }
506
-                if ($filter['text-matches']) {
507
-                    $texts = [];
508
-                    foreach ($vProperties as $vProperty)
509
-                        $texts[] = $vProperty->getValue();
502
+				$results = [];
503
+				if ($filter['param-filters']) {
504
+					$results[] = $this->validateParamFilters($vProperties, $filter['param-filters'], $filter['test']);
505
+				}
506
+				if ($filter['text-matches']) {
507
+					$texts = [];
508
+					foreach ($vProperties as $vProperty)
509
+						$texts[] = $vProperty->getValue();
510 510
 
511
-                    $results[] = $this->validateTextMatches($texts, $filter['text-matches'], $filter['test']);
512
-                }
511
+					$results[] = $this->validateTextMatches($texts, $filter['text-matches'], $filter['test']);
512
+				}
513 513
 
514
-                if (count($results) === 1) {
515
-                    $success = $results[0];
516
-                } else {
517
-                    if ($filter['test'] === 'anyof') {
518
-                        $success = $results[0] || $results[1];
519
-                    } else {
520
-                        $success = $results[0] && $results[1];
521
-                    }
522
-                }
514
+				if (count($results) === 1) {
515
+					$success = $results[0];
516
+				} else {
517
+					if ($filter['test'] === 'anyof') {
518
+						$success = $results[0] || $results[1];
519
+					} else {
520
+						$success = $results[0] && $results[1];
521
+					}
522
+				}
523 523
 
524
-            } // else
525
-
526
-            // There are two conditions where we can already determine whether
527
-            // or not this filter succeeds.
528
-            if ($test === 'anyof' && $success) {
529
-
530
-                // Destroy circular references to PHP will GC the object.
531
-                $vcard->destroy();
532
-
533
-                return true;
534
-            }
535
-            if ($test === 'allof' && !$success) {
536
-
537
-                // Destroy circular references to PHP will GC the object.
538
-                $vcard->destroy();
539
-
540
-                return false;
541
-            }
542
-
543
-        } // foreach
544
-
545
-
546
-        // Destroy circular references to PHP will GC the object.
547
-        $vcard->destroy();
548
-
549
-        // If we got all the way here, it means we haven't been able to
550
-        // determine early if the test failed or not.
551
-        //
552
-        // This implies for 'anyof' that the test failed, and for 'allof' that
553
-        // we succeeded. Sounds weird, but makes sense.
554
-        return $test === 'allof';
555
-
556
-    }
557
-
558
-    /**
559
-     * Validates if a param-filter can be applied to a specific property.
560
-     * @param array $vProperties
561
-     * @param array $filters
562
-     * @param string $test
563
-     * @return bool
564
-     */
565
-    protected function validateParamFilters(array $vProperties, array $filters, $test) {
566
-
567
-        foreach ($filters as $filter) {
568
-
569
-            $isDefined = false;
570
-            foreach ($vProperties as $vProperty) {
571
-                $isDefined = isset($vProperty[$filter['name']]);
572
-                if ($isDefined) break;
573
-            }
574
-
575
-            if ($filter['is-not-defined']) {
576
-                if ($isDefined) {
577
-                    $success = false;
578
-                } else {
579
-                    $success = true;
580
-                }
581
-
582
-            // If there's no text-match, we can just check for existence
583
-            } elseif (!$filter['text-match'] || !$isDefined) {
584
-
585
-                $success = $isDefined;
586
-
587
-            } else {
588
-
589
-                $success = false;
590
-                foreach ($vProperties as $vProperty) {
591
-                    // If we got all the way here, we'll need to validate the
592
-                    // text-match filter.
593
-                    $success = DAV\StringUtil::textMatch($vProperty[$filter['name']]->getValue(), $filter['text-match']['value'], $filter['text-match']['collation'], $filter['text-match']['match-type']);
594
-                    if ($success) break;
595
-                }
596
-                if ($filter['text-match']['negate-condition']) {
597
-                    $success = !$success;
598
-                }
599
-
600
-            } // else
601
-
602
-            // There are two conditions where we can already determine whether
603
-            // or not this filter succeeds.
604
-            if ($test === 'anyof' && $success) {
605
-                return true;
606
-            }
607
-            if ($test === 'allof' && !$success) {
608
-                return false;
609
-            }
610
-
611
-        }
612
-
613
-        // If we got all the way here, it means we haven't been able to
614
-        // determine early if the test failed or not.
615
-        //
616
-        // This implies for 'anyof' that the test failed, and for 'allof' that
617
-        // we succeeded. Sounds weird, but makes sense.
618
-        return $test === 'allof';
619
-
620
-    }
621
-
622
-    /**
623
-     * Validates if a text-filter can be applied to a specific property.
624
-     *
625
-     * @param array $texts
626
-     * @param array $filters
627
-     * @param string $test
628
-     * @return bool
629
-     */
630
-    protected function validateTextMatches(array $texts, array $filters, $test) {
631
-
632
-        foreach ($filters as $filter) {
633
-
634
-            $success = false;
635
-            foreach ($texts as $haystack) {
636
-                $success = DAV\StringUtil::textMatch($haystack, $filter['value'], $filter['collation'], $filter['match-type']);
637
-
638
-                // Breaking on the first match
639
-                if ($success) break;
640
-            }
641
-            if ($filter['negate-condition']) {
642
-                $success = !$success;
643
-            }
644
-
645
-            if ($success && $test === 'anyof')
646
-                return true;
647
-
648
-            if (!$success && $test == 'allof')
649
-                return false;
650
-
651
-
652
-        }
653
-
654
-        // If we got all the way here, it means we haven't been able to
655
-        // determine early if the test failed or not.
656
-        //
657
-        // This implies for 'anyof' that the test failed, and for 'allof' that
658
-        // we succeeded. Sounds weird, but makes sense.
659
-        return $test === 'allof';
660
-
661
-    }
662
-
663
-    /**
664
-     * This event is triggered when fetching properties.
665
-     *
666
-     * This event is scheduled late in the process, after most work for
667
-     * propfind has been done.
668
-     *
669
-     * @param DAV\PropFind $propFind
670
-     * @param DAV\INode $node
671
-     * @return void
672
-     */
673
-    public function propFindLate(DAV\PropFind $propFind, DAV\INode $node) {
674
-
675
-        // If the request was made using the SOGO connector, we must rewrite
676
-        // the content-type property. By default SabreDAV will send back
677
-        // text/x-vcard; charset=utf-8, but for SOGO we must strip that last
678
-        // part.
679
-        if (strpos($this->server->httpRequest->getHeader('User-Agent'), 'Thunderbird') === false) {
680
-            return;
681
-        }
682
-        $contentType = $propFind->get('{DAV:}getcontenttype');
683
-        list($part) = explode(';', $contentType);
684
-        if ($part === 'text/x-vcard' || $part === 'text/vcard') {
685
-            $propFind->set('{DAV:}getcontenttype', 'text/x-vcard');
686
-        }
687
-
688
-    }
689
-
690
-    /**
691
-     * This method is used to generate HTML output for the
692
-     * Sabre\DAV\Browser\Plugin. This allows us to generate an interface users
693
-     * can use to create new addressbooks.
694
-     *
695
-     * @param DAV\INode $node
696
-     * @param string $output
697
-     * @return bool
698
-     */
699
-    public function htmlActionsPanel(DAV\INode $node, &$output) {
700
-
701
-        if (!$node instanceof AddressBookHome)
702
-            return;
703
-
704
-        $output .= '<tr><td colspan="2"><form method="post" action="">
524
+			} // else
525
+
526
+			// There are two conditions where we can already determine whether
527
+			// or not this filter succeeds.
528
+			if ($test === 'anyof' && $success) {
529
+
530
+				// Destroy circular references to PHP will GC the object.
531
+				$vcard->destroy();
532
+
533
+				return true;
534
+			}
535
+			if ($test === 'allof' && !$success) {
536
+
537
+				// Destroy circular references to PHP will GC the object.
538
+				$vcard->destroy();
539
+
540
+				return false;
541
+			}
542
+
543
+		} // foreach
544
+
545
+
546
+		// Destroy circular references to PHP will GC the object.
547
+		$vcard->destroy();
548
+
549
+		// If we got all the way here, it means we haven't been able to
550
+		// determine early if the test failed or not.
551
+		//
552
+		// This implies for 'anyof' that the test failed, and for 'allof' that
553
+		// we succeeded. Sounds weird, but makes sense.
554
+		return $test === 'allof';
555
+
556
+	}
557
+
558
+	/**
559
+	 * Validates if a param-filter can be applied to a specific property.
560
+	 * @param array $vProperties
561
+	 * @param array $filters
562
+	 * @param string $test
563
+	 * @return bool
564
+	 */
565
+	protected function validateParamFilters(array $vProperties, array $filters, $test) {
566
+
567
+		foreach ($filters as $filter) {
568
+
569
+			$isDefined = false;
570
+			foreach ($vProperties as $vProperty) {
571
+				$isDefined = isset($vProperty[$filter['name']]);
572
+				if ($isDefined) break;
573
+			}
574
+
575
+			if ($filter['is-not-defined']) {
576
+				if ($isDefined) {
577
+					$success = false;
578
+				} else {
579
+					$success = true;
580
+				}
581
+
582
+			// If there's no text-match, we can just check for existence
583
+			} elseif (!$filter['text-match'] || !$isDefined) {
584
+
585
+				$success = $isDefined;
586
+
587
+			} else {
588
+
589
+				$success = false;
590
+				foreach ($vProperties as $vProperty) {
591
+					// If we got all the way here, we'll need to validate the
592
+					// text-match filter.
593
+					$success = DAV\StringUtil::textMatch($vProperty[$filter['name']]->getValue(), $filter['text-match']['value'], $filter['text-match']['collation'], $filter['text-match']['match-type']);
594
+					if ($success) break;
595
+				}
596
+				if ($filter['text-match']['negate-condition']) {
597
+					$success = !$success;
598
+				}
599
+
600
+			} // else
601
+
602
+			// There are two conditions where we can already determine whether
603
+			// or not this filter succeeds.
604
+			if ($test === 'anyof' && $success) {
605
+				return true;
606
+			}
607
+			if ($test === 'allof' && !$success) {
608
+				return false;
609
+			}
610
+
611
+		}
612
+
613
+		// If we got all the way here, it means we haven't been able to
614
+		// determine early if the test failed or not.
615
+		//
616
+		// This implies for 'anyof' that the test failed, and for 'allof' that
617
+		// we succeeded. Sounds weird, but makes sense.
618
+		return $test === 'allof';
619
+
620
+	}
621
+
622
+	/**
623
+	 * Validates if a text-filter can be applied to a specific property.
624
+	 *
625
+	 * @param array $texts
626
+	 * @param array $filters
627
+	 * @param string $test
628
+	 * @return bool
629
+	 */
630
+	protected function validateTextMatches(array $texts, array $filters, $test) {
631
+
632
+		foreach ($filters as $filter) {
633
+
634
+			$success = false;
635
+			foreach ($texts as $haystack) {
636
+				$success = DAV\StringUtil::textMatch($haystack, $filter['value'], $filter['collation'], $filter['match-type']);
637
+
638
+				// Breaking on the first match
639
+				if ($success) break;
640
+			}
641
+			if ($filter['negate-condition']) {
642
+				$success = !$success;
643
+			}
644
+
645
+			if ($success && $test === 'anyof')
646
+				return true;
647
+
648
+			if (!$success && $test == 'allof')
649
+				return false;
650
+
651
+
652
+		}
653
+
654
+		// If we got all the way here, it means we haven't been able to
655
+		// determine early if the test failed or not.
656
+		//
657
+		// This implies for 'anyof' that the test failed, and for 'allof' that
658
+		// we succeeded. Sounds weird, but makes sense.
659
+		return $test === 'allof';
660
+
661
+	}
662
+
663
+	/**
664
+	 * This event is triggered when fetching properties.
665
+	 *
666
+	 * This event is scheduled late in the process, after most work for
667
+	 * propfind has been done.
668
+	 *
669
+	 * @param DAV\PropFind $propFind
670
+	 * @param DAV\INode $node
671
+	 * @return void
672
+	 */
673
+	public function propFindLate(DAV\PropFind $propFind, DAV\INode $node) {
674
+
675
+		// If the request was made using the SOGO connector, we must rewrite
676
+		// the content-type property. By default SabreDAV will send back
677
+		// text/x-vcard; charset=utf-8, but for SOGO we must strip that last
678
+		// part.
679
+		if (strpos($this->server->httpRequest->getHeader('User-Agent'), 'Thunderbird') === false) {
680
+			return;
681
+		}
682
+		$contentType = $propFind->get('{DAV:}getcontenttype');
683
+		list($part) = explode(';', $contentType);
684
+		if ($part === 'text/x-vcard' || $part === 'text/vcard') {
685
+			$propFind->set('{DAV:}getcontenttype', 'text/x-vcard');
686
+		}
687
+
688
+	}
689
+
690
+	/**
691
+	 * This method is used to generate HTML output for the
692
+	 * Sabre\DAV\Browser\Plugin. This allows us to generate an interface users
693
+	 * can use to create new addressbooks.
694
+	 *
695
+	 * @param DAV\INode $node
696
+	 * @param string $output
697
+	 * @return bool
698
+	 */
699
+	public function htmlActionsPanel(DAV\INode $node, &$output) {
700
+
701
+		if (!$node instanceof AddressBookHome)
702
+			return;
703
+
704
+		$output .= '<tr><td colspan="2"><form method="post" action="">
705 705
             <h3>Create new address book</h3>
706 706
             <input type="hidden" name="sabreAction" value="mkcol" />
707 707
             <input type="hidden" name="resourceType" value="{DAV:}collection,{' . self::NS_CARDDAV . '}addressbook" />
@@ -711,157 +711,157 @@  discard block
 block discarded – undo
711 711
             </form>
712 712
             </td></tr>';
713 713
 
714
-        return false;
715
-
716
-    }
717
-
718
-    /**
719
-     * This event is triggered after GET requests.
720
-     *
721
-     * This is used to transform data into jCal, if this was requested.
722
-     *
723
-     * @param RequestInterface $request
724
-     * @param ResponseInterface $response
725
-     * @return void
726
-     */
727
-    public function httpAfterGet(RequestInterface $request, ResponseInterface $response) {
728
-
729
-        if (strpos($response->getHeader('Content-Type'), 'text/vcard') === false) {
730
-            return;
731
-        }
732
-
733
-        $target = $this->negotiateVCard($request->getHeader('Accept'), $mimeType);
734
-
735
-        $newBody = $this->convertVCard(
736
-            $response->getBody(),
737
-            $target
738
-        );
739
-
740
-        $response->setBody($newBody);
741
-        $response->setHeader('Content-Type', $mimeType . '; charset=utf-8');
742
-        $response->setHeader('Content-Length', strlen($newBody));
743
-
744
-    }
745
-
746
-    /**
747
-     * This helper function performs the content-type negotiation for vcards.
748
-     *
749
-     * It will return one of the following strings:
750
-     * 1. vcard3
751
-     * 2. vcard4
752
-     * 3. jcard
753
-     *
754
-     * It defaults to vcard3.
755
-     *
756
-     * @param string $input
757
-     * @param string $mimeType
758
-     * @return string
759
-     */
760
-    protected function negotiateVCard($input, &$mimeType = null) {
761
-
762
-        $result = HTTP\Util::negotiate(
763
-            $input,
764
-            [
765
-                // Most often used mime-type. Version 3
766
-                'text/x-vcard',
767
-                // The correct standard mime-type. Defaults to version 3 as
768
-                // well.
769
-                'text/vcard',
770
-                // vCard 4
771
-                'text/vcard; version=4.0',
772
-                // vCard 3
773
-                'text/vcard; version=3.0',
774
-                // jCard
775
-                'application/vcard+json',
776
-            ]
777
-        );
778
-
779
-        $mimeType = $result;
780
-        switch ($result) {
781
-
782
-            default :
783
-            case 'text/x-vcard' :
784
-            case 'text/vcard' :
785
-            case 'text/vcard; version=3.0' :
786
-                $mimeType = 'text/vcard';
787
-                return 'vcard3';
788
-            case 'text/vcard; version=4.0' :
789
-                return 'vcard4';
790
-            case 'application/vcard+json' :
791
-                return 'jcard';
792
-
793
-        // @codeCoverageIgnoreStart
794
-        }
795
-        // @codeCoverageIgnoreEnd
796
-
797
-    }
798
-
799
-    /**
800
-     * Converts a vcard blob to a different version, or jcard.
801
-     *
802
-     * @param string $data
803
-     * @param string $target
804
-     * @return string
805
-     */
806
-    protected function convertVCard($data, $target) {
807
-
808
-        $data = VObject\Reader::read($data);
809
-        switch ($target) {
810
-            default :
811
-            case 'vcard3' :
812
-                $data = $data->convert(VObject\Document::VCARD30);
813
-                $newResult = $data->serialize();
814
-                break;
815
-            case 'vcard4' :
816
-                $data = $data->convert(VObject\Document::VCARD40);
817
-                $newResult = $data->serialize();
818
-                break;
819
-            case 'jcard' :
820
-                $data = $data->convert(VObject\Document::VCARD40);
821
-                $newResult = json_encode($data->jsonSerialize());
822
-                break;
823
-
824
-        }
825
-        // Destroy circular references to PHP will GC the object.
826
-        $data->destroy();
827
-
828
-        return $newResult;
829
-
830
-    }
831
-
832
-    /**
833
-     * Returns a plugin name.
834
-     *
835
-     * Using this name other plugins will be able to access other plugins
836
-     * using DAV\Server::getPlugin
837
-     *
838
-     * @return string
839
-     */
840
-    public function getPluginName() {
841
-
842
-        return 'carddav';
843
-
844
-    }
845
-
846
-    /**
847
-     * Returns a bunch of meta-data about the plugin.
848
-     *
849
-     * Providing this information is optional, and is mainly displayed by the
850
-     * Browser plugin.
851
-     *
852
-     * The description key in the returned array may contain html and will not
853
-     * be sanitized.
854
-     *
855
-     * @return array
856
-     */
857
-    public function getPluginInfo() {
858
-
859
-        return [
860
-            'name'        => $this->getPluginName(),
861
-            'description' => 'Adds support for CardDAV (rfc6352)',
862
-            'link'        => 'http://sabre.io/dav/carddav/',
863
-        ];
864
-
865
-    }
714
+		return false;
715
+
716
+	}
717
+
718
+	/**
719
+	 * This event is triggered after GET requests.
720
+	 *
721
+	 * This is used to transform data into jCal, if this was requested.
722
+	 *
723
+	 * @param RequestInterface $request
724
+	 * @param ResponseInterface $response
725
+	 * @return void
726
+	 */
727
+	public function httpAfterGet(RequestInterface $request, ResponseInterface $response) {
728
+
729
+		if (strpos($response->getHeader('Content-Type'), 'text/vcard') === false) {
730
+			return;
731
+		}
732
+
733
+		$target = $this->negotiateVCard($request->getHeader('Accept'), $mimeType);
734
+
735
+		$newBody = $this->convertVCard(
736
+			$response->getBody(),
737
+			$target
738
+		);
739
+
740
+		$response->setBody($newBody);
741
+		$response->setHeader('Content-Type', $mimeType . '; charset=utf-8');
742
+		$response->setHeader('Content-Length', strlen($newBody));
743
+
744
+	}
745
+
746
+	/**
747
+	 * This helper function performs the content-type negotiation for vcards.
748
+	 *
749
+	 * It will return one of the following strings:
750
+	 * 1. vcard3
751
+	 * 2. vcard4
752
+	 * 3. jcard
753
+	 *
754
+	 * It defaults to vcard3.
755
+	 *
756
+	 * @param string $input
757
+	 * @param string $mimeType
758
+	 * @return string
759
+	 */
760
+	protected function negotiateVCard($input, &$mimeType = null) {
761
+
762
+		$result = HTTP\Util::negotiate(
763
+			$input,
764
+			[
765
+				// Most often used mime-type. Version 3
766
+				'text/x-vcard',
767
+				// The correct standard mime-type. Defaults to version 3 as
768
+				// well.
769
+				'text/vcard',
770
+				// vCard 4
771
+				'text/vcard; version=4.0',
772
+				// vCard 3
773
+				'text/vcard; version=3.0',
774
+				// jCard
775
+				'application/vcard+json',
776
+			]
777
+		);
778
+
779
+		$mimeType = $result;
780
+		switch ($result) {
781
+
782
+			default :
783
+			case 'text/x-vcard' :
784
+			case 'text/vcard' :
785
+			case 'text/vcard; version=3.0' :
786
+				$mimeType = 'text/vcard';
787
+				return 'vcard3';
788
+			case 'text/vcard; version=4.0' :
789
+				return 'vcard4';
790
+			case 'application/vcard+json' :
791
+				return 'jcard';
792
+
793
+		// @codeCoverageIgnoreStart
794
+		}
795
+		// @codeCoverageIgnoreEnd
796
+
797
+	}
798
+
799
+	/**
800
+	 * Converts a vcard blob to a different version, or jcard.
801
+	 *
802
+	 * @param string $data
803
+	 * @param string $target
804
+	 * @return string
805
+	 */
806
+	protected function convertVCard($data, $target) {
807
+
808
+		$data = VObject\Reader::read($data);
809
+		switch ($target) {
810
+			default :
811
+			case 'vcard3' :
812
+				$data = $data->convert(VObject\Document::VCARD30);
813
+				$newResult = $data->serialize();
814
+				break;
815
+			case 'vcard4' :
816
+				$data = $data->convert(VObject\Document::VCARD40);
817
+				$newResult = $data->serialize();
818
+				break;
819
+			case 'jcard' :
820
+				$data = $data->convert(VObject\Document::VCARD40);
821
+				$newResult = json_encode($data->jsonSerialize());
822
+				break;
823
+
824
+		}
825
+		// Destroy circular references to PHP will GC the object.
826
+		$data->destroy();
827
+
828
+		return $newResult;
829
+
830
+	}
831
+
832
+	/**
833
+	 * Returns a plugin name.
834
+	 *
835
+	 * Using this name other plugins will be able to access other plugins
836
+	 * using DAV\Server::getPlugin
837
+	 *
838
+	 * @return string
839
+	 */
840
+	public function getPluginName() {
841
+
842
+		return 'carddav';
843
+
844
+	}
845
+
846
+	/**
847
+	 * Returns a bunch of meta-data about the plugin.
848
+	 *
849
+	 * Providing this information is optional, and is mainly displayed by the
850
+	 * Browser plugin.
851
+	 *
852
+	 * The description key in the returned array may contain html and will not
853
+	 * be sanitized.
854
+	 *
855
+	 * @return array
856
+	 */
857
+	public function getPluginInfo() {
858
+
859
+		return [
860
+			'name'        => $this->getPluginName(),
861
+			'description' => 'Adds support for CardDAV (rfc6352)',
862
+			'link'        => 'http://sabre.io/dav/carddav/',
863
+		];
864
+
865
+	}
866 866
 
867 867
 }
Please login to merge, or discard this patch.
Doc Comments   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -97,7 +97,7 @@  discard block
 block discarded – undo
97 97
      *
98 98
      * This is used in the DAV: header in the OPTIONS and PROPFIND requests.
99 99
      *
100
-     * @return array
100
+     * @return string[]
101 101
      */
102 102
     public function getFeatures() {
103 103
 
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
      * @param string $reportName
190 190
      * @param \DOMNode $dom
191 191
      * @param mixed $path
192
-     * @return bool
192
+     * @return false|null
193 193
      */
194 194
     public function report($reportName, $dom, $path) {
195 195
 
@@ -322,7 +322,7 @@  discard block
 block discarded – undo
322 322
      *
323 323
      * An exception is thrown if it's not.
324 324
      *
325
-     * @param resource|string $data
325
+     * @param resource $data
326 326
      * @param bool $modified Should be set to true, if this event handler
327 327
      *                       changed &$data.
328 328
      * @return void
@@ -694,7 +694,7 @@  discard block
 block discarded – undo
694 694
      *
695 695
      * @param DAV\INode $node
696 696
      * @param string $output
697
-     * @return bool
697
+     * @return null|false
698 698
      */
699 699
     public function htmlActionsPanel(DAV\INode $node, &$output) {
700 700
 
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -63,13 +63,13 @@
 block discarded – undo
63 63
     public function initialize(DAV\Server $server) {
64 64
 
65 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']);
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 73
 
74 74
         $server->xml->namespaceMap[self::NS_CARDDAV] = 'card';
75 75
 
Please login to merge, or discard this patch.
Braces   +42 added lines, -22 removed lines patch added patch discarded remove patch
@@ -159,8 +159,10 @@  discard block
 block discarded – undo
159 159
                 return new Href($this->getAddressBookHomeForPrincipal($path) . '/');
160 160
             });
161 161
 
162
-            if ($this->directories) $propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function() {
162
+            if ($this->directories) {
163
+            	$propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function() {
163 164
                 return new Href($this->directories);
165
+            }
164 166
             });
165 167
 
166 168
         }
@@ -172,8 +174,9 @@  discard block
 block discarded – undo
172 174
             // Therefore we simply expose it as a property.
173 175
             $propFind->handle('{' . self::NS_CARDDAV . '}address-data', function() use ($node) {
174 176
                 $val = $node->get();
175
-                if (is_resource($val))
176
-                    $val = stream_get_contents($val);
177
+                if (is_resource($val)) {
178
+                                    $val = stream_get_contents($val);
179
+                }
177 180
 
178 181
                 return $val;
179 182
 
@@ -288,8 +291,9 @@  discard block
 block discarded – undo
288 291
      */
289 292
     public function beforeWriteContent($path, DAV\IFile $node, &$data, &$modified) {
290 293
 
291
-        if (!$node instanceof ICard)
292
-            return;
294
+        if (!$node instanceof ICard) {
295
+                    return;
296
+        }
293 297
 
294 298
         $this->validateVCard($data, $modified);
295 299
 
@@ -310,8 +314,9 @@  discard block
 block discarded – undo
310 314
      */
311 315
     public function beforeCreateFile($path, &$data, DAV\ICollection $parentNode, &$modified) {
312 316
 
313
-        if (!$parentNode instanceof IAddressBook)
314
-            return;
317
+        if (!$parentNode instanceof IAddressBook) {
318
+                    return;
319
+        }
315 320
 
316 321
         $this->validateVCard($data, $modified);
317 322
 
@@ -339,7 +344,9 @@  discard block
 block discarded – undo
339 344
         // Converting the data to unicode, if needed.
340 345
         $data = DAV\StringUtil::ensureUTF8($data);
341 346
 
342
-        if (md5($data) !== $before) $modified = true;
347
+        if (md5($data) !== $before) {
348
+        	$modified = true;
349
+        }
343 350
 
344 351
         try {
345 352
 
@@ -414,8 +421,9 @@  discard block
 block discarded – undo
414 421
         $validNodes = [];
415 422
         foreach ($candidateNodes as $node) {
416 423
 
417
-            if (!$node instanceof ICard)
418
-                continue;
424
+            if (!$node instanceof ICard) {
425
+                            continue;
426
+            }
419 427
 
420 428
             $blob = $node->get();
421 429
             if (is_resource($blob)) {
@@ -478,7 +486,9 @@  discard block
 block discarded – undo
478 486
     public function validateFilters($vcardData, array $filters, $test) {
479 487
 
480 488
 
481
-        if (!$filters) return true;
489
+        if (!$filters) {
490
+        	return true;
491
+        }
482 492
         $vcard = VObject\Reader::read($vcardData);
483 493
 
484 494
         foreach ($filters as $filter) {
@@ -505,8 +515,9 @@  discard block
 block discarded – undo
505 515
                 }
506 516
                 if ($filter['text-matches']) {
507 517
                     $texts = [];
508
-                    foreach ($vProperties as $vProperty)
509
-                        $texts[] = $vProperty->getValue();
518
+                    foreach ($vProperties as $vProperty) {
519
+                                            $texts[] = $vProperty->getValue();
520
+                    }
510 521
 
511 522
                     $results[] = $this->validateTextMatches($texts, $filter['text-matches'], $filter['test']);
512 523
                 }
@@ -569,7 +580,9 @@  discard block
 block discarded – undo
569 580
             $isDefined = false;
570 581
             foreach ($vProperties as $vProperty) {
571 582
                 $isDefined = isset($vProperty[$filter['name']]);
572
-                if ($isDefined) break;
583
+                if ($isDefined) {
584
+                	break;
585
+                }
573 586
             }
574 587
 
575 588
             if ($filter['is-not-defined']) {
@@ -591,7 +604,9 @@  discard block
 block discarded – undo
591 604
                     // If we got all the way here, we'll need to validate the
592 605
                     // text-match filter.
593 606
                     $success = DAV\StringUtil::textMatch($vProperty[$filter['name']]->getValue(), $filter['text-match']['value'], $filter['text-match']['collation'], $filter['text-match']['match-type']);
594
-                    if ($success) break;
607
+                    if ($success) {
608
+                    	break;
609
+                    }
595 610
                 }
596 611
                 if ($filter['text-match']['negate-condition']) {
597 612
                     $success = !$success;
@@ -636,17 +651,21 @@  discard block
 block discarded – undo
636 651
                 $success = DAV\StringUtil::textMatch($haystack, $filter['value'], $filter['collation'], $filter['match-type']);
637 652
 
638 653
                 // Breaking on the first match
639
-                if ($success) break;
654
+                if ($success) {
655
+                	break;
656
+                }
640 657
             }
641 658
             if ($filter['negate-condition']) {
642 659
                 $success = !$success;
643 660
             }
644 661
 
645
-            if ($success && $test === 'anyof')
646
-                return true;
662
+            if ($success && $test === 'anyof') {
663
+                            return true;
664
+            }
647 665
 
648
-            if (!$success && $test == 'allof')
649
-                return false;
666
+            if (!$success && $test == 'allof') {
667
+                            return false;
668
+            }
650 669
 
651 670
 
652 671
         }
@@ -698,8 +717,9 @@  discard block
 block discarded – undo
698 717
      */
699 718
     public function htmlActionsPanel(DAV\INode $node, &$output) {
700 719
 
701
-        if (!$node instanceof AddressBookHome)
702
-            return;
720
+        if (!$node instanceof AddressBookHome) {
721
+                    return;
722
+        }
703 723
 
704 724
         $output .= '<tr><td colspan="2"><form method="post" action="">
705 725
             <h3>Create new address book</h3>
Please login to merge, or discard this patch.
libraries/SabreDAV/CardDAV/VCFExportPlugin.php 4 patches
Unused Use Statements   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -3,9 +3,9 @@
 block discarded – undo
3 3
 namespace Sabre\CardDAV;
4 4
 
5 5
 use Sabre\DAV;
6
-use Sabre\VObject;
7 6
 use Sabre\HTTP\RequestInterface;
8 7
 use Sabre\HTTP\ResponseInterface;
8
+use Sabre\VObject;
9 9
 
10 10
 /**
11 11
  * VCF Exporter
Please login to merge, or discard this patch.
Indentation   +124 added lines, -124 removed lines patch added patch discarded remove patch
@@ -21,132 +21,132 @@
 block discarded – undo
21 21
  */
22 22
 class VCFExportPlugin extends DAV\ServerPlugin {
23 23
 
24
-    /**
25
-     * Reference to Server class
26
-     *
27
-     * @var Sabre\DAV\Server
28
-     */
29
-    protected $server;
24
+	/**
25
+	 * Reference to Server class
26
+	 *
27
+	 * @var Sabre\DAV\Server
28
+	 */
29
+	protected $server;
30 30
 
31
-    /**
32
-     * Initializes the plugin and registers event handlers
33
-     *
34
-     * @param DAV\Server $server
35
-     * @return void
36
-     */
37
-    public function initialize(DAV\Server $server) {
38
-
39
-        $this->server = $server;
40
-        $this->server->on('method:GET', [$this, 'httpGet'], 90);
41
-        $server->on('browserButtonActions', function($path, $node, &$actions) {
42
-            if ($node instanceof IAddressBook) {
43
-                $actions .= '<a href="' . htmlspecialchars($path, ENT_QUOTES, 'UTF-8') . '?export"><span class="oi" data-glyph="book"></span></a>';
44
-            }
45
-        });
46
-    }
47
-
48
-    /**
49
-     * Intercepts GET requests on addressbook urls ending with ?export.
50
-     *
51
-     * @param RequestInterface $request
52
-     * @param ResponseInterface $response
53
-     * @return bool
54
-     */
55
-    public function httpGet(RequestInterface $request, ResponseInterface $response) {
56
-
57
-        $queryParams = $request->getQueryParameters();
58
-        if (!array_key_exists('export', $queryParams)) return;
59
-
60
-        $path = $request->getPath();
61
-
62
-        $node = $this->server->tree->getNodeForPath($path);
63
-
64
-        if (!($node instanceof IAddressBook)) return;
65
-
66
-        $this->server->transactionType = 'get-addressbook-export';
67
-
68
-        // Checking ACL, if available.
69
-        if ($aclPlugin = $this->server->getPlugin('acl')) {
70
-            $aclPlugin->checkPrivileges($path, '{DAV:}read');
71
-        }
72
-
73
-        $response->setHeader('Content-Type', 'text/directory');
74
-        $response->setStatus(200);
75
-
76
-        $nodes = $this->server->getPropertiesForPath($path, [
77
-            '{' . Plugin::NS_CARDDAV . '}address-data',
78
-        ], 1);
79
-
80
-        $response->setBody($this->generateVCF($nodes));
81
-
82
-        // Returning false to break the event chain
83
-        return false;
84
-
85
-    }
86
-
87
-    /**
88
-     * Merges all vcard objects, and builds one big vcf export
89
-     *
90
-     * @param array $nodes
91
-     * @return string
92
-     */
93
-    public function generateVCF(array $nodes) {
94
-
95
-        $output = "";
96
-
97
-        foreach ($nodes as $node) {
98
-
99
-            if (!isset($node[200]['{' . Plugin::NS_CARDDAV . '}address-data'])) {
100
-                continue;
101
-            }
102
-            $nodeData = $node[200]['{' . Plugin::NS_CARDDAV . '}address-data'];
103
-
104
-            // Parsing this node so VObject can clean up the output.
105
-            $vcard = VObject\Reader::read($nodeData);
106
-            $output .= $vcard->serialize();
107
-
108
-            // Destroy circular references to PHP will GC the object.
109
-            $vcard->destroy();
110
-
111
-        }
112
-
113
-        return $output;
114
-
115
-    }
116
-
117
-    /**
118
-     * Returns a plugin name.
119
-     *
120
-     * Using this name other plugins will be able to access other plugins
121
-     * using \Sabre\DAV\Server::getPlugin
122
-     *
123
-     * @return string
124
-     */
125
-    public function getPluginName() {
126
-
127
-        return 'vcf-export';
128
-
129
-    }
130
-
131
-    /**
132
-     * Returns a bunch of meta-data about the plugin.
133
-     *
134
-     * Providing this information is optional, and is mainly displayed by the
135
-     * Browser plugin.
136
-     *
137
-     * The description key in the returned array may contain html and will not
138
-     * be sanitized.
139
-     *
140
-     * @return array
141
-     */
142
-    public function getPluginInfo() {
31
+	/**
32
+	 * Initializes the plugin and registers event handlers
33
+	 *
34
+	 * @param DAV\Server $server
35
+	 * @return void
36
+	 */
37
+	public function initialize(DAV\Server $server) {
38
+
39
+		$this->server = $server;
40
+		$this->server->on('method:GET', [$this, 'httpGet'], 90);
41
+		$server->on('browserButtonActions', function($path, $node, &$actions) {
42
+			if ($node instanceof IAddressBook) {
43
+				$actions .= '<a href="' . htmlspecialchars($path, ENT_QUOTES, 'UTF-8') . '?export"><span class="oi" data-glyph="book"></span></a>';
44
+			}
45
+		});
46
+	}
47
+
48
+	/**
49
+	 * Intercepts GET requests on addressbook urls ending with ?export.
50
+	 *
51
+	 * @param RequestInterface $request
52
+	 * @param ResponseInterface $response
53
+	 * @return bool
54
+	 */
55
+	public function httpGet(RequestInterface $request, ResponseInterface $response) {
56
+
57
+		$queryParams = $request->getQueryParameters();
58
+		if (!array_key_exists('export', $queryParams)) return;
59
+
60
+		$path = $request->getPath();
61
+
62
+		$node = $this->server->tree->getNodeForPath($path);
63
+
64
+		if (!($node instanceof IAddressBook)) return;
65
+
66
+		$this->server->transactionType = 'get-addressbook-export';
67
+
68
+		// Checking ACL, if available.
69
+		if ($aclPlugin = $this->server->getPlugin('acl')) {
70
+			$aclPlugin->checkPrivileges($path, '{DAV:}read');
71
+		}
72
+
73
+		$response->setHeader('Content-Type', 'text/directory');
74
+		$response->setStatus(200);
75
+
76
+		$nodes = $this->server->getPropertiesForPath($path, [
77
+			'{' . Plugin::NS_CARDDAV . '}address-data',
78
+		], 1);
79
+
80
+		$response->setBody($this->generateVCF($nodes));
81
+
82
+		// Returning false to break the event chain
83
+		return false;
84
+
85
+	}
86
+
87
+	/**
88
+	 * Merges all vcard objects, and builds one big vcf export
89
+	 *
90
+	 * @param array $nodes
91
+	 * @return string
92
+	 */
93
+	public function generateVCF(array $nodes) {
94
+
95
+		$output = "";
96
+
97
+		foreach ($nodes as $node) {
98
+
99
+			if (!isset($node[200]['{' . Plugin::NS_CARDDAV . '}address-data'])) {
100
+				continue;
101
+			}
102
+			$nodeData = $node[200]['{' . Plugin::NS_CARDDAV . '}address-data'];
103
+
104
+			// Parsing this node so VObject can clean up the output.
105
+			$vcard = VObject\Reader::read($nodeData);
106
+			$output .= $vcard->serialize();
107
+
108
+			// Destroy circular references to PHP will GC the object.
109
+			$vcard->destroy();
110
+
111
+		}
112
+
113
+		return $output;
114
+
115
+	}
116
+
117
+	/**
118
+	 * Returns a plugin name.
119
+	 *
120
+	 * Using this name other plugins will be able to access other plugins
121
+	 * using \Sabre\DAV\Server::getPlugin
122
+	 *
123
+	 * @return string
124
+	 */
125
+	public function getPluginName() {
126
+
127
+		return 'vcf-export';
128
+
129
+	}
130
+
131
+	/**
132
+	 * Returns a bunch of meta-data about the plugin.
133
+	 *
134
+	 * Providing this information is optional, and is mainly displayed by the
135
+	 * Browser plugin.
136
+	 *
137
+	 * The description key in the returned array may contain html and will not
138
+	 * be sanitized.
139
+	 *
140
+	 * @return array
141
+	 */
142
+	public function getPluginInfo() {
143 143
 
144
-        return [
145
-            'name'        => $this->getPluginName(),
146
-            'description' => 'Adds the ability to export CardDAV addressbooks as a single vCard file.',
147
-            'link'        => 'http://sabre.io/dav/vcf-export-plugin/',
148
-        ];
144
+		return [
145
+			'name'        => $this->getPluginName(),
146
+			'description' => 'Adds the ability to export CardDAV addressbooks as a single vCard file.',
147
+			'link'        => 'http://sabre.io/dav/vcf-export-plugin/',
148
+		];
149 149
 
150
-    }
150
+	}
151 151
 
152 152
 }
Please login to merge, or discard this patch.
Braces   +6 added lines, -2 removed lines patch added patch discarded remove patch
@@ -55,13 +55,17 @@
 block discarded – undo
55 55
     public function httpGet(RequestInterface $request, ResponseInterface $response) {
56 56
 
57 57
         $queryParams = $request->getQueryParameters();
58
-        if (!array_key_exists('export', $queryParams)) return;
58
+        if (!array_key_exists('export', $queryParams)) {
59
+        	return;
60
+        }
59 61
 
60 62
         $path = $request->getPath();
61 63
 
62 64
         $node = $this->server->tree->getNodeForPath($path);
63 65
 
64
-        if (!($node instanceof IAddressBook)) return;
66
+        if (!($node instanceof IAddressBook)) {
67
+        	return;
68
+        }
65 69
 
66 70
         $this->server->transactionType = 'get-addressbook-export';
67 71
 
Please login to merge, or discard this patch.
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -76,7 +76,7 @@
 block discarded – undo
76 76
      *
77 77
      * @param RequestInterface $request
78 78
      * @param ResponseInterface $response
79
-     * @return bool
79
+     * @return null|false
80 80
      */
81 81
     public function httpGet(RequestInterface $request, ResponseInterface $response) {
82 82
 
Please login to merge, or discard this patch.
libraries/SabreDAV/CardDAV/Xml/Filter/ParamFilter.php 3 patches
Unused Use Statements   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -2,10 +2,10 @@
 block discarded – undo
2 2
 
3 3
 namespace Sabre\CardDAV\Xml\Filter;
4 4
 
5
+use Sabre\CardDAV\Plugin;
6
+use Sabre\DAV\Exception\BadRequest;
5 7
 use Sabre\Xml\Element;
6 8
 use Sabre\Xml\Reader;
7
-use Sabre\DAV\Exception\BadRequest;
8
-use Sabre\CardDAV\Plugin;
9 9
 
10 10
 /**
11 11
  * ParamFilter parser.
Please login to merge, or discard this patch.
Indentation   +62 added lines, -62 removed lines patch added patch discarded remove patch
@@ -23,67 +23,67 @@
 block discarded – undo
23 23
  */
24 24
 abstract class ParamFilter implements Element {
25 25
 
26
-    /**
27
-     * The deserialize method is called during xml parsing.
28
-     *
29
-     * This method is called statictly, this is because in theory this method
30
-     * may be used as a type of constructor, or factory method.
31
-     *
32
-     * Often you want to return an instance of the current class, but you are
33
-     * free to return other data as well.
34
-     *
35
-     * You are responsible for advancing the reader to the next element. Not
36
-     * doing anything will result in a never-ending loop.
37
-     *
38
-     * If you just want to skip parsing for this element altogether, you can
39
-     * just call $reader->next();
40
-     *
41
-     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
42
-     * the next element.
43
-     *
44
-     * @param Reader $reader
45
-     * @return mixed
46
-     */
47
-    static function xmlDeserialize(Reader $reader) {
48
-
49
-        $result = [
50
-            'name'           => null,
51
-            'is-not-defined' => false,
52
-            'text-match'     => null,
53
-        ];
54
-
55
-        $att = $reader->parseAttributes();
56
-        $result['name'] = $att['name'];
57
-
58
-        $elems = $reader->parseInnerTree();
59
-
60
-        if (is_array($elems)) foreach ($elems as $elem) {
61
-
62
-            switch ($elem['name']) {
63
-
64
-                case '{' . Plugin::NS_CARDDAV . '}is-not-defined' :
65
-                    $result['is-not-defined'] = true;
66
-                    break;
67
-                case '{' . Plugin::NS_CARDDAV . '}text-match' :
68
-                    $matchType = isset($elem['attributes']['match-type']) ? $elem['attributes']['match-type'] : 'contains';
69
-
70
-                    if (!in_array($matchType, ['contains', 'equals', 'starts-with', 'ends-with'])) {
71
-                        throw new BadRequest('Unknown match-type: ' . $matchType);
72
-                    }
73
-                    $result['text-match'] = [
74
-                        'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes',
75
-                        'collation'        => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;unicode-casemap',
76
-                        'value'            => $elem['value'],
77
-                        'match-type'       => $matchType,
78
-                    ];
79
-                    break;
80
-
81
-            }
82
-
83
-        }
84
-
85
-        return $result;
86
-
87
-    }
26
+	/**
27
+	 * The deserialize method is called during xml parsing.
28
+	 *
29
+	 * This method is called statictly, this is because in theory this method
30
+	 * may be used as a type of constructor, or factory method.
31
+	 *
32
+	 * Often you want to return an instance of the current class, but you are
33
+	 * free to return other data as well.
34
+	 *
35
+	 * You are responsible for advancing the reader to the next element. Not
36
+	 * doing anything will result in a never-ending loop.
37
+	 *
38
+	 * If you just want to skip parsing for this element altogether, you can
39
+	 * just call $reader->next();
40
+	 *
41
+	 * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
42
+	 * the next element.
43
+	 *
44
+	 * @param Reader $reader
45
+	 * @return mixed
46
+	 */
47
+	static function xmlDeserialize(Reader $reader) {
48
+
49
+		$result = [
50
+			'name'           => null,
51
+			'is-not-defined' => false,
52
+			'text-match'     => null,
53
+		];
54
+
55
+		$att = $reader->parseAttributes();
56
+		$result['name'] = $att['name'];
57
+
58
+		$elems = $reader->parseInnerTree();
59
+
60
+		if (is_array($elems)) foreach ($elems as $elem) {
61
+
62
+			switch ($elem['name']) {
63
+
64
+				case '{' . Plugin::NS_CARDDAV . '}is-not-defined' :
65
+					$result['is-not-defined'] = true;
66
+					break;
67
+				case '{' . Plugin::NS_CARDDAV . '}text-match' :
68
+					$matchType = isset($elem['attributes']['match-type']) ? $elem['attributes']['match-type'] : 'contains';
69
+
70
+					if (!in_array($matchType, ['contains', 'equals', 'starts-with', 'ends-with'])) {
71
+						throw new BadRequest('Unknown match-type: ' . $matchType);
72
+					}
73
+					$result['text-match'] = [
74
+						'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes',
75
+						'collation'        => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;unicode-casemap',
76
+						'value'            => $elem['value'],
77
+						'match-type'       => $matchType,
78
+					];
79
+					break;
80
+
81
+			}
82
+
83
+		}
84
+
85
+		return $result;
86
+
87
+	}
88 88
 
89 89
 }
Please login to merge, or discard this patch.
Braces   +3 added lines, -1 removed lines patch added patch discarded remove patch
@@ -57,12 +57,14 @@
 block discarded – undo
57 57
 
58 58
         $elems = $reader->parseInnerTree();
59 59
 
60
-        if (is_array($elems)) foreach ($elems as $elem) {
60
+        if (is_array($elems)) {
61
+        	foreach ($elems as $elem) {
61 62
 
62 63
             switch ($elem['name']) {
63 64
 
64 65
                 case '{' . Plugin::NS_CARDDAV . '}is-not-defined' :
65 66
                     $result['is-not-defined'] = true;
67
+        }
66 68
                     break;
67 69
                 case '{' . Plugin::NS_CARDDAV . '}text-match' :
68 70
                     $matchType = isset($elem['attributes']['match-type']) ? $elem['attributes']['match-type'] : 'contains';
Please login to merge, or discard this patch.
libraries/SabreDAV/CardDAV/Xml/Filter/PropFilter.php 3 patches
Unused Use Statements   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -2,10 +2,10 @@
 block discarded – undo
2 2
 
3 3
 namespace Sabre\CardDAV\Xml\Filter;
4 4
 
5
+use Sabre\CardDAV\Plugin;
6
+use Sabre\DAV\Exception\BadRequest;
5 7
 use Sabre\Xml\Reader;
6 8
 use Sabre\Xml\XmlDeserializable;
7
-use Sabre\DAV\Exception\BadRequest;
8
-use Sabre\CardDAV\Plugin;
9 9
 
10 10
 /**
11 11
  * PropFilter parser.
Please login to merge, or discard this patch.
Indentation   +71 added lines, -71 removed lines patch added patch discarded remove patch
@@ -23,76 +23,76 @@
 block discarded – undo
23 23
  */
24 24
 class PropFilter implements XmlDeserializable {
25 25
 
26
-    /**
27
-     * The deserialize method is called during xml parsing.
28
-     *
29
-     * This method is called statictly, this is because in theory this method
30
-     * may be used as a type of constructor, or factory method.
31
-     *
32
-     * Often you want to return an instance of the current class, but you are
33
-     * free to return other data as well.
34
-     *
35
-     * You are responsible for advancing the reader to the next element. Not
36
-     * doing anything will result in a never-ending loop.
37
-     *
38
-     * If you just want to skip parsing for this element altogether, you can
39
-     * just call $reader->next();
40
-     *
41
-     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
42
-     * the next element.
43
-     *
44
-     * @param Reader $reader
45
-     * @return mixed
46
-     */
47
-    static function xmlDeserialize(Reader $reader) {
48
-
49
-        $result = [
50
-            'name'           => null,
51
-            'test'           => 'anyof',
52
-            'is-not-defined' => false,
53
-            'param-filters'  => [],
54
-            'text-matches'   => [],
55
-        ];
56
-
57
-        $att = $reader->parseAttributes();
58
-        $result['name'] = $att['name'];
59
-
60
-        if (isset($att['test']) && $att['test'] === 'allof') {
61
-            $result['test'] = 'allof';
62
-        }
63
-
64
-        $elems = $reader->parseInnerTree();
65
-
66
-        if (is_array($elems)) foreach ($elems as $elem) {
67
-
68
-            switch ($elem['name']) {
69
-
70
-                case '{' . Plugin::NS_CARDDAV . '}param-filter' :
71
-                    $result['param-filters'][] = $elem['value'];
72
-                    break;
73
-                case '{' . Plugin::NS_CARDDAV . '}is-not-defined' :
74
-                    $result['is-not-defined'] = true;
75
-                    break;
76
-                case '{' . Plugin::NS_CARDDAV . '}text-match' :
77
-                    $matchType = isset($elem['attributes']['match-type']) ? $elem['attributes']['match-type'] : 'contains';
78
-
79
-                    if (!in_array($matchType, ['contains', 'equals', 'starts-with', 'ends-with'])) {
80
-                        throw new BadRequest('Unknown match-type: ' . $matchType);
81
-                    }
82
-                    $result['text-matches'][] = [
83
-                        'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes',
84
-                        'collation'        => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;unicode-casemap',
85
-                        'value'            => $elem['value'],
86
-                        'match-type'       => $matchType,
87
-                    ];
88
-                    break;
89
-
90
-            }
91
-
92
-        }
93
-
94
-        return $result;
95
-
96
-    }
26
+	/**
27
+	 * The deserialize method is called during xml parsing.
28
+	 *
29
+	 * This method is called statictly, this is because in theory this method
30
+	 * may be used as a type of constructor, or factory method.
31
+	 *
32
+	 * Often you want to return an instance of the current class, but you are
33
+	 * free to return other data as well.
34
+	 *
35
+	 * You are responsible for advancing the reader to the next element. Not
36
+	 * doing anything will result in a never-ending loop.
37
+	 *
38
+	 * If you just want to skip parsing for this element altogether, you can
39
+	 * just call $reader->next();
40
+	 *
41
+	 * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
42
+	 * the next element.
43
+	 *
44
+	 * @param Reader $reader
45
+	 * @return mixed
46
+	 */
47
+	static function xmlDeserialize(Reader $reader) {
48
+
49
+		$result = [
50
+			'name'           => null,
51
+			'test'           => 'anyof',
52
+			'is-not-defined' => false,
53
+			'param-filters'  => [],
54
+			'text-matches'   => [],
55
+		];
56
+
57
+		$att = $reader->parseAttributes();
58
+		$result['name'] = $att['name'];
59
+
60
+		if (isset($att['test']) && $att['test'] === 'allof') {
61
+			$result['test'] = 'allof';
62
+		}
63
+
64
+		$elems = $reader->parseInnerTree();
65
+
66
+		if (is_array($elems)) foreach ($elems as $elem) {
67
+
68
+			switch ($elem['name']) {
69
+
70
+				case '{' . Plugin::NS_CARDDAV . '}param-filter' :
71
+					$result['param-filters'][] = $elem['value'];
72
+					break;
73
+				case '{' . Plugin::NS_CARDDAV . '}is-not-defined' :
74
+					$result['is-not-defined'] = true;
75
+					break;
76
+				case '{' . Plugin::NS_CARDDAV . '}text-match' :
77
+					$matchType = isset($elem['attributes']['match-type']) ? $elem['attributes']['match-type'] : 'contains';
78
+
79
+					if (!in_array($matchType, ['contains', 'equals', 'starts-with', 'ends-with'])) {
80
+						throw new BadRequest('Unknown match-type: ' . $matchType);
81
+					}
82
+					$result['text-matches'][] = [
83
+						'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes',
84
+						'collation'        => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;unicode-casemap',
85
+						'value'            => $elem['value'],
86
+						'match-type'       => $matchType,
87
+					];
88
+					break;
89
+
90
+			}
91
+
92
+		}
93
+
94
+		return $result;
95
+
96
+	}
97 97
 
98 98
 }
Please login to merge, or discard this patch.
Braces   +3 added lines, -1 removed lines patch added patch discarded remove patch
@@ -63,12 +63,14 @@
 block discarded – undo
63 63
 
64 64
         $elems = $reader->parseInnerTree();
65 65
 
66
-        if (is_array($elems)) foreach ($elems as $elem) {
66
+        if (is_array($elems)) {
67
+        	foreach ($elems as $elem) {
67 68
 
68 69
             switch ($elem['name']) {
69 70
 
70 71
                 case '{' . Plugin::NS_CARDDAV . '}param-filter' :
71 72
                     $result['param-filters'][] = $elem['value'];
73
+        }
72 74
                     break;
73 75
                 case '{' . Plugin::NS_CARDDAV . '}is-not-defined' :
74 76
                     $result['is-not-defined'] = true;
Please login to merge, or discard this patch.