comparison vendor/guzzlehttp/psr7/src/functions.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents 4c8ae668cc8c
children
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
67 * 67 *
68 * Options is an associative array that can contain the following keys: 68 * Options is an associative array that can contain the following keys:
69 * - metadata: Array of custom metadata. 69 * - metadata: Array of custom metadata.
70 * - size: Size of the stream. 70 * - size: Size of the stream.
71 * 71 *
72 * @param resource|string|null|int|float|bool|StreamInterface|callable $resource Entity body data 72 * @param resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource Entity body data
73 * @param array $options Additional options 73 * @param array $options Additional options
74 * 74 *
75 * @return Stream 75 * @return StreamInterface
76 * @throws \InvalidArgumentException if the $resource arg is not valid. 76 * @throws \InvalidArgumentException if the $resource arg is not valid.
77 */ 77 */
78 function stream_for($resource = '', array $options = []) 78 function stream_for($resource = '', array $options = [])
79 { 79 {
80 if (is_scalar($resource)) { 80 if (is_scalar($resource)) {
236 if (isset($changes['query'])) { 236 if (isset($changes['query'])) {
237 $uri = $uri->withQuery($changes['query']); 237 $uri = $uri->withQuery($changes['query']);
238 } 238 }
239 239
240 if ($request instanceof ServerRequestInterface) { 240 if ($request instanceof ServerRequestInterface) {
241 return new ServerRequest( 241 return (new ServerRequest(
242 isset($changes['method']) ? $changes['method'] : $request->getMethod(), 242 isset($changes['method']) ? $changes['method'] : $request->getMethod(),
243 $uri, 243 $uri,
244 $headers, 244 $headers,
245 isset($changes['body']) ? $changes['body'] : $request->getBody(), 245 isset($changes['body']) ? $changes['body'] : $request->getBody(),
246 isset($changes['version']) 246 isset($changes['version'])
247 ? $changes['version'] 247 ? $changes['version']
248 : $request->getProtocolVersion(), 248 : $request->getProtocolVersion(),
249 $request->getServerParams() 249 $request->getServerParams()
250 ); 250 ))
251 ->withParsedBody($request->getParsedBody())
252 ->withQueryParams($request->getQueryParams())
253 ->withCookieParams($request->getCookieParams())
254 ->withUploadedFiles($request->getUploadedFiles());
251 } 255 }
252 256
253 return new Request( 257 return new Request(
254 isset($changes['method']) ? $changes['method'] : $request->getMethod(), 258 isset($changes['method']) ? $changes['method'] : $request->getMethod(),
255 $uri, 259 $uri,
429 * Read a line from the stream up to the maximum allowed buffer length 433 * Read a line from the stream up to the maximum allowed buffer length
430 * 434 *
431 * @param StreamInterface $stream Stream to read from 435 * @param StreamInterface $stream Stream to read from
432 * @param int $maxLength Maximum buffer length 436 * @param int $maxLength Maximum buffer length
433 * 437 *
434 * @return string|bool 438 * @return string
435 */ 439 */
436 function readline(StreamInterface $stream, $maxLength = null) 440 function readline(StreamInterface $stream, $maxLength = null)
437 { 441 {
438 $buffer = ''; 442 $buffer = '';
439 $size = 0; 443 $size = 0;
493 $data = _parse_message($message); 497 $data = _parse_message($message);
494 // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space 498 // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space
495 // between status-code and reason-phrase is required. But browsers accept 499 // between status-code and reason-phrase is required. But browsers accept
496 // responses without space and reason as well. 500 // responses without space and reason as well.
497 if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { 501 if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
498 throw new \InvalidArgumentException('Invalid response string'); 502 throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']);
499 } 503 }
500 $parts = explode(' ', $data['start-line'], 3); 504 $parts = explode(' ', $data['start-line'], 3);
501 505
502 return new Response( 506 return new Response(
503 $parts[1], 507 $parts[1],
514 * If multiple values are found for the same key, the value of that key 518 * If multiple values are found for the same key, the value of that key
515 * value pair will become an array. This function does not parse nested 519 * value pair will become an array. This function does not parse nested
516 * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will 520 * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will
517 * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']). 521 * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
518 * 522 *
519 * @param string $str Query string to parse 523 * @param string $str Query string to parse
520 * @param bool|string $urlEncoding How the query string is encoded 524 * @param int|bool $urlEncoding How the query string is encoded
521 * 525 *
522 * @return array 526 * @return array
523 */ 527 */
524 function parse_query($str, $urlEncoding = true) 528 function parse_query($str, $urlEncoding = true)
525 { 529 {
531 535
532 if ($urlEncoding === true) { 536 if ($urlEncoding === true) {
533 $decoder = function ($value) { 537 $decoder = function ($value) {
534 return rawurldecode(str_replace('+', ' ', $value)); 538 return rawurldecode(str_replace('+', ' ', $value));
535 }; 539 };
536 } elseif ($urlEncoding == PHP_QUERY_RFC3986) { 540 } elseif ($urlEncoding === PHP_QUERY_RFC3986) {
537 $decoder = 'rawurldecode'; 541 $decoder = 'rawurldecode';
538 } elseif ($urlEncoding == PHP_QUERY_RFC1738) { 542 } elseif ($urlEncoding === PHP_QUERY_RFC1738) {
539 $decoder = 'urldecode'; 543 $decoder = 'urldecode';
540 } else { 544 } else {
541 $decoder = function ($str) { return $str; }; 545 $decoder = function ($str) { return $str; };
542 } 546 }
543 547
631 * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types 635 * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
632 */ 636 */
633 function mimetype_from_extension($extension) 637 function mimetype_from_extension($extension)
634 { 638 {
635 static $mimetypes = [ 639 static $mimetypes = [
640 '3gp' => 'video/3gpp',
636 '7z' => 'application/x-7z-compressed', 641 '7z' => 'application/x-7z-compressed',
637 'aac' => 'audio/x-aac', 642 'aac' => 'audio/x-aac',
638 'ai' => 'application/postscript', 643 'ai' => 'application/postscript',
639 'aif' => 'audio/x-aiff', 644 'aif' => 'audio/x-aiff',
640 'asc' => 'text/plain', 645 'asc' => 'text/plain',
678 'm4a' => 'audio/mp4', 683 'm4a' => 'audio/mp4',
679 'm4v' => 'video/mp4', 684 'm4v' => 'video/mp4',
680 'mid' => 'audio/midi', 685 'mid' => 'audio/midi',
681 'midi' => 'audio/midi', 686 'midi' => 'audio/midi',
682 'mov' => 'video/quicktime', 687 'mov' => 'video/quicktime',
688 'mkv' => 'video/x-matroska',
683 'mp3' => 'audio/mpeg', 689 'mp3' => 'audio/mpeg',
684 'mp4' => 'video/mp4', 690 'mp4' => 'video/mp4',
685 'mp4a' => 'audio/mp4', 691 'mp4a' => 'audio/mp4',
686 'mp4v' => 'video/mp4', 692 'mp4v' => 'video/mp4',
687 'mpe' => 'video/mpeg', 693 'mpe' => 'video/mpeg',
756 { 762 {
757 if (!$message) { 763 if (!$message) {
758 throw new \InvalidArgumentException('Invalid message'); 764 throw new \InvalidArgumentException('Invalid message');
759 } 765 }
760 766
761 // Iterate over each line in the message, accounting for line endings 767 $message = ltrim($message, "\r\n");
762 $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE); 768
763 $result = ['start-line' => array_shift($lines), 'headers' => [], 'body' => '']; 769 $messageParts = preg_split("/\r?\n\r?\n/", $message, 2);
764 array_shift($lines); 770
765 771 if ($messageParts === false || count($messageParts) !== 2) {
766 for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) { 772 throw new \InvalidArgumentException('Invalid message: Missing header delimiter');
767 $line = $lines[$i]; 773 }
768 // If two line breaks were encountered, then this is the end of body 774
769 if (empty($line)) { 775 list($rawHeaders, $body) = $messageParts;
770 if ($i < $totalLines - 1) { 776 $rawHeaders .= "\r\n"; // Put back the delimiter we split previously
771 $result['body'] = implode('', array_slice($lines, $i + 2)); 777 $headerParts = preg_split("/\r?\n/", $rawHeaders, 2);
772 } 778
773 break; 779 if ($headerParts === false || count($headerParts) !== 2) {
774 } 780 throw new \InvalidArgumentException('Invalid message: Missing status line');
775 if (strpos($line, ':')) { 781 }
776 $parts = explode(':', $line, 2); 782
777 $key = trim($parts[0]); 783 list($startLine, $rawHeaders) = $headerParts;
778 $value = isset($parts[1]) ? trim($parts[1]) : ''; 784
779 $result['headers'][$key][] = $value; 785 if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') {
780 } 786 // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
781 } 787 $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);
782 788 }
783 return $result; 789
790 /** @var array[] $headerLines */
791 $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER);
792
793 // If these aren't the same, then one line didn't match and there's an invalid header.
794 if ($count !== substr_count($rawHeaders, "\n")) {
795 // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4
796 if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) {
797 throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding');
798 }
799
800 throw new \InvalidArgumentException('Invalid header syntax');
801 }
802
803 $headers = [];
804
805 foreach ($headerLines as $headerLine) {
806 $headers[$headerLine[1]][] = $headerLine[2];
807 }
808
809 return [
810 'start-line' => $startLine,
811 'headers' => $headers,
812 'body' => $body,
813 ];
784 } 814 }
785 815
786 /** 816 /**
787 * Constructs a URI for an HTTP request message. 817 * Constructs a URI for an HTTP request message.
788 * 818 *
807 $scheme = substr($host, -4) === ':443' ? 'https' : 'http'; 837 $scheme = substr($host, -4) === ':443' ? 'https' : 'http';
808 838
809 return $scheme . '://' . $host . '/' . ltrim($path, '/'); 839 return $scheme . '://' . $host . '/' . ltrim($path, '/');
810 } 840 }
811 841
842 /**
843 * Get a short summary of the message body
844 *
845 * Will return `null` if the response is not printable.
846 *
847 * @param MessageInterface $message The message to get the body summary
848 * @param int $truncateAt The maximum allowed size of the summary
849 *
850 * @return null|string
851 */
852 function get_message_body_summary(MessageInterface $message, $truncateAt = 120)
853 {
854 $body = $message->getBody();
855
856 if (!$body->isSeekable() || !$body->isReadable()) {
857 return null;
858 }
859
860 $size = $body->getSize();
861
862 if ($size === 0) {
863 return null;
864 }
865
866 $summary = $body->read($truncateAt);
867 $body->rewind();
868
869 if ($size > $truncateAt) {
870 $summary .= ' (truncated...)';
871 }
872
873 // Matches any printable character, including unicode characters:
874 // letters, marks, numbers, punctuation, spacing, and separators.
875 if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
876 return null;
877 }
878
879 return $summary;
880 }
881
812 /** @internal */ 882 /** @internal */
813 function _caseless_remove($keys, array $data) 883 function _caseless_remove($keys, array $data)
814 { 884 {
815 $result = []; 885 $result = [];
816 886