13
13
14
14
namespace CodeIgniter \HTTP ;
15
15
16
+ use InvalidArgumentException ;
16
17
use Stringable ;
17
18
18
19
/**
@@ -54,7 +55,7 @@ class Header implements Stringable
54
55
*/
55
56
public function __construct (string $ name , $ value = null )
56
57
{
57
- $ this ->name = $ name ;
58
+ $ this ->setName ( $ name) ;
58
59
$ this ->setValue ($ value );
59
60
}
60
61
@@ -81,9 +82,12 @@ public function getValue()
81
82
* Sets the name of the header, overwriting any previous value.
82
83
*
83
84
* @return $this
85
+ *
86
+ * @throws InvalidArgumentException
84
87
*/
85
88
public function setName (string $ name )
86
89
{
90
+ $ this ->validateName ($ name );
87
91
$ this ->name = $ name ;
88
92
89
93
return $ this ;
@@ -95,10 +99,16 @@ public function setName(string $name)
95
99
* @param array<int|string, array<string, string>|string>|string|null $value
96
100
*
97
101
* @return $this
102
+ *
103
+ * @throws InvalidArgumentException
98
104
*/
99
105
public function setValue ($ value = null )
100
106
{
101
- $ this ->value = is_array ($ value ) ? $ value : (string ) $ value ;
107
+ $ value = is_array ($ value ) ? $ value : (string ) $ value ;
108
+
109
+ $ this ->validateValue ($ value );
110
+
111
+ $ this ->value = $ value ;
102
112
103
113
return $ this ;
104
114
}
@@ -110,13 +120,17 @@ public function setValue($value = null)
110
120
* @param array<string, string>|string|null $value
111
121
*
112
122
* @return $this
123
+ *
124
+ * @throws InvalidArgumentException
113
125
*/
114
126
public function appendValue ($ value = null )
115
127
{
116
128
if ($ value === null ) {
117
129
return $ this ;
118
130
}
119
131
132
+ $ this ->validateValue ($ value );
133
+
120
134
if (! is_array ($ this ->value )) {
121
135
$ this ->value = [$ this ->value ];
122
136
}
@@ -135,13 +149,17 @@ public function appendValue($value = null)
135
149
* @param array<string, string>|string|null $value
136
150
*
137
151
* @return $this
152
+ *
153
+ * @throws InvalidArgumentException
138
154
*/
139
155
public function prependValue ($ value = null )
140
156
{
141
157
if ($ value === null ) {
142
158
return $ this ;
143
159
}
144
160
161
+ $ this ->validateValue ($ value );
162
+
145
163
if (! is_array ($ this ->value )) {
146
164
$ this ->value = [$ this ->value ];
147
165
}
@@ -193,4 +211,54 @@ public function __toString(): string
193
211
{
194
212
return $ this ->name . ': ' . $ this ->getValueLine ();
195
213
}
214
+
215
+ /**
216
+ * Validate header name.
217
+ *
218
+ * Regex is based on code from a guzzlehttp/psr7 library.
219
+ *
220
+ * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
221
+ *
222
+ * @throws InvalidArgumentException
223
+ */
224
+ private function validateName (string $ name ): void
225
+ {
226
+ if (preg_match ('/^[a-zA-Z0-9 \'`#$%&*+.^_|~!-]+$/D ' , $ name ) !== 1 ) {
227
+ throw new InvalidArgumentException ('The header name is not valid as per RFC 7230. ' );
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Validate header value.
233
+ *
234
+ * Regex is based on code from a guzzlehttp/psr7 library.
235
+ *
236
+ * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
237
+ *
238
+ * @param array<int|string, array<string, string>|string>|int|string $value
239
+ *
240
+ * @throws InvalidArgumentException
241
+ */
242
+ private function validateValue (array |int |string $ value ): void
243
+ {
244
+ if (is_int ($ value )) {
245
+ return ;
246
+ }
247
+
248
+ if (is_array ($ value )) {
249
+ foreach ($ value as $ key => $ val ) {
250
+ $ this ->validateValue ($ key );
251
+ $ this ->validateValue ($ val );
252
+ }
253
+
254
+ return ;
255
+ }
256
+
257
+ // The regular expression excludes obs-fold per RFC 7230#3.2.4, as sending folded lines
258
+ // is deprecated and rare. This obscure HTTP/1.1 feature is unlikely to impact legitimate
259
+ // use cases. Libraries like Guzzle and AMPHP follow the same principle.
260
+ if (preg_match ('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D ' , $ value ) !== 1 ) {
261
+ throw new InvalidArgumentException ('The header value is not valid as per RFC 7230. ' );
262
+ }
263
+ }
196
264
}
0 commit comments