>bRZ慰'r9B#̙Qu@~~W189@O#Ms=vlCF9 CTcE+&Vy$9T2<@' 茌3HL~ Œ#\v2xPcJ,[{VWr+, M@Z]d`f U]j)/ B+@:D_^ ;˥Q5DHo[(; @AC\ aꆍ{8pR0Ҙ[Lp T;ɔܧ`a!ώ qSP5alNViC6X>hKT& ^!7xbbsu :;EvOM5]R~\ma1|*c!Wf S%*NaoCԚh HT;VĻ7vM!j#4>}q%ő~'ꝛH}B2L8T֪G 넅]] {0])c|(qsG<3v9gV ˟ʲ&xq>XH)m%Y#վ!˲S64d8fz=xBZ@K6yR1 EW@%㵀7N: @+3 ȱLb\{2{g=!uJ ]9{f;l}z}כ~{6?%/C_Lk9.ke~q5QBuΒG U*I,*ܮ%WfJpbX@ n<z@WKr9(WrzHܨ{B'Y&4qUa7nI5ԔzkE.ʢUJ\ۿQz63G.RMBĔiI+ŇqL |9 3J9?R.N+o!+]afz+`1hQW؋XoH)lb-0~Y8L3sl%ClFxsOxY[Vc?W45 (-5 w١ftAMaD*dM̺UNúfS\Ùv}" *dUnarˤjI]*9bifI9 cX1c tk_9KRLeh \Y"RuAD|VOPqq’AHp};ДrDLs0@"A^QP׌,L)c|(qsG텱53δqxS.JN<[>F=z)yD"pEt1ldQd6ä{ 6#z tNNd4̰\4q+อ_l/aJp+>k۲ `Cw\UֺDI=SSW)ל԰&%s>q.-3Eآ Oa~$U0SRS`s1Qװ!`n6' ^7ᢕQFB? 'u wϵAc.+IaYG }0urͱD"TƎJ60./ E^$(gˉ%ä *Rlki4rBydkWa.+muC 0\{*!4^Zqf,eaXSB"ذǻep^\ݥ%;V=GIxӤJƀhSvs!' `lShhP5r+/jWgH_~ >:gm*7qC?nel@G=#ɗSZN!VD4+hg2dĦr;3ؾdJ`24],tͣ!ߕsz#'m+/< ruX/ !fĶ9fQH?4Œ!^NA2{bqo0o2dުD縷{C!7' E\ >`sa1BC&#?/I{ 卝ƟZd {"h(訥(K]i$em@թ0ܠ]?V1;F4}mܜ+k+5C<`0쿾?qC|INZ@+ȩ=5T0*N7i=B˓20 \Е-V{yykJv@#cy()NX( y%!r2z̊w3}OJd$66ꗧu?3?QO>fL&YibyL*[/D`wWbϽni'"mB={jFVz_T3s15sm>l* +zZ+̂¯loD͒,FߞO$& kA':Y e%c,q!9 hYǶ!'2{CN`1* !>zߤJ:X\fu=-p1=KLA'竊CԑU_i%V6@fE#}Y^Or6n\w;G6hŽ/k[3ak.a&*htŨ699+nki4rBydkWa.+muC 0\{*!4^Zqf } else { $this->headerNames[$normalized] = $header; $this->headers[$header] = $value; } } } /** * @param mixed $value * * @return string[] */ private function normalizeHeaderValue($value): array { if (!is_array($value)) { return $this->trimAndValidateHeaderValues([$value]); } if (count($value) === 0) { throw new \InvalidArgumentException('Header value can not be an empty array.'); } return $this->trimAndValidateHeaderValues($value); } /** * Trims whitespace from the header values. * * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. * * header-field = field-name ":" OWS field-value OWS * OWS = *( SP / HTAB ) * * @param mixed[] $values Header values * * @return string[] Trimmed header values * * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 */ private function trimAndValidateHeaderValues(array $values): array { return array_map(function ($value) { if (!is_scalar($value) && null !== $value) { throw new \InvalidArgumentException(sprintf( 'Header value must be scalar or null but %s provided.', is_object($value) ? get_class($value) : gettype($value) )); } $trimmed = trim((string) $value, " \t"); $this->assertValue($trimmed); return $trimmed; }, array_values($values)); } /** * @see https://tools.ietf.org/html/rfc7230#section-3.2 * * @param mixed $header */ private function assertHeader($header): void { if (!is_string($header)) { throw new \InvalidArgumentException(sprintf( 'Header name must be a string but %s provided.', is_object($header) ? get_class($header) : gettype($header) )); } if (!preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) { throw new \InvalidArgumentException( sprintf('"%s" is not valid header name.', $header) ); } } /** * @see https://tools.ietf.org/html/rfc7230#section-3.2 * * field-value = *( field-content / obs-fold ) * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] * field-vchar = VCHAR / obs-text * VCHAR = %x21-7E * obs-text = %x80-FF * obs-fold = CRLF 1*( SP / HTAB ) */ private function assertValue(string $value): void { // The regular expression intentionally does not support the obs-fold production, because as // per RFC 7230#3.2.4: // // A sender MUST NOT generate a message that includes // line folding (i.e., that has any field-value that contains a match to // the obs-fold rule) unless the message is intended for packaging // within the message/http media type. // // Clients must not send a request with line folding and a server sending folded headers is // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting // folding is not likely to break any legitimate use case. if (!preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) { throw new \InvalidArgumentException( sprintf('"%s" is not valid header value.', $value) ); } } }