ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
functions.php
Go to the documentation of this file.
1<?php
2
3namespace Sabre\HTTP;
4
5use DateTime;
6
32function parseDate($dateString) {
33
34 // Only the format is checked, valid ranges are checked by strtotime below
35 $month = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)';
36 $weekday = '(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)';
37 $wkday = '(Mon|Tue|Wed|Thu|Fri|Sat|Sun)';
38 $time = '([0-1]\d|2[0-3])(\:[0-5]\d){2}';
39 $date3 = $month . ' ([12]\d|3[01]| [1-9])';
40 $date2 = '(0[1-9]|[12]\d|3[01])\-' . $month . '\-\d{2}';
41 // 4-digit year cannot begin with 0 - unix timestamp begins in 1970
42 $date1 = '(0[1-9]|[12]\d|3[01]) ' . $month . ' [1-9]\d{3}';
43
44 // ANSI C's asctime() format
45 // 4-digit year cannot begin with 0 - unix timestamp begins in 1970
46 $asctime_date = $wkday . ' ' . $date3 . ' ' . $time . ' [1-9]\d{3}';
47 // RFC 850, obsoleted by RFC 1036
48 $rfc850_date = $weekday . ', ' . $date2 . ' ' . $time . ' GMT';
49 // RFC 822, updated by RFC 1123
50 $rfc1123_date = $wkday . ', ' . $date1 . ' ' . $time . ' GMT';
51 // allowed date formats by RFC 2616
52 $HTTP_date = "($rfc1123_date|$rfc850_date|$asctime_date)";
53
54 // allow for space around the string and strip it
55 $dateString = trim($dateString, ' ');
56 if (!preg_match('/^' . $HTTP_date . '$/', $dateString))
57 return false;
58
59 // append implicit GMT timezone to ANSI C time format
60 if (strpos($dateString, ' GMT') === false)
61 $dateString .= ' GMT';
62
63 try {
64 return new DateTime($dateString, new \DateTimeZone('UTC'));
65 } catch (\Exception $e) {
66 return false;
67 }
68
69}
70
77function toDate(DateTime $dateTime) {
78
79 // We need to clone it, as we don't want to affect the existing
80 // DateTime.
81 $dateTime = clone $dateTime;
82 $dateTime->setTimezone(new \DateTimeZone('GMT'));
83 return $dateTime->format('D, d M Y H:i:s \G\M\T');
84
85}
86
107function negotiateContentType($acceptHeaderValue, array $availableOptions) {
108
109 if (!$acceptHeaderValue) {
110 // Grabbing the first in the list.
111 return reset($availableOptions);
112 }
113
114 $proposals = array_map(
115 'Sabre\HTTP\parseMimeType',
116 explode(',', $acceptHeaderValue)
117 );
118
119 // Ensuring array keys are reset.
120 $availableOptions = array_values($availableOptions);
121
122 $options = array_map(
123 'Sabre\HTTP\parseMimeType',
124 $availableOptions
125 );
126
127 $lastQuality = 0;
128 $lastSpecificity = 0;
129 $lastOptionIndex = 0;
130 $lastChoice = null;
131
132 foreach ($proposals as $proposal) {
133
134 // Ignoring broken values.
135 if (is_null($proposal)) continue;
136
137 // If the quality is lower we don't have to bother comparing.
138 if ($proposal['quality'] < $lastQuality) {
139 continue;
140 }
141
142 foreach ($options as $optionIndex => $option) {
143
144 if ($proposal['type'] !== '*' && $proposal['type'] !== $option['type']) {
145 // no match on type.
146 continue;
147 }
148 if ($proposal['subType'] !== '*' && $proposal['subType'] !== $option['subType']) {
149 // no match on subtype.
150 continue;
151 }
152
153 // Any parameters appearing on the options must appear on
154 // proposals.
155 foreach ($option['parameters'] as $paramName => $paramValue) {
156 if (!array_key_exists($paramName, $proposal['parameters'])) {
157 continue 2;
158 }
159 if ($paramValue !== $proposal['parameters'][$paramName]) {
160 continue 2;
161 }
162 }
163
164 // If we got here, we have a match on parameters, type and
165 // subtype. We need to calculate a score for how specific the
166 // match was.
167 $specificity =
168 ($proposal['type'] !== '*' ? 20 : 0) +
169 ($proposal['subType'] !== '*' ? 10 : 0) +
170 count($option['parameters']);
171
172
173 // Does this entry win?
174 if (
175 ($proposal['quality'] > $lastQuality) ||
176 ($proposal['quality'] === $lastQuality && $specificity > $lastSpecificity) ||
177 ($proposal['quality'] === $lastQuality && $specificity === $lastSpecificity && $optionIndex < $lastOptionIndex)
178 ) {
179
180 $lastQuality = $proposal['quality'];
181 $lastSpecificity = $specificity;
182 $lastOptionIndex = $optionIndex;
183 $lastChoice = $availableOptions[$optionIndex];
184
185 }
186
187 }
188
189 }
190
191 return $lastChoice;
192
193}
194
223
224 $token = '[!#$%&\'*+\-.^_`~A-Za-z0-9]+';
225
226 // Work in progress
227 $word = '(?: [a-zA-Z0-9]+ | "[a-zA-Z0-9]*" )';
228
229 $regex = <<<REGEX
230/
231^
232(?<name> $token) # Prefer property name
233\s* # Optional space
234(?: = \s* # Prefer property value
235 (?<value> $word)
236)?
237(?: \s* ; (?: .*))? # Prefer parameters (ignored)
238$
239/x
240REGEX;
241
242 $output = [];
243 foreach (getHeaderValues($input) as $value) {
244
245 if (!preg_match($regex, $value, $matches)) {
246 // Ignore
247 continue;
248 }
249
250 // Mapping old values to their new counterparts
251 switch ($matches['name']) {
252 case 'return-asynch' :
253 $output['respond-async'] = true;
254 break;
255 case 'return-representation' :
256 $output['return'] = 'representation';
257 break;
258 case 'return-minimal' :
259 $output['return'] = 'minimal';
260 break;
261 case 'strict' :
262 $output['handling'] = 'strict';
263 break;
264 case 'lenient' :
265 $output['handling'] = 'lenient';
266 break;
267 default :
268 if (isset($matches['value'])) {
269 $value = trim($matches['value'], '"');
270 } else {
271 $value = true;
272 }
273 $output[strtolower($matches['name'])] = empty($value) ? true : $value;
274 break;
275 }
276
277 }
278
279 return $output;
280
281}
282
301function getHeaderValues($values, $values2 = null) {
302
303 $values = (array)$values;
304 if ($values2) {
305 $values = array_merge($values, (array)$values2);
306 }
307 foreach ($values as $l1) {
308 foreach (explode(',', $l1) as $l2) {
309 $result[] = trim($l2);
310 }
311 }
312 return $result;
313
314}
315
327function parseMimeType($str) {
328
329 $parameters = [];
330 // If no q= parameter appears, then quality = 1.
331 $quality = 1;
332
333 $parts = explode(';', $str);
334
335 // The first part is the mime-type.
336 $mimeType = array_shift($parts);
337
338 $mimeType = explode('/', trim($mimeType));
339 if (count($mimeType) !== 2) {
340 // Illegal value
341 return null;
342 }
343 list($type, $subType) = $mimeType;
344
345 foreach ($parts as $part) {
346
347 $part = trim($part);
348 if (strpos($part, '=')) {
349 list($partName, $partValue) =
350 explode('=', $part, 2);
351 } else {
352 $partName = $part;
353 $partValue = null;
354 }
355
356 // The quality parameter, if it appears, also marks the end of
357 // the parameter list. Anything after the q= counts as an
358 // 'accept extension' and could introduce new semantics in
359 // content-negotation.
360 if ($partName !== 'q') {
361 $parameters[$partName] = $part;
362 } else {
363 $quality = (float)$partValue;
364 break; // Stop parsing parts
365 }
366
367 }
368
369 return [
370 'type' => $type,
371 'subType' => $subType,
372 'quality' => $quality,
373 'parameters' => $parameters,
374 ];
375
376}
377
386function encodePath($path) {
387
388 return preg_replace_callback('/([^A-Za-z0-9_\-\.~\‍(\‍)\/:@])/', function($match) {
389
390 return '%' . sprintf('%02x', ord($match[0]));
391
392 }, $path);
393
394}
395
404function encodePathSegment($pathSegment) {
405
406 return preg_replace_callback('/([^A-Za-z0-9_\-\.~\‍(\‍):@])/', function($match) {
407
408 return '%' . sprintf('%02x', ord($match[0]));
409
410 }, $pathSegment);
411}
412
419function decodePath($path) {
420
421 return decodePathSegment($path);
422
423}
424
432
433 $path = rawurldecode($path);
434 $encoding = mb_detect_encoding($path, ['UTF-8', 'ISO-8859-1']);
435
436 switch ($encoding) {
437
438 case 'ISO-8859-1' :
439 $path = utf8_encode($path);
440
441 }
442
443 return $path;
444
445}
$result
$path
Definition: aliased.php:25
An exception for terminatinating execution or to throw for unit testing.
$time
Definition: cron.php:21
decodePathSegment($path)
Decodes a url-encoded path segment.
Definition: functions.php:431
parsePrefer($input)
Parses the Prefer header, as defined in RFC7240.
Definition: functions.php:222
encodePathSegment($pathSegment)
Encodes a 1 segment of a path.
Definition: functions.php:404
parseMimeType($str)
Parses a mime-type and splits it into:
Definition: functions.php:327
parseDate($dateString)
A collection of useful helpers for parsing or generating various HTTP headers.
Definition: functions.php:32
toDate(DateTime $dateTime)
Transforms a DateTime object to a valid HTTP/1.1 Date header value.
Definition: functions.php:77
encodePath($path)
Encodes the path of a url.
Definition: functions.php:386
getHeaderValues($values, $values2=null)
This method splits up headers into all their individual values.
Definition: functions.php:301
decodePath($path)
Decodes a url-encoded path.
Definition: functions.php:419
negotiateContentType($acceptHeaderValue, array $availableOptions)
This function can be used to aid with content negotiation.
Definition: functions.php:107
$type
$values