ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
functions.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Sabre\HTTP;
4 
5 use DateTime;
6 
32 function 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 
77 function 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 
107 function 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 
222 function parsePrefer($input) {
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
240 REGEX;
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 
301 function 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 
327 function 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 
386 function 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 
404 function 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 
419 function 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 }
$path
Definition: aliased.php:25
decodePathSegment($path)
Decodes a url-encoded path segment.
Definition: functions.php:431
$result
encodePath($path)
Encodes the path of a url.
Definition: functions.php:386
toDate(DateTime $dateTime)
Transforms a DateTime object to a valid HTTP/1.1 Date header value.
Definition: functions.php:77
$type
negotiateContentType($acceptHeaderValue, array $availableOptions)
This function can be used to aid with content negotiation.
Definition: functions.php:107
decodePath($path)
Decodes a url-encoded path.
Definition: functions.php:419
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
$time
Definition: cron.php:21
parseDate($dateString)
A collection of useful helpers for parsing or generating various HTTP headers.
Definition: functions.php:32
getHeaderValues($values, $values2=null)
This method splits up headers into all their individual values.
Definition: functions.php:301
$values
parseMimeType($str)
Parses a mime-type and splits it into:
Definition: functions.php:327