Completed
Branch develop (37f7b7)
by
unknown
24:41
created
htdocs/includes/sabre/sabre/vobject/lib/Component/VAlarm.php 1 patch
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -18,121 +18,121 @@
 block discarded – undo
18 18
  */
19 19
 class VAlarm extends VObject\Component
20 20
 {
21
-    /**
22
-     * Returns a DateTime object when this alarm is going to trigger.
23
-     *
24
-     * This ignores repeated alarm, only the first trigger is returned.
25
-     *
26
-     * @return DateTimeImmutable
27
-     */
28
-    public function getEffectiveTriggerTime()
29
-    {
30
-        $trigger = $this->TRIGGER;
31
-        if (!isset($trigger['VALUE']) || 'DURATION' === strtoupper($trigger['VALUE'])) {
32
-            $triggerDuration = VObject\DateTimeParser::parseDuration($this->TRIGGER);
33
-            $related = (isset($trigger['RELATED']) && 'END' == strtoupper($trigger['RELATED'])) ? 'END' : 'START';
21
+	/**
22
+	 * Returns a DateTime object when this alarm is going to trigger.
23
+	 *
24
+	 * This ignores repeated alarm, only the first trigger is returned.
25
+	 *
26
+	 * @return DateTimeImmutable
27
+	 */
28
+	public function getEffectiveTriggerTime()
29
+	{
30
+		$trigger = $this->TRIGGER;
31
+		if (!isset($trigger['VALUE']) || 'DURATION' === strtoupper($trigger['VALUE'])) {
32
+			$triggerDuration = VObject\DateTimeParser::parseDuration($this->TRIGGER);
33
+			$related = (isset($trigger['RELATED']) && 'END' == strtoupper($trigger['RELATED'])) ? 'END' : 'START';
34 34
 
35
-            $parentComponent = $this->parent;
36
-            if ('START' === $related) {
37
-                if ('VTODO' === $parentComponent->name) {
38
-                    $propName = 'DUE';
39
-                } else {
40
-                    $propName = 'DTSTART';
41
-                }
35
+			$parentComponent = $this->parent;
36
+			if ('START' === $related) {
37
+				if ('VTODO' === $parentComponent->name) {
38
+					$propName = 'DUE';
39
+				} else {
40
+					$propName = 'DTSTART';
41
+				}
42 42
 
43
-                $effectiveTrigger = $parentComponent->$propName->getDateTime();
44
-                $effectiveTrigger = $effectiveTrigger->add($triggerDuration);
45
-            } else {
46
-                if ('VTODO' === $parentComponent->name) {
47
-                    $endProp = 'DUE';
48
-                } elseif ('VEVENT' === $parentComponent->name) {
49
-                    $endProp = 'DTEND';
50
-                } else {
51
-                    throw new InvalidDataException('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT');
52
-                }
43
+				$effectiveTrigger = $parentComponent->$propName->getDateTime();
44
+				$effectiveTrigger = $effectiveTrigger->add($triggerDuration);
45
+			} else {
46
+				if ('VTODO' === $parentComponent->name) {
47
+					$endProp = 'DUE';
48
+				} elseif ('VEVENT' === $parentComponent->name) {
49
+					$endProp = 'DTEND';
50
+				} else {
51
+					throw new InvalidDataException('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT');
52
+				}
53 53
 
54
-                if (isset($parentComponent->$endProp)) {
55
-                    $effectiveTrigger = $parentComponent->$endProp->getDateTime();
56
-                    $effectiveTrigger = $effectiveTrigger->add($triggerDuration);
57
-                } elseif (isset($parentComponent->DURATION)) {
58
-                    $effectiveTrigger = $parentComponent->DTSTART->getDateTime();
59
-                    $duration = VObject\DateTimeParser::parseDuration($parentComponent->DURATION);
60
-                    $effectiveTrigger = $effectiveTrigger->add($duration);
61
-                    $effectiveTrigger = $effectiveTrigger->add($triggerDuration);
62
-                } else {
63
-                    $effectiveTrigger = $parentComponent->DTSTART->getDateTime();
64
-                    $effectiveTrigger = $effectiveTrigger->add($triggerDuration);
65
-                }
66
-            }
67
-        } else {
68
-            $effectiveTrigger = $trigger->getDateTime();
69
-        }
54
+				if (isset($parentComponent->$endProp)) {
55
+					$effectiveTrigger = $parentComponent->$endProp->getDateTime();
56
+					$effectiveTrigger = $effectiveTrigger->add($triggerDuration);
57
+				} elseif (isset($parentComponent->DURATION)) {
58
+					$effectiveTrigger = $parentComponent->DTSTART->getDateTime();
59
+					$duration = VObject\DateTimeParser::parseDuration($parentComponent->DURATION);
60
+					$effectiveTrigger = $effectiveTrigger->add($duration);
61
+					$effectiveTrigger = $effectiveTrigger->add($triggerDuration);
62
+				} else {
63
+					$effectiveTrigger = $parentComponent->DTSTART->getDateTime();
64
+					$effectiveTrigger = $effectiveTrigger->add($triggerDuration);
65
+				}
66
+			}
67
+		} else {
68
+			$effectiveTrigger = $trigger->getDateTime();
69
+		}
70 70
 
71
-        return $effectiveTrigger;
72
-    }
71
+		return $effectiveTrigger;
72
+	}
73 73
 
74
-    /**
75
-     * Returns true or false depending on if the event falls in the specified
76
-     * time-range. This is used for filtering purposes.
77
-     *
78
-     * The rules used to determine if an event falls within the specified
79
-     * time-range is based on the CalDAV specification.
80
-     *
81
-     * @param DateTime $start
82
-     * @param DateTime $end
83
-     *
84
-     * @return bool
85
-     */
86
-    public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
87
-    {
88
-        $effectiveTrigger = $this->getEffectiveTriggerTime();
74
+	/**
75
+	 * Returns true or false depending on if the event falls in the specified
76
+	 * time-range. This is used for filtering purposes.
77
+	 *
78
+	 * The rules used to determine if an event falls within the specified
79
+	 * time-range is based on the CalDAV specification.
80
+	 *
81
+	 * @param DateTime $start
82
+	 * @param DateTime $end
83
+	 *
84
+	 * @return bool
85
+	 */
86
+	public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
87
+	{
88
+		$effectiveTrigger = $this->getEffectiveTriggerTime();
89 89
 
90
-        if (isset($this->DURATION)) {
91
-            $duration = VObject\DateTimeParser::parseDuration($this->DURATION);
92
-            $repeat = (string) $this->REPEAT;
93
-            if (!$repeat) {
94
-                $repeat = 1;
95
-            }
90
+		if (isset($this->DURATION)) {
91
+			$duration = VObject\DateTimeParser::parseDuration($this->DURATION);
92
+			$repeat = (string) $this->REPEAT;
93
+			if (!$repeat) {
94
+				$repeat = 1;
95
+			}
96 96
 
97
-            $period = new \DatePeriod($effectiveTrigger, $duration, (int) $repeat);
97
+			$period = new \DatePeriod($effectiveTrigger, $duration, (int) $repeat);
98 98
 
99
-            foreach ($period as $occurrence) {
100
-                if ($start <= $occurrence && $end > $occurrence) {
101
-                    return true;
102
-                }
103
-            }
99
+			foreach ($period as $occurrence) {
100
+				if ($start <= $occurrence && $end > $occurrence) {
101
+					return true;
102
+				}
103
+			}
104 104
 
105
-            return false;
106
-        } else {
107
-            return $start <= $effectiveTrigger && $end > $effectiveTrigger;
108
-        }
109
-    }
105
+			return false;
106
+		} else {
107
+			return $start <= $effectiveTrigger && $end > $effectiveTrigger;
108
+		}
109
+	}
110 110
 
111
-    /**
112
-     * A simple list of validation rules.
113
-     *
114
-     * This is simply a list of properties, and how many times they either
115
-     * must or must not appear.
116
-     *
117
-     * Possible values per property:
118
-     *   * 0 - Must not appear.
119
-     *   * 1 - Must appear exactly once.
120
-     *   * + - Must appear at least once.
121
-     *   * * - Can appear any number of times.
122
-     *   * ? - May appear, but not more than once.
123
-     *
124
-     * @var array
125
-     */
126
-    public function getValidationRules()
127
-    {
128
-        return [
129
-            'ACTION' => 1,
130
-            'TRIGGER' => 1,
111
+	/**
112
+	 * A simple list of validation rules.
113
+	 *
114
+	 * This is simply a list of properties, and how many times they either
115
+	 * must or must not appear.
116
+	 *
117
+	 * Possible values per property:
118
+	 *   * 0 - Must not appear.
119
+	 *   * 1 - Must appear exactly once.
120
+	 *   * + - Must appear at least once.
121
+	 *   * * - Can appear any number of times.
122
+	 *   * ? - May appear, but not more than once.
123
+	 *
124
+	 * @var array
125
+	 */
126
+	public function getValidationRules()
127
+	{
128
+		return [
129
+			'ACTION' => 1,
130
+			'TRIGGER' => 1,
131 131
 
132
-            'DURATION' => '?',
133
-            'REPEAT' => '?',
132
+			'DURATION' => '?',
133
+			'REPEAT' => '?',
134 134
 
135
-            'ATTACH' => '?',
136
-        ];
137
-    }
135
+			'ATTACH' => '?',
136
+		];
137
+	}
138 138
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VTodo.php 1 patch
Indentation   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -16,166 +16,166 @@
 block discarded – undo
16 16
  */
17 17
 class VTodo extends VObject\Component
18 18
 {
19
-    /**
20
-     * Returns true or false depending on if the event falls in the specified
21
-     * time-range. This is used for filtering purposes.
22
-     *
23
-     * The rules used to determine if an event falls within the specified
24
-     * time-range is based on the CalDAV specification.
25
-     *
26
-     * @return bool
27
-     */
28
-    public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
29
-    {
30
-        $dtstart = isset($this->DTSTART) ? $this->DTSTART->getDateTime() : null;
31
-        $duration = isset($this->DURATION) ? VObject\DateTimeParser::parseDuration($this->DURATION) : null;
32
-        $due = isset($this->DUE) ? $this->DUE->getDateTime() : null;
33
-        $completed = isset($this->COMPLETED) ? $this->COMPLETED->getDateTime() : null;
34
-        $created = isset($this->CREATED) ? $this->CREATED->getDateTime() : null;
19
+	/**
20
+	 * Returns true or false depending on if the event falls in the specified
21
+	 * time-range. This is used for filtering purposes.
22
+	 *
23
+	 * The rules used to determine if an event falls within the specified
24
+	 * time-range is based on the CalDAV specification.
25
+	 *
26
+	 * @return bool
27
+	 */
28
+	public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
29
+	{
30
+		$dtstart = isset($this->DTSTART) ? $this->DTSTART->getDateTime() : null;
31
+		$duration = isset($this->DURATION) ? VObject\DateTimeParser::parseDuration($this->DURATION) : null;
32
+		$due = isset($this->DUE) ? $this->DUE->getDateTime() : null;
33
+		$completed = isset($this->COMPLETED) ? $this->COMPLETED->getDateTime() : null;
34
+		$created = isset($this->CREATED) ? $this->CREATED->getDateTime() : null;
35 35
 
36
-        if ($dtstart) {
37
-            if ($duration) {
38
-                $effectiveEnd = $dtstart->add($duration);
36
+		if ($dtstart) {
37
+			if ($duration) {
38
+				$effectiveEnd = $dtstart->add($duration);
39 39
 
40
-                return $start <= $effectiveEnd && $end > $dtstart;
41
-            } elseif ($due) {
42
-                return
43
-                    ($start < $due || $start <= $dtstart) &&
44
-                    ($end > $dtstart || $end >= $due);
45
-            } else {
46
-                return $start <= $dtstart && $end > $dtstart;
47
-            }
48
-        }
49
-        if ($due) {
50
-            return $start < $due && $end >= $due;
51
-        }
52
-        if ($completed && $created) {
53
-            return
54
-                ($start <= $created || $start <= $completed) &&
55
-                ($end >= $created || $end >= $completed);
56
-        }
57
-        if ($completed) {
58
-            return $start <= $completed && $end >= $completed;
59
-        }
60
-        if ($created) {
61
-            return $end > $created;
62
-        }
40
+				return $start <= $effectiveEnd && $end > $dtstart;
41
+			} elseif ($due) {
42
+				return
43
+					($start < $due || $start <= $dtstart) &&
44
+					($end > $dtstart || $end >= $due);
45
+			} else {
46
+				return $start <= $dtstart && $end > $dtstart;
47
+			}
48
+		}
49
+		if ($due) {
50
+			return $start < $due && $end >= $due;
51
+		}
52
+		if ($completed && $created) {
53
+			return
54
+				($start <= $created || $start <= $completed) &&
55
+				($end >= $created || $end >= $completed);
56
+		}
57
+		if ($completed) {
58
+			return $start <= $completed && $end >= $completed;
59
+		}
60
+		if ($created) {
61
+			return $end > $created;
62
+		}
63 63
 
64
-        return true;
65
-    }
64
+		return true;
65
+	}
66 66
 
67
-    /**
68
-     * A simple list of validation rules.
69
-     *
70
-     * This is simply a list of properties, and how many times they either
71
-     * must or must not appear.
72
-     *
73
-     * Possible values per property:
74
-     *   * 0 - Must not appear.
75
-     *   * 1 - Must appear exactly once.
76
-     *   * + - Must appear at least once.
77
-     *   * * - Can appear any number of times.
78
-     *   * ? - May appear, but not more than once.
79
-     *
80
-     * @var array
81
-     */
82
-    public function getValidationRules()
83
-    {
84
-        return [
85
-            'UID' => 1,
86
-            'DTSTAMP' => 1,
67
+	/**
68
+	 * A simple list of validation rules.
69
+	 *
70
+	 * This is simply a list of properties, and how many times they either
71
+	 * must or must not appear.
72
+	 *
73
+	 * Possible values per property:
74
+	 *   * 0 - Must not appear.
75
+	 *   * 1 - Must appear exactly once.
76
+	 *   * + - Must appear at least once.
77
+	 *   * * - Can appear any number of times.
78
+	 *   * ? - May appear, but not more than once.
79
+	 *
80
+	 * @var array
81
+	 */
82
+	public function getValidationRules()
83
+	{
84
+		return [
85
+			'UID' => 1,
86
+			'DTSTAMP' => 1,
87 87
 
88
-            'CLASS' => '?',
89
-            'COMPLETED' => '?',
90
-            'CREATED' => '?',
91
-            'DESCRIPTION' => '?',
92
-            'DTSTART' => '?',
93
-            'GEO' => '?',
94
-            'LAST-MODIFIED' => '?',
95
-            'LOCATION' => '?',
96
-            'ORGANIZER' => '?',
97
-            'PERCENT' => '?',
98
-            'PRIORITY' => '?',
99
-            'RECURRENCE-ID' => '?',
100
-            'SEQUENCE' => '?',
101
-            'STATUS' => '?',
102
-            'SUMMARY' => '?',
103
-            'URL' => '?',
88
+			'CLASS' => '?',
89
+			'COMPLETED' => '?',
90
+			'CREATED' => '?',
91
+			'DESCRIPTION' => '?',
92
+			'DTSTART' => '?',
93
+			'GEO' => '?',
94
+			'LAST-MODIFIED' => '?',
95
+			'LOCATION' => '?',
96
+			'ORGANIZER' => '?',
97
+			'PERCENT' => '?',
98
+			'PRIORITY' => '?',
99
+			'RECURRENCE-ID' => '?',
100
+			'SEQUENCE' => '?',
101
+			'STATUS' => '?',
102
+			'SUMMARY' => '?',
103
+			'URL' => '?',
104 104
 
105
-            'RRULE' => '?',
106
-            'DUE' => '?',
107
-            'DURATION' => '?',
105
+			'RRULE' => '?',
106
+			'DUE' => '?',
107
+			'DURATION' => '?',
108 108
 
109
-            'ATTACH' => '*',
110
-            'ATTENDEE' => '*',
111
-            'CATEGORIES' => '*',
112
-            'COMMENT' => '*',
113
-            'CONTACT' => '*',
114
-            'EXDATE' => '*',
115
-            'REQUEST-STATUS' => '*',
116
-            'RELATED-TO' => '*',
117
-            'RESOURCES' => '*',
118
-            'RDATE' => '*',
119
-        ];
120
-    }
109
+			'ATTACH' => '*',
110
+			'ATTENDEE' => '*',
111
+			'CATEGORIES' => '*',
112
+			'COMMENT' => '*',
113
+			'CONTACT' => '*',
114
+			'EXDATE' => '*',
115
+			'REQUEST-STATUS' => '*',
116
+			'RELATED-TO' => '*',
117
+			'RESOURCES' => '*',
118
+			'RDATE' => '*',
119
+		];
120
+	}
121 121
 
122
-    /**
123
-     * Validates the node for correctness.
124
-     *
125
-     * The following options are supported:
126
-     *   Node::REPAIR - May attempt to automatically repair the problem.
127
-     *
128
-     * This method returns an array with detected problems.
129
-     * Every element has the following properties:
130
-     *
131
-     *  * level - problem level.
132
-     *  * message - A human-readable string describing the issue.
133
-     *  * node - A reference to the problematic node.
134
-     *
135
-     * The level means:
136
-     *   1 - The issue was repaired (only happens if REPAIR was turned on)
137
-     *   2 - An inconsequential issue
138
-     *   3 - A severe issue.
139
-     *
140
-     * @param int $options
141
-     *
142
-     * @return array
143
-     */
144
-    public function validate($options = 0)
145
-    {
146
-        $result = parent::validate($options);
147
-        if (isset($this->DUE) && isset($this->DTSTART)) {
148
-            $due = $this->DUE;
149
-            $dtStart = $this->DTSTART;
122
+	/**
123
+	 * Validates the node for correctness.
124
+	 *
125
+	 * The following options are supported:
126
+	 *   Node::REPAIR - May attempt to automatically repair the problem.
127
+	 *
128
+	 * This method returns an array with detected problems.
129
+	 * Every element has the following properties:
130
+	 *
131
+	 *  * level - problem level.
132
+	 *  * message - A human-readable string describing the issue.
133
+	 *  * node - A reference to the problematic node.
134
+	 *
135
+	 * The level means:
136
+	 *   1 - The issue was repaired (only happens if REPAIR was turned on)
137
+	 *   2 - An inconsequential issue
138
+	 *   3 - A severe issue.
139
+	 *
140
+	 * @param int $options
141
+	 *
142
+	 * @return array
143
+	 */
144
+	public function validate($options = 0)
145
+	{
146
+		$result = parent::validate($options);
147
+		if (isset($this->DUE) && isset($this->DTSTART)) {
148
+			$due = $this->DUE;
149
+			$dtStart = $this->DTSTART;
150 150
 
151
-            if ($due->getValueType() !== $dtStart->getValueType()) {
152
-                $result[] = [
153
-                    'level' => 3,
154
-                    'message' => 'The value type (DATE or DATE-TIME) must be identical for DUE and DTSTART',
155
-                    'node' => $due,
156
-                ];
157
-            } elseif ($due->getDateTime() < $dtStart->getDateTime()) {
158
-                $result[] = [
159
-                    'level' => 3,
160
-                    'message' => 'DUE must occur after DTSTART',
161
-                    'node' => $due,
162
-                ];
163
-            }
164
-        }
151
+			if ($due->getValueType() !== $dtStart->getValueType()) {
152
+				$result[] = [
153
+					'level' => 3,
154
+					'message' => 'The value type (DATE or DATE-TIME) must be identical for DUE and DTSTART',
155
+					'node' => $due,
156
+				];
157
+			} elseif ($due->getDateTime() < $dtStart->getDateTime()) {
158
+				$result[] = [
159
+					'level' => 3,
160
+					'message' => 'DUE must occur after DTSTART',
161
+					'node' => $due,
162
+				];
163
+			}
164
+		}
165 165
 
166
-        return $result;
167
-    }
166
+		return $result;
167
+	}
168 168
 
169
-    /**
170
-     * This method should return a list of default property values.
171
-     *
172
-     * @return array
173
-     */
174
-    protected function getDefaults()
175
-    {
176
-        return [
177
-            'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
178
-            'DTSTAMP' => date('Ymd\\THis\\Z'),
179
-        ];
180
-    }
169
+	/**
170
+	 * This method should return a list of default property values.
171
+	 *
172
+	 * @return array
173
+	 */
174
+	protected function getDefaults()
175
+	{
176
+		return [
177
+			'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
178
+			'DTSTAMP' => date('Ymd\\THis\\Z'),
179
+		];
180
+	}
181 181
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VFreeBusy.php 1 patch
Indentation   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -17,77 +17,77 @@
 block discarded – undo
17 17
  */
18 18
 class VFreeBusy extends VObject\Component
19 19
 {
20
-    /**
21
-     * Checks based on the contained FREEBUSY information, if a timeslot is
22
-     * available.
23
-     *
24
-     * @return bool
25
-     */
26
-    public function isFree(DateTimeInterface $start, DatetimeInterface $end)
27
-    {
28
-        foreach ($this->select('FREEBUSY') as $freebusy) {
29
-            // We are only interested in FBTYPE=BUSY (the default),
30
-            // FBTYPE=BUSY-TENTATIVE or FBTYPE=BUSY-UNAVAILABLE.
31
-            if (isset($freebusy['FBTYPE']) && 'BUSY' !== strtoupper(substr((string) $freebusy['FBTYPE'], 0, 4))) {
32
-                continue;
33
-            }
20
+	/**
21
+	 * Checks based on the contained FREEBUSY information, if a timeslot is
22
+	 * available.
23
+	 *
24
+	 * @return bool
25
+	 */
26
+	public function isFree(DateTimeInterface $start, DatetimeInterface $end)
27
+	{
28
+		foreach ($this->select('FREEBUSY') as $freebusy) {
29
+			// We are only interested in FBTYPE=BUSY (the default),
30
+			// FBTYPE=BUSY-TENTATIVE or FBTYPE=BUSY-UNAVAILABLE.
31
+			if (isset($freebusy['FBTYPE']) && 'BUSY' !== strtoupper(substr((string) $freebusy['FBTYPE'], 0, 4))) {
32
+				continue;
33
+			}
34 34
 
35
-            // The freebusy component can hold more than 1 value, separated by
36
-            // commas.
37
-            $periods = explode(',', (string) $freebusy);
35
+			// The freebusy component can hold more than 1 value, separated by
36
+			// commas.
37
+			$periods = explode(',', (string) $freebusy);
38 38
 
39
-            foreach ($periods as $period) {
40
-                // Every period is formatted as [start]/[end]. The start is an
41
-                // absolute UTC time, the end may be an absolute UTC time, or
42
-                // duration (relative) value.
43
-                list($busyStart, $busyEnd) = explode('/', $period);
39
+			foreach ($periods as $period) {
40
+				// Every period is formatted as [start]/[end]. The start is an
41
+				// absolute UTC time, the end may be an absolute UTC time, or
42
+				// duration (relative) value.
43
+				list($busyStart, $busyEnd) = explode('/', $period);
44 44
 
45
-                $busyStart = VObject\DateTimeParser::parse($busyStart);
46
-                $busyEnd = VObject\DateTimeParser::parse($busyEnd);
47
-                if ($busyEnd instanceof \DateInterval) {
48
-                    $busyEnd = $busyStart->add($busyEnd);
49
-                }
45
+				$busyStart = VObject\DateTimeParser::parse($busyStart);
46
+				$busyEnd = VObject\DateTimeParser::parse($busyEnd);
47
+				if ($busyEnd instanceof \DateInterval) {
48
+					$busyEnd = $busyStart->add($busyEnd);
49
+				}
50 50
 
51
-                if ($start < $busyEnd && $end > $busyStart) {
52
-                    return false;
53
-                }
54
-            }
55
-        }
51
+				if ($start < $busyEnd && $end > $busyStart) {
52
+					return false;
53
+				}
54
+			}
55
+		}
56 56
 
57
-        return true;
58
-    }
57
+		return true;
58
+	}
59 59
 
60
-    /**
61
-     * A simple list of validation rules.
62
-     *
63
-     * This is simply a list of properties, and how many times they either
64
-     * must or must not appear.
65
-     *
66
-     * Possible values per property:
67
-     *   * 0 - Must not appear.
68
-     *   * 1 - Must appear exactly once.
69
-     *   * + - Must appear at least once.
70
-     *   * * - Can appear any number of times.
71
-     *   * ? - May appear, but not more than once.
72
-     *
73
-     * @var array
74
-     */
75
-    public function getValidationRules()
76
-    {
77
-        return [
78
-            'UID' => 1,
79
-            'DTSTAMP' => 1,
60
+	/**
61
+	 * A simple list of validation rules.
62
+	 *
63
+	 * This is simply a list of properties, and how many times they either
64
+	 * must or must not appear.
65
+	 *
66
+	 * Possible values per property:
67
+	 *   * 0 - Must not appear.
68
+	 *   * 1 - Must appear exactly once.
69
+	 *   * + - Must appear at least once.
70
+	 *   * * - Can appear any number of times.
71
+	 *   * ? - May appear, but not more than once.
72
+	 *
73
+	 * @var array
74
+	 */
75
+	public function getValidationRules()
76
+	{
77
+		return [
78
+			'UID' => 1,
79
+			'DTSTAMP' => 1,
80 80
 
81
-            'CONTACT' => '?',
82
-            'DTSTART' => '?',
83
-            'DTEND' => '?',
84
-            'ORGANIZER' => '?',
85
-            'URL' => '?',
81
+			'CONTACT' => '?',
82
+			'DTSTART' => '?',
83
+			'DTEND' => '?',
84
+			'ORGANIZER' => '?',
85
+			'URL' => '?',
86 86
 
87
-            'ATTENDEE' => '*',
88
-            'COMMENT' => '*',
89
-            'FREEBUSY' => '*',
90
-            'REQUEST-STATUS' => '*',
91
-        ];
92
-    }
87
+			'ATTENDEE' => '*',
88
+			'COMMENT' => '*',
89
+			'FREEBUSY' => '*',
90
+			'REQUEST-STATUS' => '*',
91
+		];
92
+	}
93 93
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VEvent.php 1 patch
Indentation   +111 added lines, -111 removed lines patch added patch discarded remove patch
@@ -18,123 +18,123 @@
 block discarded – undo
18 18
  */
19 19
 class VEvent extends VObject\Component
20 20
 {
21
-    /**
22
-     * Returns true or false depending on if the event falls in the specified
23
-     * time-range. This is used for filtering purposes.
24
-     *
25
-     * The rules used to determine if an event falls within the specified
26
-     * time-range is based on the CalDAV specification.
27
-     *
28
-     * @return bool
29
-     */
30
-    public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
31
-    {
32
-        if ($this->RRULE) {
33
-            try {
34
-                $it = new EventIterator($this, null, $start->getTimezone());
35
-            } catch (NoInstancesException $e) {
36
-                // If we've caught this exception, there are no instances
37
-                // for the event that fall into the specified time-range.
38
-                return false;
39
-            }
21
+	/**
22
+	 * Returns true or false depending on if the event falls in the specified
23
+	 * time-range. This is used for filtering purposes.
24
+	 *
25
+	 * The rules used to determine if an event falls within the specified
26
+	 * time-range is based on the CalDAV specification.
27
+	 *
28
+	 * @return bool
29
+	 */
30
+	public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
31
+	{
32
+		if ($this->RRULE) {
33
+			try {
34
+				$it = new EventIterator($this, null, $start->getTimezone());
35
+			} catch (NoInstancesException $e) {
36
+				// If we've caught this exception, there are no instances
37
+				// for the event that fall into the specified time-range.
38
+				return false;
39
+			}
40 40
 
41
-            $it->fastForward($start);
41
+			$it->fastForward($start);
42 42
 
43
-            // We fast-forwarded to a spot where the end-time of the
44
-            // recurrence instance exceeded the start of the requested
45
-            // time-range.
46
-            //
47
-            // If the starttime of the recurrence did not exceed the
48
-            // end of the time range as well, we have a match.
49
-            return $it->getDTStart() < $end && $it->getDTEnd() > $start;
50
-        }
43
+			// We fast-forwarded to a spot where the end-time of the
44
+			// recurrence instance exceeded the start of the requested
45
+			// time-range.
46
+			//
47
+			// If the starttime of the recurrence did not exceed the
48
+			// end of the time range as well, we have a match.
49
+			return $it->getDTStart() < $end && $it->getDTEnd() > $start;
50
+		}
51 51
 
52
-        $effectiveStart = $this->DTSTART->getDateTime($start->getTimezone());
53
-        if (isset($this->DTEND)) {
54
-            // The DTEND property is considered non inclusive. So for a 3 day
55
-            // event in july, dtstart and dtend would have to be July 1st and
56
-            // July 4th respectively.
57
-            //
58
-            // See:
59
-            // http://tools.ietf.org/html/rfc5545#page-54
60
-            $effectiveEnd = $this->DTEND->getDateTime($end->getTimezone());
61
-        } elseif (isset($this->DURATION)) {
62
-            $effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
63
-        } elseif (!$this->DTSTART->hasTime()) {
64
-            $effectiveEnd = $effectiveStart->modify('+1 day');
65
-        } else {
66
-            $effectiveEnd = $effectiveStart;
67
-        }
52
+		$effectiveStart = $this->DTSTART->getDateTime($start->getTimezone());
53
+		if (isset($this->DTEND)) {
54
+			// The DTEND property is considered non inclusive. So for a 3 day
55
+			// event in july, dtstart and dtend would have to be July 1st and
56
+			// July 4th respectively.
57
+			//
58
+			// See:
59
+			// http://tools.ietf.org/html/rfc5545#page-54
60
+			$effectiveEnd = $this->DTEND->getDateTime($end->getTimezone());
61
+		} elseif (isset($this->DURATION)) {
62
+			$effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
63
+		} elseif (!$this->DTSTART->hasTime()) {
64
+			$effectiveEnd = $effectiveStart->modify('+1 day');
65
+		} else {
66
+			$effectiveEnd = $effectiveStart;
67
+		}
68 68
 
69
-        return
70
-            ($start < $effectiveEnd) && ($end > $effectiveStart)
71
-        ;
72
-    }
69
+		return
70
+			($start < $effectiveEnd) && ($end > $effectiveStart)
71
+		;
72
+	}
73 73
 
74
-    /**
75
-     * This method should return a list of default property values.
76
-     *
77
-     * @return array
78
-     */
79
-    protected function getDefaults()
80
-    {
81
-        return [
82
-            'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
83
-            'DTSTAMP' => gmdate('Ymd\\THis\\Z'),
84
-        ];
85
-    }
74
+	/**
75
+	 * This method should return a list of default property values.
76
+	 *
77
+	 * @return array
78
+	 */
79
+	protected function getDefaults()
80
+	{
81
+		return [
82
+			'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
83
+			'DTSTAMP' => gmdate('Ymd\\THis\\Z'),
84
+		];
85
+	}
86 86
 
87
-    /**
88
-     * A simple list of validation rules.
89
-     *
90
-     * This is simply a list of properties, and how many times they either
91
-     * must or must not appear.
92
-     *
93
-     * Possible values per property:
94
-     *   * 0 - Must not appear.
95
-     *   * 1 - Must appear exactly once.
96
-     *   * + - Must appear at least once.
97
-     *   * * - Can appear any number of times.
98
-     *   * ? - May appear, but not more than once.
99
-     *
100
-     * @var array
101
-     */
102
-    public function getValidationRules()
103
-    {
104
-        $hasMethod = isset($this->parent->METHOD);
87
+	/**
88
+	 * A simple list of validation rules.
89
+	 *
90
+	 * This is simply a list of properties, and how many times they either
91
+	 * must or must not appear.
92
+	 *
93
+	 * Possible values per property:
94
+	 *   * 0 - Must not appear.
95
+	 *   * 1 - Must appear exactly once.
96
+	 *   * + - Must appear at least once.
97
+	 *   * * - Can appear any number of times.
98
+	 *   * ? - May appear, but not more than once.
99
+	 *
100
+	 * @var array
101
+	 */
102
+	public function getValidationRules()
103
+	{
104
+		$hasMethod = isset($this->parent->METHOD);
105 105
 
106
-        return [
107
-            'UID' => 1,
108
-            'DTSTAMP' => 1,
109
-            'DTSTART' => $hasMethod ? '?' : '1',
110
-            'CLASS' => '?',
111
-            'CREATED' => '?',
112
-            'DESCRIPTION' => '?',
113
-            'GEO' => '?',
114
-            'LAST-MODIFIED' => '?',
115
-            'LOCATION' => '?',
116
-            'ORGANIZER' => '?',
117
-            'PRIORITY' => '?',
118
-            'SEQUENCE' => '?',
119
-            'STATUS' => '?',
120
-            'SUMMARY' => '?',
121
-            'TRANSP' => '?',
122
-            'URL' => '?',
123
-            'RECURRENCE-ID' => '?',
124
-            'RRULE' => '?',
125
-            'DTEND' => '?',
126
-            'DURATION' => '?',
106
+		return [
107
+			'UID' => 1,
108
+			'DTSTAMP' => 1,
109
+			'DTSTART' => $hasMethod ? '?' : '1',
110
+			'CLASS' => '?',
111
+			'CREATED' => '?',
112
+			'DESCRIPTION' => '?',
113
+			'GEO' => '?',
114
+			'LAST-MODIFIED' => '?',
115
+			'LOCATION' => '?',
116
+			'ORGANIZER' => '?',
117
+			'PRIORITY' => '?',
118
+			'SEQUENCE' => '?',
119
+			'STATUS' => '?',
120
+			'SUMMARY' => '?',
121
+			'TRANSP' => '?',
122
+			'URL' => '?',
123
+			'RECURRENCE-ID' => '?',
124
+			'RRULE' => '?',
125
+			'DTEND' => '?',
126
+			'DURATION' => '?',
127 127
 
128
-            'ATTACH' => '*',
129
-            'ATTENDEE' => '*',
130
-            'CATEGORIES' => '*',
131
-            'COMMENT' => '*',
132
-            'CONTACT' => '*',
133
-            'EXDATE' => '*',
134
-            'REQUEST-STATUS' => '*',
135
-            'RELATED-TO' => '*',
136
-            'RESOURCES' => '*',
137
-            'RDATE' => '*',
138
-        ];
139
-    }
128
+			'ATTACH' => '*',
129
+			'ATTENDEE' => '*',
130
+			'CATEGORIES' => '*',
131
+			'COMMENT' => '*',
132
+			'CONTACT' => '*',
133
+			'EXDATE' => '*',
134
+			'REQUEST-STATUS' => '*',
135
+			'RELATED-TO' => '*',
136
+			'RESOURCES' => '*',
137
+			'RDATE' => '*',
138
+		];
139
+	}
140 140
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VTimeZone.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -16,48 +16,48 @@
 block discarded – undo
16 16
  */
17 17
 class VTimeZone extends VObject\Component
18 18
 {
19
-    /**
20
-     * Returns the PHP DateTimeZone for this VTIMEZONE component.
21
-     *
22
-     * If we can't accurately determine the timezone, this method will return
23
-     * UTC.
24
-     *
25
-     * @return \DateTimeZone
26
-     */
27
-    public function getTimeZone()
28
-    {
29
-        return VObject\TimeZoneUtil::getTimeZone((string) $this->TZID, $this->root);
30
-    }
19
+	/**
20
+	 * Returns the PHP DateTimeZone for this VTIMEZONE component.
21
+	 *
22
+	 * If we can't accurately determine the timezone, this method will return
23
+	 * UTC.
24
+	 *
25
+	 * @return \DateTimeZone
26
+	 */
27
+	public function getTimeZone()
28
+	{
29
+		return VObject\TimeZoneUtil::getTimeZone((string) $this->TZID, $this->root);
30
+	}
31 31
 
32
-    /**
33
-     * A simple list of validation rules.
34
-     *
35
-     * This is simply a list of properties, and how many times they either
36
-     * must or must not appear.
37
-     *
38
-     * Possible values per property:
39
-     *   * 0 - Must not appear.
40
-     *   * 1 - Must appear exactly once.
41
-     *   * + - Must appear at least once.
42
-     *   * * - Can appear any number of times.
43
-     *   * ? - May appear, but not more than once.
44
-     *
45
-     * @var array
46
-     */
47
-    public function getValidationRules()
48
-    {
49
-        return [
50
-            'TZID' => 1,
32
+	/**
33
+	 * A simple list of validation rules.
34
+	 *
35
+	 * This is simply a list of properties, and how many times they either
36
+	 * must or must not appear.
37
+	 *
38
+	 * Possible values per property:
39
+	 *   * 0 - Must not appear.
40
+	 *   * 1 - Must appear exactly once.
41
+	 *   * + - Must appear at least once.
42
+	 *   * * - Can appear any number of times.
43
+	 *   * ? - May appear, but not more than once.
44
+	 *
45
+	 * @var array
46
+	 */
47
+	public function getValidationRules()
48
+	{
49
+		return [
50
+			'TZID' => 1,
51 51
 
52
-            'LAST-MODIFIED' => '?',
53
-            'TZURL' => '?',
52
+			'LAST-MODIFIED' => '?',
53
+			'TZURL' => '?',
54 54
 
55
-            // At least 1 STANDARD or DAYLIGHT must appear.
56
-            //
57
-            // The validator is not specific yet to pick this up, so these
58
-            // rules are too loose.
59
-            'STANDARD' => '*',
60
-            'DAYLIGHT' => '*',
61
-        ];
62
-    }
55
+			// At least 1 STANDARD or DAYLIGHT must appear.
56
+			//
57
+			// The validator is not specific yet to pick this up, so these
58
+			// rules are too loose.
59
+			'STANDARD' => '*',
60
+			'DAYLIGHT' => '*',
61
+		];
62
+	}
63 63
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/Available.php 1 patch
Indentation   +95 added lines, -95 removed lines patch added patch discarded remove patch
@@ -16,108 +16,108 @@
 block discarded – undo
16 16
  */
17 17
 class Available extends VObject\Component
18 18
 {
19
-    /**
20
-     * Returns the 'effective start' and 'effective end' of this VAVAILABILITY
21
-     * component.
22
-     *
23
-     * We use the DTSTART and DTEND or DURATION to determine this.
24
-     *
25
-     * The returned value is an array containing DateTimeImmutable instances.
26
-     * If either the start or end is 'unbounded' its value will be null
27
-     * instead.
28
-     *
29
-     * @return array
30
-     */
31
-    public function getEffectiveStartEnd()
32
-    {
33
-        $effectiveStart = $this->DTSTART->getDateTime();
34
-        if (isset($this->DTEND)) {
35
-            $effectiveEnd = $this->DTEND->getDateTime();
36
-        } else {
37
-            $effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
38
-        }
19
+	/**
20
+	 * Returns the 'effective start' and 'effective end' of this VAVAILABILITY
21
+	 * component.
22
+	 *
23
+	 * We use the DTSTART and DTEND or DURATION to determine this.
24
+	 *
25
+	 * The returned value is an array containing DateTimeImmutable instances.
26
+	 * If either the start or end is 'unbounded' its value will be null
27
+	 * instead.
28
+	 *
29
+	 * @return array
30
+	 */
31
+	public function getEffectiveStartEnd()
32
+	{
33
+		$effectiveStart = $this->DTSTART->getDateTime();
34
+		if (isset($this->DTEND)) {
35
+			$effectiveEnd = $this->DTEND->getDateTime();
36
+		} else {
37
+			$effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
38
+		}
39 39
 
40
-        return [$effectiveStart, $effectiveEnd];
41
-    }
40
+		return [$effectiveStart, $effectiveEnd];
41
+	}
42 42
 
43
-    /**
44
-     * A simple list of validation rules.
45
-     *
46
-     * This is simply a list of properties, and how many times they either
47
-     * must or must not appear.
48
-     *
49
-     * Possible values per property:
50
-     *   * 0 - Must not appear.
51
-     *   * 1 - Must appear exactly once.
52
-     *   * + - Must appear at least once.
53
-     *   * * - Can appear any number of times.
54
-     *   * ? - May appear, but not more than once.
55
-     *
56
-     * @var array
57
-     */
58
-    public function getValidationRules()
59
-    {
60
-        return [
61
-            'UID' => 1,
62
-            'DTSTART' => 1,
63
-            'DTSTAMP' => 1,
43
+	/**
44
+	 * A simple list of validation rules.
45
+	 *
46
+	 * This is simply a list of properties, and how many times they either
47
+	 * must or must not appear.
48
+	 *
49
+	 * Possible values per property:
50
+	 *   * 0 - Must not appear.
51
+	 *   * 1 - Must appear exactly once.
52
+	 *   * + - Must appear at least once.
53
+	 *   * * - Can appear any number of times.
54
+	 *   * ? - May appear, but not more than once.
55
+	 *
56
+	 * @var array
57
+	 */
58
+	public function getValidationRules()
59
+	{
60
+		return [
61
+			'UID' => 1,
62
+			'DTSTART' => 1,
63
+			'DTSTAMP' => 1,
64 64
 
65
-            'DTEND' => '?',
66
-            'DURATION' => '?',
65
+			'DTEND' => '?',
66
+			'DURATION' => '?',
67 67
 
68
-            'CREATED' => '?',
69
-            'DESCRIPTION' => '?',
70
-            'LAST-MODIFIED' => '?',
71
-            'RECURRENCE-ID' => '?',
72
-            'RRULE' => '?',
73
-            'SUMMARY' => '?',
68
+			'CREATED' => '?',
69
+			'DESCRIPTION' => '?',
70
+			'LAST-MODIFIED' => '?',
71
+			'RECURRENCE-ID' => '?',
72
+			'RRULE' => '?',
73
+			'SUMMARY' => '?',
74 74
 
75
-            'CATEGORIES' => '*',
76
-            'COMMENT' => '*',
77
-            'CONTACT' => '*',
78
-            'EXDATE' => '*',
79
-            'RDATE' => '*',
75
+			'CATEGORIES' => '*',
76
+			'COMMENT' => '*',
77
+			'CONTACT' => '*',
78
+			'EXDATE' => '*',
79
+			'RDATE' => '*',
80 80
 
81
-            'AVAILABLE' => '*',
82
-        ];
83
-    }
81
+			'AVAILABLE' => '*',
82
+		];
83
+	}
84 84
 
85
-    /**
86
-     * Validates the node for correctness.
87
-     *
88
-     * The following options are supported:
89
-     *   Node::REPAIR - May attempt to automatically repair the problem.
90
-     *   Node::PROFILE_CARDDAV - Validate the vCard for CardDAV purposes.
91
-     *   Node::PROFILE_CALDAV - Validate the iCalendar for CalDAV purposes.
92
-     *
93
-     * This method returns an array with detected problems.
94
-     * Every element has the following properties:
95
-     *
96
-     *  * level - problem level.
97
-     *  * message - A human-readable string describing the issue.
98
-     *  * node - A reference to the problematic node.
99
-     *
100
-     * The level means:
101
-     *   1 - The issue was repaired (only happens if REPAIR was turned on).
102
-     *   2 - A warning.
103
-     *   3 - An error.
104
-     *
105
-     * @param int $options
106
-     *
107
-     * @return array
108
-     */
109
-    public function validate($options = 0)
110
-    {
111
-        $result = parent::validate($options);
85
+	/**
86
+	 * Validates the node for correctness.
87
+	 *
88
+	 * The following options are supported:
89
+	 *   Node::REPAIR - May attempt to automatically repair the problem.
90
+	 *   Node::PROFILE_CARDDAV - Validate the vCard for CardDAV purposes.
91
+	 *   Node::PROFILE_CALDAV - Validate the iCalendar for CalDAV purposes.
92
+	 *
93
+	 * This method returns an array with detected problems.
94
+	 * Every element has the following properties:
95
+	 *
96
+	 *  * level - problem level.
97
+	 *  * message - A human-readable string describing the issue.
98
+	 *  * node - A reference to the problematic node.
99
+	 *
100
+	 * The level means:
101
+	 *   1 - The issue was repaired (only happens if REPAIR was turned on).
102
+	 *   2 - A warning.
103
+	 *   3 - An error.
104
+	 *
105
+	 * @param int $options
106
+	 *
107
+	 * @return array
108
+	 */
109
+	public function validate($options = 0)
110
+	{
111
+		$result = parent::validate($options);
112 112
 
113
-        if (isset($this->DTEND) && isset($this->DURATION)) {
114
-            $result[] = [
115
-                'level' => 3,
116
-                'message' => 'DTEND and DURATION cannot both be present',
117
-                'node' => $this,
118
-            ];
119
-        }
113
+		if (isset($this->DTEND) && isset($this->DURATION)) {
114
+			$result[] = [
115
+				'level' => 3,
116
+				'message' => 'DTEND and DURATION cannot both be present',
117
+				'node' => $this,
118
+			];
119
+		}
120 120
 
121
-        return $result;
122
-    }
121
+		return $result;
122
+	}
123 123
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/UUIDUtil.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -15,52 +15,52 @@
 block discarded – undo
15 15
  */
16 16
 class UUIDUtil
17 17
 {
18
-    /**
19
-     * Returns a pseudo-random v4 UUID.
20
-     *
21
-     * This function is based on a comment by Andrew Moore on php.net
22
-     *
23
-     * @see http://www.php.net/manual/en/function.uniqid.php#94959
24
-     *
25
-     * @return string
26
-     */
27
-    public static function getUUID()
28
-    {
29
-        return sprintf(
30
-            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
18
+	/**
19
+	 * Returns a pseudo-random v4 UUID.
20
+	 *
21
+	 * This function is based on a comment by Andrew Moore on php.net
22
+	 *
23
+	 * @see http://www.php.net/manual/en/function.uniqid.php#94959
24
+	 *
25
+	 * @return string
26
+	 */
27
+	public static function getUUID()
28
+	{
29
+		return sprintf(
30
+			'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
31 31
 
32
-            // 32 bits for "time_low"
33
-            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
32
+			// 32 bits for "time_low"
33
+			mt_rand(0, 0xffff), mt_rand(0, 0xffff),
34 34
 
35
-            // 16 bits for "time_mid"
36
-            mt_rand(0, 0xffff),
35
+			// 16 bits for "time_mid"
36
+			mt_rand(0, 0xffff),
37 37
 
38
-            // 16 bits for "time_hi_and_version",
39
-            // four most significant bits holds version number 4
40
-            mt_rand(0, 0x0fff) | 0x4000,
38
+			// 16 bits for "time_hi_and_version",
39
+			// four most significant bits holds version number 4
40
+			mt_rand(0, 0x0fff) | 0x4000,
41 41
 
42
-            // 16 bits, 8 bits for "clk_seq_hi_res",
43
-            // 8 bits for "clk_seq_low",
44
-            // two most significant bits holds zero and one for variant DCE1.1
45
-            mt_rand(0, 0x3fff) | 0x8000,
42
+			// 16 bits, 8 bits for "clk_seq_hi_res",
43
+			// 8 bits for "clk_seq_low",
44
+			// two most significant bits holds zero and one for variant DCE1.1
45
+			mt_rand(0, 0x3fff) | 0x8000,
46 46
 
47
-            // 48 bits for "node"
48
-            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
49
-        );
50
-    }
47
+			// 48 bits for "node"
48
+			mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
49
+		);
50
+	}
51 51
 
52
-    /**
53
-     * Checks if a string is a valid UUID.
54
-     *
55
-     * @param string $uuid
56
-     *
57
-     * @return bool
58
-     */
59
-    public static function validateUUID($uuid)
60
-    {
61
-        return 0 !== preg_match(
62
-            '/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i',
63
-            $uuid
64
-        );
65
-    }
52
+	/**
53
+	 * Checks if a string is a valid UUID.
54
+	 *
55
+	 * @param string $uuid
56
+	 *
57
+	 * @return bool
58
+	 */
59
+	public static function validateUUID($uuid)
60
+	{
61
+		return 0 !== preg_match(
62
+			'/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i',
63
+			$uuid
64
+		);
65
+	}
66 66
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/VCardConverter.php 1 patch
Indentation   +403 added lines, -403 removed lines patch added patch discarded remove patch
@@ -11,411 +11,411 @@
 block discarded – undo
11 11
  */
12 12
 class VCardConverter
13 13
 {
14
-    /**
15
-     * Converts a vCard object to a new version.
16
-     *
17
-     * targetVersion must be one of:
18
-     *   Document::VCARD21
19
-     *   Document::VCARD30
20
-     *   Document::VCARD40
21
-     *
22
-     * Currently only 3.0 and 4.0 as input and output versions.
23
-     *
24
-     * 2.1 has some minor support for the input version, it's incomplete at the
25
-     * moment though.
26
-     *
27
-     * If input and output version are identical, a clone is returned.
28
-     *
29
-     * @param int $targetVersion
30
-     */
31
-    public function convert(Component\VCard $input, $targetVersion)
32
-    {
33
-        $inputVersion = $input->getDocumentType();
34
-        if ($inputVersion === $targetVersion) {
35
-            return clone $input;
36
-        }
37
-
38
-        if (!in_array($inputVersion, [Document::VCARD21, Document::VCARD30, Document::VCARD40])) {
39
-            throw new \InvalidArgumentException('Only vCard 2.1, 3.0 and 4.0 are supported for the input data');
40
-        }
41
-        if (!in_array($targetVersion, [Document::VCARD30, Document::VCARD40])) {
42
-            throw new \InvalidArgumentException('You can only use vCard 3.0 or 4.0 for the target version');
43
-        }
44
-
45
-        $newVersion = Document::VCARD40 === $targetVersion ? '4.0' : '3.0';
46
-
47
-        $output = new Component\VCard([
48
-            'VERSION' => $newVersion,
49
-        ]);
50
-
51
-        // We might have generated a default UID. Remove it!
52
-        unset($output->UID);
53
-
54
-        foreach ($input->children() as $property) {
55
-            $this->convertProperty($input, $output, $property, $targetVersion);
56
-        }
57
-
58
-        return $output;
59
-    }
60
-
61
-    /**
62
-     * Handles conversion of a single property.
63
-     *
64
-     * @param int $targetVersion
65
-     */
66
-    protected function convertProperty(Component\VCard $input, Component\VCard $output, Property $property, $targetVersion)
67
-    {
68
-        // Skipping these, those are automatically added.
69
-        if (in_array($property->name, ['VERSION', 'PRODID'])) {
70
-            return;
71
-        }
72
-
73
-        $parameters = $property->parameters();
74
-        $valueType = null;
75
-        if (isset($parameters['VALUE'])) {
76
-            $valueType = $parameters['VALUE']->getValue();
77
-            unset($parameters['VALUE']);
78
-        }
79
-        if (!$valueType) {
80
-            $valueType = $property->getValueType();
81
-        }
82
-        if (Document::VCARD30 !== $targetVersion && 'PHONE-NUMBER' === $valueType) {
83
-            $valueType = null;
84
-        }
85
-        $newProperty = $output->createProperty(
86
-            $property->name,
87
-            $property->getParts(),
88
-            [], // parameters will get added a bit later.
89
-            $valueType
90
-        );
91
-
92
-        if (Document::VCARD30 === $targetVersion) {
93
-            if ($property instanceof Property\Uri && in_array($property->name, ['PHOTO', 'LOGO', 'SOUND'])) {
94
-                $newProperty = $this->convertUriToBinary($output, $newProperty);
95
-            } elseif ($property instanceof Property\VCard\DateAndOrTime) {
96
-                // In vCard 4, the birth year may be optional. This is not the
97
-                // case for vCard 3. Apple has a workaround for this that
98
-                // allows applications that support Apple's extension still
99
-                // omit birthyears in vCard 3, but applications that do not
100
-                // support this, will just use a random birthyear. We're
101
-                // choosing 1604 for the birthyear, because that's what apple
102
-                // uses.
103
-                $parts = DateTimeParser::parseVCardDateTime($property->getValue());
104
-                if (is_null($parts['year'])) {
105
-                    $newValue = '1604-'.$parts['month'].'-'.$parts['date'];
106
-                    $newProperty->setValue($newValue);
107
-                    $newProperty['X-APPLE-OMIT-YEAR'] = '1604';
108
-                }
109
-
110
-                if ('ANNIVERSARY' == $newProperty->name) {
111
-                    // Microsoft non-standard anniversary
112
-                    $newProperty->name = 'X-ANNIVERSARY';
113
-
114
-                    // We also need to add a new apple property for the same
115
-                    // purpose. This apple property needs a 'label' in the same
116
-                    // group, so we first need to find a groupname that doesn't
117
-                    // exist yet.
118
-                    $x = 1;
119
-                    while ($output->select('ITEM'.$x.'.')) {
120
-                        ++$x;
121
-                    }
122
-                    $output->add('ITEM'.$x.'.X-ABDATE', $newProperty->getValue(), ['VALUE' => 'DATE-AND-OR-TIME']);
123
-                    $output->add('ITEM'.$x.'.X-ABLABEL', '_$!<Anniversary>!$_');
124
-                }
125
-            } elseif ('KIND' === $property->name) {
126
-                switch (strtolower($property->getValue())) {
127
-                    case 'org':
128
-                        // vCard 3.0 does not have an equivalent to KIND:ORG,
129
-                        // but apple has an extension that means the same
130
-                        // thing.
131
-                        $newProperty = $output->createProperty('X-ABSHOWAS', 'COMPANY');
132
-                        break;
133
-
134
-                    case 'individual':
135
-                        // Individual is implicit, so we skip it.
136
-                        return;
137
-
138
-                    case 'group':
139
-                        // OS X addressbook property
140
-                        $newProperty = $output->createProperty('X-ADDRESSBOOKSERVER-KIND', 'GROUP');
141
-                        break;
142
-                }
143
-            } elseif ('MEMBER' === $property->name) {
144
-                $newProperty = $output->createProperty('X-ADDRESSBOOKSERVER-MEMBER', $property->getValue());
145
-            }
146
-        } elseif (Document::VCARD40 === $targetVersion) {
147
-            // These properties were removed in vCard 4.0
148
-            if (in_array($property->name, ['NAME', 'MAILER', 'LABEL', 'CLASS'])) {
149
-                return;
150
-            }
151
-
152
-            if ($property instanceof Property\Binary) {
153
-                $newProperty = $this->convertBinaryToUri($output, $newProperty, $parameters);
154
-            } elseif ($property instanceof Property\VCard\DateAndOrTime && isset($parameters['X-APPLE-OMIT-YEAR'])) {
155
-                // If a property such as BDAY contained 'X-APPLE-OMIT-YEAR',
156
-                // then we're stripping the year from the vcard 4 value.
157
-                $parts = DateTimeParser::parseVCardDateTime($property->getValue());
158
-                if ($parts['year'] === $property['X-APPLE-OMIT-YEAR']->getValue()) {
159
-                    $newValue = '--'.$parts['month'].'-'.$parts['date'];
160
-                    $newProperty->setValue($newValue);
161
-                }
162
-
163
-                // Regardless if the year matched or not, we do need to strip
164
-                // X-APPLE-OMIT-YEAR.
165
-                unset($parameters['X-APPLE-OMIT-YEAR']);
166
-            }
167
-            switch ($property->name) {
168
-                case 'X-ABSHOWAS':
169
-                    if ('COMPANY' === strtoupper($property->getValue())) {
170
-                        $newProperty = $output->createProperty('KIND', 'ORG');
171
-                    }
172
-                    break;
173
-                case 'X-ADDRESSBOOKSERVER-KIND':
174
-                    if ('GROUP' === strtoupper($property->getValue())) {
175
-                        $newProperty = $output->createProperty('KIND', 'GROUP');
176
-                    }
177
-                    break;
178
-                case 'X-ADDRESSBOOKSERVER-MEMBER':
179
-                    $newProperty = $output->createProperty('MEMBER', $property->getValue());
180
-                    break;
181
-                case 'X-ANNIVERSARY':
182
-                    $newProperty->name = 'ANNIVERSARY';
183
-                    // If we already have an anniversary property with the same
184
-                    // value, ignore.
185
-                    foreach ($output->select('ANNIVERSARY') as $anniversary) {
186
-                        if ($anniversary->getValue() === $newProperty->getValue()) {
187
-                            return;
188
-                        }
189
-                    }
190
-                    break;
191
-                case 'X-ABDATE':
192
-                    // Find out what the label was, if it exists.
193
-                    if (!$property->group) {
194
-                        break;
195
-                    }
196
-                    $label = $input->{$property->group.'.X-ABLABEL'};
197
-
198
-                    // We only support converting anniversaries.
199
-                    if (!$label || '_$!<Anniversary>!$_' !== $label->getValue()) {
200
-                        break;
201
-                    }
202
-
203
-                    // If we already have an anniversary property with the same
204
-                    // value, ignore.
205
-                    foreach ($output->select('ANNIVERSARY') as $anniversary) {
206
-                        if ($anniversary->getValue() === $newProperty->getValue()) {
207
-                            return;
208
-                        }
209
-                    }
210
-                    $newProperty->name = 'ANNIVERSARY';
211
-                    break;
212
-                // Apple's per-property label system.
213
-                case 'X-ABLABEL':
214
-                    if ('_$!<Anniversary>!$_' === $newProperty->getValue()) {
215
-                        // We can safely remove these, as they are converted to
216
-                        // ANNIVERSARY properties.
217
-                        return;
218
-                    }
219
-                    break;
220
-            }
221
-        }
222
-
223
-        // set property group
224
-        $newProperty->group = $property->group;
225
-
226
-        if (Document::VCARD40 === $targetVersion) {
227
-            $this->convertParameters40($newProperty, $parameters);
228
-        } else {
229
-            $this->convertParameters30($newProperty, $parameters);
230
-        }
231
-
232
-        // Lastly, we need to see if there's a need for a VALUE parameter.
233
-        //
234
-        // We can do that by instantiating a empty property with that name, and
235
-        // seeing if the default valueType is identical to the current one.
236
-        $tempProperty = $output->createProperty($newProperty->name);
237
-        if ($tempProperty->getValueType() !== $newProperty->getValueType()) {
238
-            $newProperty['VALUE'] = $newProperty->getValueType();
239
-        }
240
-
241
-        $output->add($newProperty);
242
-    }
243
-
244
-    /**
245
-     * Converts a BINARY property to a URI property.
246
-     *
247
-     * vCard 4.0 no longer supports BINARY properties.
248
-     *
249
-     * @param Property\Uri $property the input property
250
-     * @param $parameters list of parameters that will eventually be added to
251
-     *                    the new property
252
-     *
253
-     * @return Property\Uri
254
-     */
255
-    protected function convertBinaryToUri(Component\VCard $output, Property\Binary $newProperty, array &$parameters)
256
-    {
257
-        $value = $newProperty->getValue();
258
-        $newProperty = $output->createProperty(
259
-            $newProperty->name,
260
-            null, // no value
261
-            [], // no parameters yet
262
-            'URI' // Forcing the BINARY type
263
-        );
264
-
265
-        $mimeType = 'application/octet-stream';
266
-
267
-        // See if we can find a better mimetype.
268
-        if (isset($parameters['TYPE'])) {
269
-            $newTypes = [];
270
-            foreach ($parameters['TYPE']->getParts() as $typePart) {
271
-                if (in_array(
272
-                    strtoupper($typePart),
273
-                    ['JPEG', 'PNG', 'GIF']
274
-                )) {
275
-                    $mimeType = 'image/'.strtolower($typePart);
276
-                } else {
277
-                    $newTypes[] = $typePart;
278
-                }
279
-            }
280
-
281
-            // If there were any parameters we're not converting to a
282
-            // mime-type, we need to keep them.
283
-            if ($newTypes) {
284
-                $parameters['TYPE']->setParts($newTypes);
285
-            } else {
286
-                unset($parameters['TYPE']);
287
-            }
288
-        }
289
-
290
-        $newProperty->setValue('data:'.$mimeType.';base64,'.base64_encode($value));
291
-
292
-        return $newProperty;
293
-    }
294
-
295
-    /**
296
-     * Converts a URI property to a BINARY property.
297
-     *
298
-     * In vCard 4.0 attachments are encoded as data: uri. Even though these may
299
-     * be valid in vCard 3.0 as well, we should convert those to BINARY if
300
-     * possible, to improve compatibility.
301
-     *
302
-     * @param Property\Uri $property the input property
303
-     *
304
-     * @return Property\Binary|null
305
-     */
306
-    protected function convertUriToBinary(Component\VCard $output, Property\Uri $newProperty)
307
-    {
308
-        $value = $newProperty->getValue();
309
-
310
-        // Only converting data: uris
311
-        if ('data:' !== substr($value, 0, 5)) {
312
-            return $newProperty;
313
-        }
314
-
315
-        $newProperty = $output->createProperty(
316
-            $newProperty->name,
317
-            null, // no value
318
-            [], // no parameters yet
319
-            'BINARY'
320
-        );
321
-
322
-        $mimeType = substr($value, 5, strpos($value, ',') - 5);
323
-        if (strpos($mimeType, ';')) {
324
-            $mimeType = substr($mimeType, 0, strpos($mimeType, ';'));
325
-            $newProperty->setValue(base64_decode(substr($value, strpos($value, ',') + 1)));
326
-        } else {
327
-            $newProperty->setValue(substr($value, strpos($value, ',') + 1));
328
-        }
329
-        unset($value);
330
-
331
-        $newProperty['ENCODING'] = 'b';
332
-        switch ($mimeType) {
333
-            case 'image/jpeg':
334
-                $newProperty['TYPE'] = 'JPEG';
335
-                break;
336
-            case 'image/png':
337
-                $newProperty['TYPE'] = 'PNG';
338
-                break;
339
-            case 'image/gif':
340
-                $newProperty['TYPE'] = 'GIF';
341
-                break;
342
-        }
343
-
344
-        return $newProperty;
345
-    }
346
-
347
-    /**
348
-     * Adds parameters to a new property for vCard 4.0.
349
-     */
350
-    protected function convertParameters40(Property $newProperty, array $parameters)
351
-    {
352
-        // Adding all parameters.
353
-        foreach ($parameters as $param) {
354
-            // vCard 2.1 allowed parameters with no name
355
-            if ($param->noName) {
356
-                $param->noName = false;
357
-            }
358
-
359
-            switch ($param->name) {
360
-                // We need to see if there's any TYPE=PREF, because in vCard 4
361
-                // that's now PREF=1.
362
-                case 'TYPE':
363
-                    foreach ($param->getParts() as $paramPart) {
364
-                        if ('PREF' === strtoupper($paramPart)) {
365
-                            $newProperty->add('PREF', '1');
366
-                        } else {
367
-                            $newProperty->add($param->name, $paramPart);
368
-                        }
369
-                    }
370
-                    break;
371
-                // These no longer exist in vCard 4
372
-                case 'ENCODING':
373
-                case 'CHARSET':
374
-                    break;
375
-
376
-                default:
377
-                    $newProperty->add($param->name, $param->getParts());
378
-                    break;
379
-            }
380
-        }
381
-    }
382
-
383
-    /**
384
-     * Adds parameters to a new property for vCard 3.0.
385
-     */
386
-    protected function convertParameters30(Property $newProperty, array $parameters)
387
-    {
388
-        // Adding all parameters.
389
-        foreach ($parameters as $param) {
390
-            // vCard 2.1 allowed parameters with no name
391
-            if ($param->noName) {
392
-                $param->noName = false;
393
-            }
394
-
395
-            switch ($param->name) {
396
-                case 'ENCODING':
397
-                    // This value only existed in vCard 2.1, and should be
398
-                    // removed for anything else.
399
-                    if ('QUOTED-PRINTABLE' !== strtoupper($param->getValue())) {
400
-                        $newProperty->add($param->name, $param->getParts());
401
-                    }
402
-                    break;
403
-
404
-                /*
14
+	/**
15
+	 * Converts a vCard object to a new version.
16
+	 *
17
+	 * targetVersion must be one of:
18
+	 *   Document::VCARD21
19
+	 *   Document::VCARD30
20
+	 *   Document::VCARD40
21
+	 *
22
+	 * Currently only 3.0 and 4.0 as input and output versions.
23
+	 *
24
+	 * 2.1 has some minor support for the input version, it's incomplete at the
25
+	 * moment though.
26
+	 *
27
+	 * If input and output version are identical, a clone is returned.
28
+	 *
29
+	 * @param int $targetVersion
30
+	 */
31
+	public function convert(Component\VCard $input, $targetVersion)
32
+	{
33
+		$inputVersion = $input->getDocumentType();
34
+		if ($inputVersion === $targetVersion) {
35
+			return clone $input;
36
+		}
37
+
38
+		if (!in_array($inputVersion, [Document::VCARD21, Document::VCARD30, Document::VCARD40])) {
39
+			throw new \InvalidArgumentException('Only vCard 2.1, 3.0 and 4.0 are supported for the input data');
40
+		}
41
+		if (!in_array($targetVersion, [Document::VCARD30, Document::VCARD40])) {
42
+			throw new \InvalidArgumentException('You can only use vCard 3.0 or 4.0 for the target version');
43
+		}
44
+
45
+		$newVersion = Document::VCARD40 === $targetVersion ? '4.0' : '3.0';
46
+
47
+		$output = new Component\VCard([
48
+			'VERSION' => $newVersion,
49
+		]);
50
+
51
+		// We might have generated a default UID. Remove it!
52
+		unset($output->UID);
53
+
54
+		foreach ($input->children() as $property) {
55
+			$this->convertProperty($input, $output, $property, $targetVersion);
56
+		}
57
+
58
+		return $output;
59
+	}
60
+
61
+	/**
62
+	 * Handles conversion of a single property.
63
+	 *
64
+	 * @param int $targetVersion
65
+	 */
66
+	protected function convertProperty(Component\VCard $input, Component\VCard $output, Property $property, $targetVersion)
67
+	{
68
+		// Skipping these, those are automatically added.
69
+		if (in_array($property->name, ['VERSION', 'PRODID'])) {
70
+			return;
71
+		}
72
+
73
+		$parameters = $property->parameters();
74
+		$valueType = null;
75
+		if (isset($parameters['VALUE'])) {
76
+			$valueType = $parameters['VALUE']->getValue();
77
+			unset($parameters['VALUE']);
78
+		}
79
+		if (!$valueType) {
80
+			$valueType = $property->getValueType();
81
+		}
82
+		if (Document::VCARD30 !== $targetVersion && 'PHONE-NUMBER' === $valueType) {
83
+			$valueType = null;
84
+		}
85
+		$newProperty = $output->createProperty(
86
+			$property->name,
87
+			$property->getParts(),
88
+			[], // parameters will get added a bit later.
89
+			$valueType
90
+		);
91
+
92
+		if (Document::VCARD30 === $targetVersion) {
93
+			if ($property instanceof Property\Uri && in_array($property->name, ['PHOTO', 'LOGO', 'SOUND'])) {
94
+				$newProperty = $this->convertUriToBinary($output, $newProperty);
95
+			} elseif ($property instanceof Property\VCard\DateAndOrTime) {
96
+				// In vCard 4, the birth year may be optional. This is not the
97
+				// case for vCard 3. Apple has a workaround for this that
98
+				// allows applications that support Apple's extension still
99
+				// omit birthyears in vCard 3, but applications that do not
100
+				// support this, will just use a random birthyear. We're
101
+				// choosing 1604 for the birthyear, because that's what apple
102
+				// uses.
103
+				$parts = DateTimeParser::parseVCardDateTime($property->getValue());
104
+				if (is_null($parts['year'])) {
105
+					$newValue = '1604-'.$parts['month'].'-'.$parts['date'];
106
+					$newProperty->setValue($newValue);
107
+					$newProperty['X-APPLE-OMIT-YEAR'] = '1604';
108
+				}
109
+
110
+				if ('ANNIVERSARY' == $newProperty->name) {
111
+					// Microsoft non-standard anniversary
112
+					$newProperty->name = 'X-ANNIVERSARY';
113
+
114
+					// We also need to add a new apple property for the same
115
+					// purpose. This apple property needs a 'label' in the same
116
+					// group, so we first need to find a groupname that doesn't
117
+					// exist yet.
118
+					$x = 1;
119
+					while ($output->select('ITEM'.$x.'.')) {
120
+						++$x;
121
+					}
122
+					$output->add('ITEM'.$x.'.X-ABDATE', $newProperty->getValue(), ['VALUE' => 'DATE-AND-OR-TIME']);
123
+					$output->add('ITEM'.$x.'.X-ABLABEL', '_$!<Anniversary>!$_');
124
+				}
125
+			} elseif ('KIND' === $property->name) {
126
+				switch (strtolower($property->getValue())) {
127
+					case 'org':
128
+						// vCard 3.0 does not have an equivalent to KIND:ORG,
129
+						// but apple has an extension that means the same
130
+						// thing.
131
+						$newProperty = $output->createProperty('X-ABSHOWAS', 'COMPANY');
132
+						break;
133
+
134
+					case 'individual':
135
+						// Individual is implicit, so we skip it.
136
+						return;
137
+
138
+					case 'group':
139
+						// OS X addressbook property
140
+						$newProperty = $output->createProperty('X-ADDRESSBOOKSERVER-KIND', 'GROUP');
141
+						break;
142
+				}
143
+			} elseif ('MEMBER' === $property->name) {
144
+				$newProperty = $output->createProperty('X-ADDRESSBOOKSERVER-MEMBER', $property->getValue());
145
+			}
146
+		} elseif (Document::VCARD40 === $targetVersion) {
147
+			// These properties were removed in vCard 4.0
148
+			if (in_array($property->name, ['NAME', 'MAILER', 'LABEL', 'CLASS'])) {
149
+				return;
150
+			}
151
+
152
+			if ($property instanceof Property\Binary) {
153
+				$newProperty = $this->convertBinaryToUri($output, $newProperty, $parameters);
154
+			} elseif ($property instanceof Property\VCard\DateAndOrTime && isset($parameters['X-APPLE-OMIT-YEAR'])) {
155
+				// If a property such as BDAY contained 'X-APPLE-OMIT-YEAR',
156
+				// then we're stripping the year from the vcard 4 value.
157
+				$parts = DateTimeParser::parseVCardDateTime($property->getValue());
158
+				if ($parts['year'] === $property['X-APPLE-OMIT-YEAR']->getValue()) {
159
+					$newValue = '--'.$parts['month'].'-'.$parts['date'];
160
+					$newProperty->setValue($newValue);
161
+				}
162
+
163
+				// Regardless if the year matched or not, we do need to strip
164
+				// X-APPLE-OMIT-YEAR.
165
+				unset($parameters['X-APPLE-OMIT-YEAR']);
166
+			}
167
+			switch ($property->name) {
168
+				case 'X-ABSHOWAS':
169
+					if ('COMPANY' === strtoupper($property->getValue())) {
170
+						$newProperty = $output->createProperty('KIND', 'ORG');
171
+					}
172
+					break;
173
+				case 'X-ADDRESSBOOKSERVER-KIND':
174
+					if ('GROUP' === strtoupper($property->getValue())) {
175
+						$newProperty = $output->createProperty('KIND', 'GROUP');
176
+					}
177
+					break;
178
+				case 'X-ADDRESSBOOKSERVER-MEMBER':
179
+					$newProperty = $output->createProperty('MEMBER', $property->getValue());
180
+					break;
181
+				case 'X-ANNIVERSARY':
182
+					$newProperty->name = 'ANNIVERSARY';
183
+					// If we already have an anniversary property with the same
184
+					// value, ignore.
185
+					foreach ($output->select('ANNIVERSARY') as $anniversary) {
186
+						if ($anniversary->getValue() === $newProperty->getValue()) {
187
+							return;
188
+						}
189
+					}
190
+					break;
191
+				case 'X-ABDATE':
192
+					// Find out what the label was, if it exists.
193
+					if (!$property->group) {
194
+						break;
195
+					}
196
+					$label = $input->{$property->group.'.X-ABLABEL'};
197
+
198
+					// We only support converting anniversaries.
199
+					if (!$label || '_$!<Anniversary>!$_' !== $label->getValue()) {
200
+						break;
201
+					}
202
+
203
+					// If we already have an anniversary property with the same
204
+					// value, ignore.
205
+					foreach ($output->select('ANNIVERSARY') as $anniversary) {
206
+						if ($anniversary->getValue() === $newProperty->getValue()) {
207
+							return;
208
+						}
209
+					}
210
+					$newProperty->name = 'ANNIVERSARY';
211
+					break;
212
+				// Apple's per-property label system.
213
+				case 'X-ABLABEL':
214
+					if ('_$!<Anniversary>!$_' === $newProperty->getValue()) {
215
+						// We can safely remove these, as they are converted to
216
+						// ANNIVERSARY properties.
217
+						return;
218
+					}
219
+					break;
220
+			}
221
+		}
222
+
223
+		// set property group
224
+		$newProperty->group = $property->group;
225
+
226
+		if (Document::VCARD40 === $targetVersion) {
227
+			$this->convertParameters40($newProperty, $parameters);
228
+		} else {
229
+			$this->convertParameters30($newProperty, $parameters);
230
+		}
231
+
232
+		// Lastly, we need to see if there's a need for a VALUE parameter.
233
+		//
234
+		// We can do that by instantiating a empty property with that name, and
235
+		// seeing if the default valueType is identical to the current one.
236
+		$tempProperty = $output->createProperty($newProperty->name);
237
+		if ($tempProperty->getValueType() !== $newProperty->getValueType()) {
238
+			$newProperty['VALUE'] = $newProperty->getValueType();
239
+		}
240
+
241
+		$output->add($newProperty);
242
+	}
243
+
244
+	/**
245
+	 * Converts a BINARY property to a URI property.
246
+	 *
247
+	 * vCard 4.0 no longer supports BINARY properties.
248
+	 *
249
+	 * @param Property\Uri $property the input property
250
+	 * @param $parameters list of parameters that will eventually be added to
251
+	 *                    the new property
252
+	 *
253
+	 * @return Property\Uri
254
+	 */
255
+	protected function convertBinaryToUri(Component\VCard $output, Property\Binary $newProperty, array &$parameters)
256
+	{
257
+		$value = $newProperty->getValue();
258
+		$newProperty = $output->createProperty(
259
+			$newProperty->name,
260
+			null, // no value
261
+			[], // no parameters yet
262
+			'URI' // Forcing the BINARY type
263
+		);
264
+
265
+		$mimeType = 'application/octet-stream';
266
+
267
+		// See if we can find a better mimetype.
268
+		if (isset($parameters['TYPE'])) {
269
+			$newTypes = [];
270
+			foreach ($parameters['TYPE']->getParts() as $typePart) {
271
+				if (in_array(
272
+					strtoupper($typePart),
273
+					['JPEG', 'PNG', 'GIF']
274
+				)) {
275
+					$mimeType = 'image/'.strtolower($typePart);
276
+				} else {
277
+					$newTypes[] = $typePart;
278
+				}
279
+			}
280
+
281
+			// If there were any parameters we're not converting to a
282
+			// mime-type, we need to keep them.
283
+			if ($newTypes) {
284
+				$parameters['TYPE']->setParts($newTypes);
285
+			} else {
286
+				unset($parameters['TYPE']);
287
+			}
288
+		}
289
+
290
+		$newProperty->setValue('data:'.$mimeType.';base64,'.base64_encode($value));
291
+
292
+		return $newProperty;
293
+	}
294
+
295
+	/**
296
+	 * Converts a URI property to a BINARY property.
297
+	 *
298
+	 * In vCard 4.0 attachments are encoded as data: uri. Even though these may
299
+	 * be valid in vCard 3.0 as well, we should convert those to BINARY if
300
+	 * possible, to improve compatibility.
301
+	 *
302
+	 * @param Property\Uri $property the input property
303
+	 *
304
+	 * @return Property\Binary|null
305
+	 */
306
+	protected function convertUriToBinary(Component\VCard $output, Property\Uri $newProperty)
307
+	{
308
+		$value = $newProperty->getValue();
309
+
310
+		// Only converting data: uris
311
+		if ('data:' !== substr($value, 0, 5)) {
312
+			return $newProperty;
313
+		}
314
+
315
+		$newProperty = $output->createProperty(
316
+			$newProperty->name,
317
+			null, // no value
318
+			[], // no parameters yet
319
+			'BINARY'
320
+		);
321
+
322
+		$mimeType = substr($value, 5, strpos($value, ',') - 5);
323
+		if (strpos($mimeType, ';')) {
324
+			$mimeType = substr($mimeType, 0, strpos($mimeType, ';'));
325
+			$newProperty->setValue(base64_decode(substr($value, strpos($value, ',') + 1)));
326
+		} else {
327
+			$newProperty->setValue(substr($value, strpos($value, ',') + 1));
328
+		}
329
+		unset($value);
330
+
331
+		$newProperty['ENCODING'] = 'b';
332
+		switch ($mimeType) {
333
+			case 'image/jpeg':
334
+				$newProperty['TYPE'] = 'JPEG';
335
+				break;
336
+			case 'image/png':
337
+				$newProperty['TYPE'] = 'PNG';
338
+				break;
339
+			case 'image/gif':
340
+				$newProperty['TYPE'] = 'GIF';
341
+				break;
342
+		}
343
+
344
+		return $newProperty;
345
+	}
346
+
347
+	/**
348
+	 * Adds parameters to a new property for vCard 4.0.
349
+	 */
350
+	protected function convertParameters40(Property $newProperty, array $parameters)
351
+	{
352
+		// Adding all parameters.
353
+		foreach ($parameters as $param) {
354
+			// vCard 2.1 allowed parameters with no name
355
+			if ($param->noName) {
356
+				$param->noName = false;
357
+			}
358
+
359
+			switch ($param->name) {
360
+				// We need to see if there's any TYPE=PREF, because in vCard 4
361
+				// that's now PREF=1.
362
+				case 'TYPE':
363
+					foreach ($param->getParts() as $paramPart) {
364
+						if ('PREF' === strtoupper($paramPart)) {
365
+							$newProperty->add('PREF', '1');
366
+						} else {
367
+							$newProperty->add($param->name, $paramPart);
368
+						}
369
+					}
370
+					break;
371
+				// These no longer exist in vCard 4
372
+				case 'ENCODING':
373
+				case 'CHARSET':
374
+					break;
375
+
376
+				default:
377
+					$newProperty->add($param->name, $param->getParts());
378
+					break;
379
+			}
380
+		}
381
+	}
382
+
383
+	/**
384
+	 * Adds parameters to a new property for vCard 3.0.
385
+	 */
386
+	protected function convertParameters30(Property $newProperty, array $parameters)
387
+	{
388
+		// Adding all parameters.
389
+		foreach ($parameters as $param) {
390
+			// vCard 2.1 allowed parameters with no name
391
+			if ($param->noName) {
392
+				$param->noName = false;
393
+			}
394
+
395
+			switch ($param->name) {
396
+				case 'ENCODING':
397
+					// This value only existed in vCard 2.1, and should be
398
+					// removed for anything else.
399
+					if ('QUOTED-PRINTABLE' !== strtoupper($param->getValue())) {
400
+						$newProperty->add($param->name, $param->getParts());
401
+					}
402
+					break;
403
+
404
+				/*
405 405
                  * Converting PREF=1 to TYPE=PREF.
406 406
                  *
407 407
                  * Any other PREF numbers we'll drop.
408 408
                  */
409
-                case 'PREF':
410
-                    if ('1' == $param->getValue()) {
411
-                        $newProperty->add('TYPE', 'PREF');
412
-                    }
413
-                    break;
414
-
415
-                default:
416
-                    $newProperty->add($param->name, $param->getParts());
417
-                    break;
418
-            }
419
-        }
420
-    }
409
+				case 'PREF':
410
+					if ('1' == $param->getValue()) {
411
+						$newProperty->add('TYPE', 'PREF');
412
+					}
413
+					break;
414
+
415
+				default:
416
+					$newProperty->add($param->name, $param->getParts());
417
+					break;
418
+			}
419
+		}
420
+	}
421 421
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/uri/lib/functions.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@  discard block
 block discarded – undo
31 31
     }
32 32
 
33 33
     $base = parse($basePath);
34
-    $pick = function ($part) use ($base, $delta) {
34
+    $pick = function($part) use ($base, $delta) {
35 35
         if ($delta[$part]) {
36 36
             return $delta[$part];
37 37
         } elseif ($base[$part]) {
@@ -187,7 +187,7 @@  discard block
 block discarded – undo
187 187
     // uriencode them first.
188 188
     $uri = preg_replace_callback(
189 189
         '/[^[:ascii:]]/u',
190
-        function ($matches) {
190
+        function($matches) {
191 191
             return rawurlencode($matches[0]);
192 192
         },
193 193
         $uri
@@ -316,7 +316,7 @@  discard block
 block discarded – undo
316 316
     // uriencode them first.
317 317
     $uri = preg_replace_callback(
318 318
         '/[^[:ascii:]]/u',
319
-        function ($matches) {
319
+        function($matches) {
320 320
             return rawurlencode($matches[0]);
321 321
         },
322 322
         $uri
Please login to merge, or discard this patch.
Indentation   +260 added lines, -260 removed lines patch added patch discarded remove patch
@@ -22,80 +22,80 @@  discard block
 block discarded – undo
22 22
  */
23 23
 function resolve(string $basePath, string $newPath): string
24 24
 {
25
-    $delta = parse($newPath);
26
-
27
-    // If the new path defines a scheme, it's absolute and we can just return
28
-    // that.
29
-    if ($delta['scheme']) {
30
-        return build($delta);
31
-    }
32
-
33
-    $base = parse($basePath);
34
-    $pick = function ($part) use ($base, $delta) {
35
-        if ($delta[$part]) {
36
-            return $delta[$part];
37
-        } elseif ($base[$part]) {
38
-            return $base[$part];
39
-        }
40
-
41
-        return null;
42
-    };
43
-
44
-    $newParts = [];
45
-
46
-    $newParts['scheme'] = $pick('scheme');
47
-    $newParts['host'] = $pick('host');
48
-    $newParts['port'] = $pick('port');
49
-
50
-    $path = '';
51
-    if (is_string($delta['path']) and strlen($delta['path']) > 0) {
52
-        // If the path starts with a slash
53
-        if ('/' === $delta['path'][0]) {
54
-            $path = $delta['path'];
55
-        } else {
56
-            // Removing last component from base path.
57
-            $path = $base['path'];
58
-            $length = strrpos((string) $path, '/');
59
-            if (false !== $length) {
60
-                $path = substr($path, 0, $length);
61
-            }
62
-            $path .= '/'.$delta['path'];
63
-        }
64
-    } else {
65
-        $path = $base['path'] ?: '/';
66
-    }
67
-    // Removing .. and .
68
-    $pathParts = explode('/', $path);
69
-    $newPathParts = [];
70
-    foreach ($pathParts as $pathPart) {
71
-        switch ($pathPart) {
72
-            //case '' :
73
-            case '.':
74
-                break;
75
-            case '..':
76
-                array_pop($newPathParts);
77
-                break;
78
-            default:
79
-                $newPathParts[] = $pathPart;
80
-                break;
81
-        }
82
-    }
83
-
84
-    $path = implode('/', $newPathParts);
85
-
86
-    // If the source url ended with a /, we want to preserve that.
87
-    $newParts['path'] = 0 === strpos($path, '/') ? $path : '/'.$path;
88
-    if ($delta['query']) {
89
-        $newParts['query'] = $delta['query'];
90
-    } elseif (!empty($base['query']) && empty($delta['host']) && empty($delta['path'])) {
91
-        // Keep the old query if host and path didn't change
92
-        $newParts['query'] = $base['query'];
93
-    }
94
-    if ($delta['fragment']) {
95
-        $newParts['fragment'] = $delta['fragment'];
96
-    }
97
-
98
-    return build($newParts);
25
+	$delta = parse($newPath);
26
+
27
+	// If the new path defines a scheme, it's absolute and we can just return
28
+	// that.
29
+	if ($delta['scheme']) {
30
+		return build($delta);
31
+	}
32
+
33
+	$base = parse($basePath);
34
+	$pick = function ($part) use ($base, $delta) {
35
+		if ($delta[$part]) {
36
+			return $delta[$part];
37
+		} elseif ($base[$part]) {
38
+			return $base[$part];
39
+		}
40
+
41
+		return null;
42
+	};
43
+
44
+	$newParts = [];
45
+
46
+	$newParts['scheme'] = $pick('scheme');
47
+	$newParts['host'] = $pick('host');
48
+	$newParts['port'] = $pick('port');
49
+
50
+	$path = '';
51
+	if (is_string($delta['path']) and strlen($delta['path']) > 0) {
52
+		// If the path starts with a slash
53
+		if ('/' === $delta['path'][0]) {
54
+			$path = $delta['path'];
55
+		} else {
56
+			// Removing last component from base path.
57
+			$path = $base['path'];
58
+			$length = strrpos((string) $path, '/');
59
+			if (false !== $length) {
60
+				$path = substr($path, 0, $length);
61
+			}
62
+			$path .= '/'.$delta['path'];
63
+		}
64
+	} else {
65
+		$path = $base['path'] ?: '/';
66
+	}
67
+	// Removing .. and .
68
+	$pathParts = explode('/', $path);
69
+	$newPathParts = [];
70
+	foreach ($pathParts as $pathPart) {
71
+		switch ($pathPart) {
72
+			//case '' :
73
+			case '.':
74
+				break;
75
+			case '..':
76
+				array_pop($newPathParts);
77
+				break;
78
+			default:
79
+				$newPathParts[] = $pathPart;
80
+				break;
81
+		}
82
+	}
83
+
84
+	$path = implode('/', $newPathParts);
85
+
86
+	// If the source url ended with a /, we want to preserve that.
87
+	$newParts['path'] = 0 === strpos($path, '/') ? $path : '/'.$path;
88
+	if ($delta['query']) {
89
+		$newParts['query'] = $delta['query'];
90
+	} elseif (!empty($base['query']) && empty($delta['host']) && empty($delta['path'])) {
91
+		// Keep the old query if host and path didn't change
92
+		$newParts['query'] = $base['query'];
93
+	}
94
+	if ($delta['fragment']) {
95
+		$newParts['fragment'] = $delta['fragment'];
96
+	}
97
+
98
+	return build($newParts);
99 99
 }
100 100
 
101 101
 /**
@@ -111,57 +111,57 @@  discard block
 block discarded – undo
111 111
  */
112 112
 function normalize(string $uri): string
113 113
 {
114
-    $parts = parse($uri);
115
-
116
-    if (!empty($parts['path'])) {
117
-        $pathParts = explode('/', ltrim($parts['path'], '/'));
118
-        $newPathParts = [];
119
-        foreach ($pathParts as $pathPart) {
120
-            switch ($pathPart) {
121
-                case '.':
122
-                    // skip
123
-                    break;
124
-                case '..':
125
-                    // One level up in the hierarchy
126
-                    array_pop($newPathParts);
127
-                    break;
128
-                default:
129
-                    // Ensuring that everything is correctly percent-encoded.
130
-                    $newPathParts[] = rawurlencode(rawurldecode($pathPart));
131
-                    break;
132
-            }
133
-        }
134
-        $parts['path'] = '/'.implode('/', $newPathParts);
135
-    }
136
-
137
-    if ($parts['scheme']) {
138
-        $parts['scheme'] = strtolower($parts['scheme']);
139
-        $defaultPorts = [
140
-            'http' => '80',
141
-            'https' => '443',
142
-        ];
143
-
144
-        if (!empty($parts['port']) && isset($defaultPorts[$parts['scheme']]) && $defaultPorts[$parts['scheme']] == $parts['port']) {
145
-            // Removing default ports.
146
-            unset($parts['port']);
147
-        }
148
-        // A few HTTP specific rules.
149
-        switch ($parts['scheme']) {
150
-            case 'http':
151
-            case 'https':
152
-                if (empty($parts['path'])) {
153
-                    // An empty path is equivalent to / in http.
154
-                    $parts['path'] = '/';
155
-                }
156
-                break;
157
-        }
158
-    }
159
-
160
-    if ($parts['host']) {
161
-        $parts['host'] = strtolower($parts['host']);
162
-    }
163
-
164
-    return build($parts);
114
+	$parts = parse($uri);
115
+
116
+	if (!empty($parts['path'])) {
117
+		$pathParts = explode('/', ltrim($parts['path'], '/'));
118
+		$newPathParts = [];
119
+		foreach ($pathParts as $pathPart) {
120
+			switch ($pathPart) {
121
+				case '.':
122
+					// skip
123
+					break;
124
+				case '..':
125
+					// One level up in the hierarchy
126
+					array_pop($newPathParts);
127
+					break;
128
+				default:
129
+					// Ensuring that everything is correctly percent-encoded.
130
+					$newPathParts[] = rawurlencode(rawurldecode($pathPart));
131
+					break;
132
+			}
133
+		}
134
+		$parts['path'] = '/'.implode('/', $newPathParts);
135
+	}
136
+
137
+	if ($parts['scheme']) {
138
+		$parts['scheme'] = strtolower($parts['scheme']);
139
+		$defaultPorts = [
140
+			'http' => '80',
141
+			'https' => '443',
142
+		];
143
+
144
+		if (!empty($parts['port']) && isset($defaultPorts[$parts['scheme']]) && $defaultPorts[$parts['scheme']] == $parts['port']) {
145
+			// Removing default ports.
146
+			unset($parts['port']);
147
+		}
148
+		// A few HTTP specific rules.
149
+		switch ($parts['scheme']) {
150
+			case 'http':
151
+			case 'https':
152
+				if (empty($parts['path'])) {
153
+					// An empty path is equivalent to / in http.
154
+					$parts['path'] = '/';
155
+				}
156
+				break;
157
+		}
158
+	}
159
+
160
+	if ($parts['host']) {
161
+		$parts['host'] = strtolower($parts['host']);
162
+	}
163
+
164
+	return build($parts);
165 165
 }
166 166
 
167 167
 /**
@@ -180,34 +180,34 @@  discard block
 block discarded – undo
180 180
  */
181 181
 function parse(string $uri): array
182 182
 {
183
-    // Normally a URI must be ASCII, however. However, often it's not and
184
-    // parse_url might corrupt these strings.
185
-    //
186
-    // For that reason we take any non-ascii characters from the uri and
187
-    // uriencode them first.
188
-    $uri = preg_replace_callback(
189
-        '/[^[:ascii:]]/u',
190
-        function ($matches) {
191
-            return rawurlencode($matches[0]);
192
-        },
193
-        $uri
194
-    );
195
-
196
-    $result = parse_url($uri);
197
-    if (!$result) {
198
-        $result = _parse_fallback($uri);
199
-    }
200
-
201
-    return
202
-         $result + [
203
-            'scheme' => null,
204
-            'host' => null,
205
-            'path' => null,
206
-            'port' => null,
207
-            'user' => null,
208
-            'query' => null,
209
-            'fragment' => null,
210
-        ];
183
+	// Normally a URI must be ASCII, however. However, often it's not and
184
+	// parse_url might corrupt these strings.
185
+	//
186
+	// For that reason we take any non-ascii characters from the uri and
187
+	// uriencode them first.
188
+	$uri = preg_replace_callback(
189
+		'/[^[:ascii:]]/u',
190
+		function ($matches) {
191
+			return rawurlencode($matches[0]);
192
+		},
193
+		$uri
194
+	);
195
+
196
+	$result = parse_url($uri);
197
+	if (!$result) {
198
+		$result = _parse_fallback($uri);
199
+	}
200
+
201
+	return
202
+		 $result + [
203
+			'scheme' => null,
204
+			'host' => null,
205
+			'path' => null,
206
+			'port' => null,
207
+			'user' => null,
208
+			'query' => null,
209
+			'fragment' => null,
210
+		];
211 211
 }
212 212
 
213 213
 /**
@@ -218,39 +218,39 @@  discard block
 block discarded – undo
218 218
  */
219 219
 function build(array $parts): string
220 220
 {
221
-    $uri = '';
222
-
223
-    $authority = '';
224
-    if (!empty($parts['host'])) {
225
-        $authority = $parts['host'];
226
-        if (!empty($parts['user'])) {
227
-            $authority = $parts['user'].'@'.$authority;
228
-        }
229
-        if (!empty($parts['port'])) {
230
-            $authority = $authority.':'.$parts['port'];
231
-        }
232
-    }
233
-
234
-    if (!empty($parts['scheme'])) {
235
-        // If there's a scheme, there's also a host.
236
-        $uri = $parts['scheme'].':';
237
-    }
238
-    if ($authority || (!empty($parts['scheme']) && 'file' === $parts['scheme'])) {
239
-        // No scheme, but there is a host.
240
-        $uri .= '//'.$authority;
241
-    }
242
-
243
-    if (!empty($parts['path'])) {
244
-        $uri .= $parts['path'];
245
-    }
246
-    if (!empty($parts['query'])) {
247
-        $uri .= '?'.$parts['query'];
248
-    }
249
-    if (!empty($parts['fragment'])) {
250
-        $uri .= '#'.$parts['fragment'];
251
-    }
252
-
253
-    return $uri;
221
+	$uri = '';
222
+
223
+	$authority = '';
224
+	if (!empty($parts['host'])) {
225
+		$authority = $parts['host'];
226
+		if (!empty($parts['user'])) {
227
+			$authority = $parts['user'].'@'.$authority;
228
+		}
229
+		if (!empty($parts['port'])) {
230
+			$authority = $authority.':'.$parts['port'];
231
+		}
232
+	}
233
+
234
+	if (!empty($parts['scheme'])) {
235
+		// If there's a scheme, there's also a host.
236
+		$uri = $parts['scheme'].':';
237
+	}
238
+	if ($authority || (!empty($parts['scheme']) && 'file' === $parts['scheme'])) {
239
+		// No scheme, but there is a host.
240
+		$uri .= '//'.$authority;
241
+	}
242
+
243
+	if (!empty($parts['path'])) {
244
+		$uri .= $parts['path'];
245
+	}
246
+	if (!empty($parts['query'])) {
247
+		$uri .= '?'.$parts['query'];
248
+	}
249
+	if (!empty($parts['fragment'])) {
250
+		$uri .= '#'.$parts['fragment'];
251
+	}
252
+
253
+	return $uri;
254 254
 }
255 255
 
256 256
 /**
@@ -272,12 +272,12 @@  discard block
 block discarded – undo
272 272
  */
273 273
 function split(string $path): array
274 274
 {
275
-    $matches = [];
276
-    if (preg_match('/^(?:(?:(.*)(?:\/+))?([^\/]+))(?:\/?)$/u', $path, $matches)) {
277
-        return [$matches[1], $matches[2]];
278
-    }
275
+	$matches = [];
276
+	if (preg_match('/^(?:(?:(.*)(?:\/+))?([^\/]+))(?:\/?)$/u', $path, $matches)) {
277
+		return [$matches[1], $matches[2]];
278
+	}
279 279
 
280
-    return [null, null];
280
+	return [null, null];
281 281
 }
282 282
 
283 283
 /**
@@ -296,79 +296,79 @@  discard block
 block discarded – undo
296 296
  */
297 297
 function _parse_fallback(string $uri): array
298 298
 {
299
-    // Normally a URI must be ASCII, however. However, often it's not and
300
-    // parse_url might corrupt these strings.
301
-    //
302
-    // For that reason we take any non-ascii characters from the uri and
303
-    // uriencode them first.
304
-    $uri = preg_replace_callback(
305
-        '/[^[:ascii:]]/u',
306
-        function ($matches) {
307
-            return rawurlencode($matches[0]);
308
-        },
309
-        $uri
310
-    );
311
-
312
-    $result = [
313
-        'scheme' => null,
314
-        'host' => null,
315
-        'port' => null,
316
-        'user' => null,
317
-        'path' => null,
318
-        'fragment' => null,
319
-        'query' => null,
320
-    ];
321
-
322
-    if (preg_match('% ^([A-Za-z][A-Za-z0-9+-\.]+): %x', $uri, $matches)) {
323
-        $result['scheme'] = $matches[1];
324
-        // Take what's left.
325
-        $uri = substr($uri, strlen($result['scheme']) + 1);
326
-    }
327
-
328
-    // Taking off a fragment part
329
-    if (false !== strpos($uri, '#')) {
330
-        list($uri, $result['fragment']) = explode('#', $uri, 2);
331
-    }
332
-    // Taking off the query part
333
-    if (false !== strpos($uri, '?')) {
334
-        list($uri, $result['query']) = explode('?', $uri, 2);
335
-    }
336
-
337
-    if ('///' === substr($uri, 0, 3)) {
338
-        // The triple slash uris are a bit unusual, but we have special handling
339
-        // for them.
340
-        $result['path'] = substr($uri, 2);
341
-        $result['host'] = '';
342
-    } elseif ('//' === substr($uri, 0, 2)) {
343
-        // Uris that have an authority part.
344
-        $regex = '%^
299
+	// Normally a URI must be ASCII, however. However, often it's not and
300
+	// parse_url might corrupt these strings.
301
+	//
302
+	// For that reason we take any non-ascii characters from the uri and
303
+	// uriencode them first.
304
+	$uri = preg_replace_callback(
305
+		'/[^[:ascii:]]/u',
306
+		function ($matches) {
307
+			return rawurlencode($matches[0]);
308
+		},
309
+		$uri
310
+	);
311
+
312
+	$result = [
313
+		'scheme' => null,
314
+		'host' => null,
315
+		'port' => null,
316
+		'user' => null,
317
+		'path' => null,
318
+		'fragment' => null,
319
+		'query' => null,
320
+	];
321
+
322
+	if (preg_match('% ^([A-Za-z][A-Za-z0-9+-\.]+): %x', $uri, $matches)) {
323
+		$result['scheme'] = $matches[1];
324
+		// Take what's left.
325
+		$uri = substr($uri, strlen($result['scheme']) + 1);
326
+	}
327
+
328
+	// Taking off a fragment part
329
+	if (false !== strpos($uri, '#')) {
330
+		list($uri, $result['fragment']) = explode('#', $uri, 2);
331
+	}
332
+	// Taking off the query part
333
+	if (false !== strpos($uri, '?')) {
334
+		list($uri, $result['query']) = explode('?', $uri, 2);
335
+	}
336
+
337
+	if ('///' === substr($uri, 0, 3)) {
338
+		// The triple slash uris are a bit unusual, but we have special handling
339
+		// for them.
340
+		$result['path'] = substr($uri, 2);
341
+		$result['host'] = '';
342
+	} elseif ('//' === substr($uri, 0, 2)) {
343
+		// Uris that have an authority part.
344
+		$regex = '%^
345 345
             //
346 346
             (?: (?<user> [^:@]+) (: (?<pass> [^@]+)) @)?
347 347
             (?<host> ( [^:/]* | \[ [^\]]+ \] ))
348 348
             (?: : (?<port> [0-9]+))?
349 349
             (?<path> / .*)?
350 350
           $%x';
351
-        if (!preg_match($regex, $uri, $matches)) {
352
-            throw new InvalidUriException('Invalid, or could not parse URI');
353
-        }
354
-        if ($matches['host']) {
355
-            $result['host'] = $matches['host'];
356
-        }
357
-        if (isset($matches['port'])) {
358
-            $result['port'] = (int) $matches['port'];
359
-        }
360
-        if (isset($matches['path'])) {
361
-            $result['path'] = $matches['path'];
362
-        }
363
-        if ($matches['user']) {
364
-            $result['user'] = $matches['user'];
365
-        }
366
-        if ($matches['pass']) {
367
-            $result['pass'] = $matches['pass'];
368
-        }
369
-    } else {
370
-        $result['path'] = $uri;
371
-    }
372
-
373
-    return $result;
351
+		if (!preg_match($regex, $uri, $matches)) {
352
+			throw new InvalidUriException('Invalid, or could not parse URI');
353
+		}
354
+		if ($matches['host']) {
355
+			$result['host'] = $matches['host'];
356
+		}
357
+		if (isset($matches['port'])) {
358
+			$result['port'] = (int) $matches['port'];
359
+		}
360
+		if (isset($matches['path'])) {
361
+			$result['path'] = $matches['path'];
362
+		}
363
+		if ($matches['user']) {
364
+			$result['user'] = $matches['user'];
365
+		}
366
+		if ($matches['pass']) {
367
+			$result['pass'] = $matches['pass'];
368
+		}
369
+	} else {
370
+		$result['path'] = $uri;
371
+	}
372
+
373
+	return $result;
374 374
 }
Please login to merge, or discard this patch.