1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace kdn\yii2\validators; |
4
|
|
|
|
5
|
|
|
use kdn\yii2\validators\mocks\ModelMock; |
6
|
|
|
use stdClass; |
7
|
|
|
use Yii; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Class DomainValidatorTest. |
11
|
|
|
* @package kdn\yii2\validators |
12
|
|
|
* @covers kdn\yii2\validators\DomainValidator::init |
13
|
|
|
*/ |
14
|
|
|
class DomainValidatorTest extends TestCase |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* @var DomainValidator |
18
|
|
|
*/ |
19
|
|
|
protected $validator; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @inheritdoc |
23
|
|
|
*/ |
24
|
|
|
protected function setUp() |
25
|
|
|
{ |
26
|
|
|
parent::setUp(); |
27
|
|
|
$this->validator = new DomainValidator(['labelNumberMin' => 1]); |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
public static function validDomainProvider() |
31
|
|
|
{ |
32
|
|
|
return [ |
33
|
|
|
'one domain name label' => ['localhost'], |
34
|
|
|
'two domain name labels' => ['example.com'], |
35
|
|
|
'domain name with trailing dot' => ['example.com.'], |
36
|
|
|
'127 levels, 253 characters and trailing dot' => [ |
37
|
|
|
'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' . |
38
|
|
|
'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' . |
39
|
|
|
'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' . |
40
|
|
|
'a.a.a.a.', |
41
|
|
|
], |
42
|
|
|
'domain name labels with 63 characters' => [ |
43
|
|
|
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.' . |
44
|
|
|
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.' . |
45
|
|
|
'example.com', |
46
|
|
|
], |
47
|
|
|
'domain name with various symbols' => ['1.a-B.c2'], |
48
|
|
|
'Punycode, mixed domain name' => ['xn--e1afmkfd.test.xn--80akhbyknj4f'], |
49
|
|
|
]; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
public static function validDomainInUrlProvider() |
53
|
|
|
{ |
54
|
|
|
return [ |
55
|
|
|
'HTTP, one domain name label' => ['http://localhost'], |
56
|
|
|
'HTTP, two domain name labels' => ['http://example.com/index.html'], |
57
|
|
|
'FTP, domain name with trailing dot' => ['ftp://example.com./img/dir/'], |
58
|
|
|
// todo it causes empty array in "idn_to_ascii" $idnaInfo |
59
|
|
|
'HTTPS, 127 levels, 253 characters and trailing dot' => [ |
60
|
|
|
'https://a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' . |
61
|
|
|
'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' . |
62
|
|
|
'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' . |
63
|
|
|
'a.a.a.a./index.html', |
64
|
|
|
], |
65
|
|
|
'missing scheme, domain name labels with 63 characters' => [ |
66
|
|
|
'//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.' . |
67
|
|
|
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.' . |
68
|
|
|
'example.com', |
69
|
|
|
], |
70
|
|
|
'complex URL, domain name with various symbols' => [ |
71
|
|
|
'http://username:[email protected]:9090/path?a=b&c=d#anchor', |
72
|
|
|
], |
73
|
|
|
'Punycode, FTP, mixed domain name' => ['ftp://xn--e1afmkfd.test.xn--80akhbyknj4f/img/dir/'], |
74
|
|
|
]; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
public static function validDomainIdnProvider() |
78
|
|
|
{ |
79
|
|
|
return [ |
80
|
|
|
'IDN, one domain name label' => ['пример'], |
81
|
|
|
'IDN, two domain name labels' => ['пример.испытание'], |
82
|
|
|
'IDN, domain name with trailing dot' => ['пример.испытание.'], |
83
|
|
|
'IDN, mixed domain name' => ['пример.test.испытание'], |
84
|
|
|
'IDN, 34 levels, 253 characters (ф. == xn--t1a.) and trailing dot' => [ |
85
|
|
|
'ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.s.s.s.', |
86
|
|
|
], |
87
|
|
|
'IDN, domain name labels with 63 characters' => [ |
88
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
89
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
90
|
|
|
'испытание' |
91
|
|
|
], |
92
|
|
|
'IDN, domain name with various symbols' => ['1.a-B.cф2'], |
93
|
|
|
'IDN, hot beverage' => ['☕.us'], |
94
|
|
|
'IDN, full-width characters' => ['日本語。JP'], |
95
|
|
|
'IDN, box-drawing character' => ['ex╬ample.com'], |
96
|
|
|
]; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
public static function validDomainIdnInUrlProvider() |
100
|
|
|
{ |
101
|
|
|
return [ |
102
|
|
|
'IDN, HTTP, one domain name label' => ['http://пример'], |
103
|
|
|
'IDN, HTTP, two domain name labels' => ['http://пример.испытание/index.html'], |
104
|
|
|
'IDN, FTP, domain name with trailing dot' => ['ftp://пример.испытание./img/dir/'], |
105
|
|
|
'IDN, FTP, mixed domain name' => ['ftp://пример.test.испытание/img/dir/'], |
106
|
|
|
// todo it causes empty array in "idn_to_ascii" $idnaInfo |
107
|
|
|
'IDN, HTTPS, 34 levels, 253 characters (ф. == xn--t1a.) and trailing dot' => [ |
108
|
|
|
'https://ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.s.s.s./index.html', |
109
|
|
|
], |
110
|
|
|
'IDN, missing scheme, domain name labels with 63 characters' => [ |
111
|
|
|
'//ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
112
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
113
|
|
|
'испытание' |
114
|
|
|
], |
115
|
|
|
'IDN, complex URL, domain name with various symbols' => [ |
116
|
|
|
'http://username:[email protected]ф2:9090/path?a=ф&c=d#-пример', |
117
|
|
|
], |
118
|
|
|
'IDN, HTTP, hot beverage' => ['http://☕.us/index.html'], |
119
|
|
|
'IDN, HTTP, full-width characters' => ['http://日本語。JP/index.html'], |
120
|
|
|
'IDN, HTTP, box-drawing character' => ['http://ex╬ample.com/index.html'], |
121
|
|
|
]; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
public static function validDomainAllWithoutIdnProvider() |
125
|
|
|
{ |
126
|
|
|
return array_merge( |
127
|
|
|
static::validDomainProvider(), |
128
|
|
|
static::validDomainInUrlProvider() |
129
|
|
|
); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
public static function validDomainAllOnlyIdnProvider() |
133
|
|
|
{ |
134
|
|
|
return array_merge( |
135
|
|
|
static::validDomainIdnProvider(), |
136
|
|
|
static::validDomainIdnInUrlProvider() |
137
|
|
|
); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
public static function validDomainAllProvider() |
141
|
|
|
{ |
142
|
|
|
return array_merge( |
143
|
|
|
static::validDomainProvider(), |
144
|
|
|
static::validDomainInUrlProvider(), |
145
|
|
|
static::validDomainIdnProvider(), |
146
|
|
|
static::validDomainIdnInUrlProvider() |
147
|
|
|
); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* @param string $value |
152
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
153
|
|
|
* @dataProvider validDomainAllWithoutIdnProvider |
154
|
|
|
* @small |
155
|
|
|
*/ |
156
|
|
|
public function testValidDomain($value) |
157
|
|
|
{ |
158
|
|
|
$this->assertTrue($this->validator->validate($value)); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* @param string $value |
163
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
164
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
165
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
166
|
|
|
* @dataProvider validDomainAllOnlyIdnProvider |
167
|
|
|
* @small |
168
|
|
|
*/ |
169
|
|
|
public function testInvalidDomainWithDisabledIdn($value) |
170
|
|
|
{ |
171
|
|
|
$this->assertFalse($this->validator->validate($value, $errorMessage)); |
172
|
|
|
$this->assertEquals( |
173
|
|
|
'Each label of the input value can consist of only latin letters, numbers and hyphens.', |
174
|
|
|
$errorMessage |
175
|
|
|
); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* @param string $value |
180
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
181
|
|
|
* @dataProvider validDomainAllProvider |
182
|
|
|
* @small |
183
|
|
|
*/ |
184
|
|
|
public function testValidDomainWithEnabledIdn($value) |
185
|
|
|
{ |
186
|
|
|
if (!function_exists('idn_to_ascii')) { |
187
|
|
|
$this->markTestSkipped('intl extension required.'); |
188
|
|
|
return; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
$this->validator->enableIDN = true; |
192
|
|
|
$this->testValidDomain($value); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
197
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
198
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
199
|
|
|
* @medium |
200
|
|
|
*/ |
201
|
|
|
public function testDns() |
202
|
|
|
{ |
203
|
|
|
$validator = $this->validator; |
204
|
|
|
$nonExistingDomain = 'non-existing-subdomain.example.com'; |
205
|
|
|
$this->assertTrue($validator->validate($nonExistingDomain)); |
206
|
|
|
$validator->checkDNS = true; |
207
|
|
|
$this->assertFalse($validator->validate($nonExistingDomain, $errorMessage)); |
208
|
|
|
$this->assertEquals('DNS record corresponding to the input value not found.', $errorMessage); |
209
|
|
|
|
210
|
|
|
$data = [ |
211
|
|
|
'google.com', |
212
|
|
|
'http://username:[email protected]:9090/path?a=b&c=d#anchor', |
213
|
|
|
]; |
214
|
|
|
foreach ($data as $value) { |
215
|
|
|
$this->assertTrue( |
216
|
|
|
$validator->validate($value), |
217
|
|
|
"Failed to validate \"$value\" (checkDNS = true)." |
218
|
|
|
); |
219
|
|
|
} |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
224
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
225
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
226
|
|
|
* @medium |
227
|
|
|
*/ |
228
|
|
|
public function testDnsWithEnabledIdn() |
229
|
|
|
{ |
230
|
|
|
if (!function_exists('idn_to_ascii')) { |
231
|
|
|
$this->markTestSkipped('intl extension required.'); |
232
|
|
|
return; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
$validator = $this->validator; |
236
|
|
|
$validator->checkDNS = true; |
237
|
|
|
// enabling of IDN should not affect error message |
238
|
|
|
$validator->enableIDN = true; |
239
|
|
|
$this->assertFalse($validator->validate('non-existing-subdomain.example.com', $errorMessage)); |
240
|
|
|
$this->assertEquals('DNS record corresponding to the input value not found.', $errorMessage); |
241
|
|
|
|
242
|
|
|
$data = [ |
243
|
|
|
'google.com', |
244
|
|
|
'http://username:[email protected]:9090/path?a=b&c=d#anchor', |
245
|
|
|
'яндекс.рф', |
246
|
|
|
'http://username:password@яндекс.рф:9090/path?a=ф&c=d#-пример', |
247
|
|
|
]; |
248
|
|
|
foreach ($data as $value) { |
249
|
|
|
$this->assertTrue( |
250
|
|
|
$validator->validate($value), |
251
|
|
|
"Failed to validate \"$value\" (checkDNS = true, enableIDN = true)." |
252
|
|
|
); |
253
|
|
|
} |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
258
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
259
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
260
|
|
|
* @small |
261
|
|
|
*/ |
262
|
|
|
public function testUnderscore() |
263
|
|
|
{ |
264
|
|
|
$validator = $this->validator; |
265
|
|
|
$validator->allowUnderscore = true; |
266
|
|
|
|
267
|
|
|
$data = [ |
268
|
|
|
'ex_ample.com', |
269
|
|
|
'http://username:password@ex_ample.com:9090/path?a=b&c=d#anchor', |
270
|
|
|
]; |
271
|
|
|
foreach ($data as $value) { |
272
|
|
|
$this->assertTrue( |
273
|
|
|
$validator->validate($value), |
274
|
|
|
"Failed to validate \"$value\" (allowUnderscore = true)." |
275
|
|
|
); |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
$this->assertFalse($validator->validate('a_@_a', $errorMessage)); |
279
|
|
|
if ($validator->enableIDN) { |
280
|
|
|
$expectedErrorMessage = |
281
|
|
|
'Each label of the input value can consist of only letters, numbers, hyphens and underscores.'; |
282
|
|
|
} else { |
283
|
|
|
$expectedErrorMessage = |
284
|
|
|
'Each label of the input value can consist of only latin letters, numbers, hyphens and underscores.'; |
285
|
|
|
} |
286
|
|
|
$this->assertEquals($expectedErrorMessage, $errorMessage); |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
/** |
290
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
291
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
292
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
293
|
|
|
* @small |
294
|
|
|
*/ |
295
|
|
|
public function testUnderscoreWithEnabledIdn() |
296
|
|
|
{ |
297
|
|
|
if (!function_exists('idn_to_ascii')) { |
298
|
|
|
$this->markTestSkipped('intl extension required.'); |
299
|
|
|
return; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
$this->validator->enableIDN = true; |
303
|
|
|
$this->testUnderscore(); |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
public static function urlNotAllowedProvider() |
307
|
|
|
{ |
308
|
|
|
return array_merge( |
309
|
|
|
static::arrayAddColumn(static::validDomainProvider(), true), |
310
|
|
|
static::arrayAddColumn(static::validDomainInUrlProvider(), false) |
311
|
|
|
); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* @param string $value |
316
|
|
|
* @param boolean $expectedResult |
317
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
318
|
|
|
* @uses kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
319
|
|
|
* @uses kdn\yii2\validators\DomainValidator::getErrorMessage |
320
|
|
|
* @dataProvider urlNotAllowedProvider |
321
|
|
|
* @small |
322
|
|
|
*/ |
323
|
|
|
public function testUrlNotAllowed($value, $expectedResult) |
324
|
|
|
{ |
325
|
|
|
$validator = $this->validator; |
326
|
|
|
$validator->allowURL = false; |
327
|
|
|
$this->assertEquals($expectedResult, $validator->validate($value)); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
public static function urlNotAllowedProviderWithEnabledIdn() |
331
|
|
|
{ |
332
|
|
|
return array_merge( |
333
|
|
|
static::urlNotAllowedProvider(), |
334
|
|
|
static::arrayAddColumn(static::validDomainIdnProvider(), true), |
335
|
|
|
static::arrayAddColumn(static::validDomainIdnInUrlProvider(), false) |
336
|
|
|
); |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
/** |
340
|
|
|
* @param string $value |
341
|
|
|
* @param boolean $expectedResult |
342
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
343
|
|
|
* @uses kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
344
|
|
|
* @uses kdn\yii2\validators\DomainValidator::getErrorMessage |
345
|
|
|
* @dataProvider urlNotAllowedProviderWithEnabledIdn |
346
|
|
|
* @small |
347
|
|
|
*/ |
348
|
|
|
public function testUrlNotAllowedWithEnabledIdn($value, $expectedResult) |
349
|
|
|
{ |
350
|
|
|
if (!function_exists('idn_to_ascii')) { |
351
|
|
|
$this->markTestSkipped('intl extension required.'); |
352
|
|
|
return; |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
$this->validator->enableIDN = true; |
356
|
|
|
$this->testUrlNotAllowed($value, $expectedResult); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
361
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
362
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
363
|
|
|
* @small |
364
|
|
|
*/ |
365
|
|
|
public function testLabelNumberMin() |
366
|
|
|
{ |
367
|
|
|
$validator = $this->validator; |
368
|
|
|
$validator->labelNumberMin = 2; |
369
|
|
|
$this->assertFalse($validator->validate('localhost', $errorMessage)); |
370
|
|
|
$this->assertEquals('the input value should consist of at least 2 labels separated by dot.', $errorMessage); |
371
|
|
|
$this->assertTrue($validator->validate('example.com')); |
372
|
|
|
$this->assertTrue($validator->validate('test.example.com')); |
373
|
|
|
$validator->labelNumberMin = 3; |
374
|
|
|
$this->assertFalse($validator->validate('example.com', $errorMessage)); |
375
|
|
|
$this->assertEquals('the input value should consist of at least 3 labels separated by dots.', $errorMessage); |
376
|
|
|
$this->assertTrue($validator->validate('test.example.com')); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
/** |
380
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
381
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
382
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
383
|
|
|
* @small |
384
|
|
|
*/ |
385
|
|
|
public function testLabelNumberMinWithEnabledIdn() |
386
|
|
|
{ |
387
|
|
|
if (!function_exists('idn_to_ascii')) { |
388
|
|
|
$this->markTestSkipped('intl extension required.'); |
389
|
|
|
return; |
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
$this->validator->enableIDN = true; |
393
|
|
|
$this->testLabelNumberMin(); |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
public static function invalidDomainProvider($testName) |
397
|
|
|
{ |
398
|
|
|
if ($testName == 'testInvalidDomain') { |
399
|
|
|
$messageInvalidCharacter = |
400
|
|
|
'Each label of the input value can consist of only latin letters, numbers and hyphens.'; |
401
|
|
|
$messageLabelStartEnd = 'Each label of the input value should start and end with latin letter or number.' . |
402
|
|
|
' The rightmost label of the input value should start with latin letter.'; |
403
|
|
|
$messageLabelTooLong = 'Each label of the input value should contain at most 63 characters.'; |
404
|
|
|
$messageTooLong = 'the input value should contain at most 253 characters.'; |
405
|
|
|
} else { |
406
|
|
|
$messageInvalidCharacter = |
407
|
|
|
'Each label of the input value can consist of only letters, numbers and hyphens.'; |
408
|
|
|
$messageLabelStartEnd = 'Each label of the input value should start and end with letter or number.' . |
409
|
|
|
' The rightmost label of the input value should start with letter.'; |
410
|
|
|
$messageLabelTooLong = 'Label of the input value is too long.'; |
411
|
|
|
$messageTooLong = 'the input value is too long.'; |
412
|
|
|
} |
413
|
|
|
$messageLabelTooShort = 'Each label of the input value should contain at least 1 character.'; |
414
|
|
|
$messageNotString = 'the input value must be a string.'; |
415
|
|
|
$messageTooShort = 'the input value should contain at least 1 character.'; |
416
|
|
|
return [ |
417
|
|
|
'null' => [null, $messageNotString], |
418
|
|
|
'boolean' => [true, $messageNotString], |
419
|
|
|
'integer' => [1, $messageNotString], |
420
|
|
|
'float' => [1.2, $messageNotString], |
421
|
|
|
'array' => [[], $messageNotString], |
422
|
|
|
'object' => [new stdClass, $messageNotString], |
423
|
|
|
|
424
|
|
|
'domain name too long' => [str_repeat('a.', 126) . 'aa', $messageTooLong], |
425
|
|
|
|
426
|
|
|
'domain name too short' => ['', $messageTooShort], |
427
|
|
|
|
428
|
|
|
'first domain name label starts with hyphen' => ['-example.com', $messageLabelStartEnd], |
429
|
|
|
'first domain name label ends with hyphen' => ['example-.com', $messageLabelStartEnd], |
430
|
|
|
'last domain name label starts with hyphen' => ['example.-com', $messageLabelStartEnd], |
431
|
|
|
'last domain name label ends with hyphen' => ['example.com-', $messageLabelStartEnd], |
432
|
|
|
|
433
|
|
|
'IDN, first domain name label starts with hyphen' => ['-пример.испытание', $messageInvalidCharacter], |
434
|
|
|
'IDN, first domain name label ends with hyphen' => ['пример-.испытание', $messageInvalidCharacter], |
435
|
|
|
'IDN, last domain name label starts with hyphen' => ['пример.-испытание', $messageInvalidCharacter], |
436
|
|
|
'IDN, last domain name label ends with hyphen' => ['пример.испытание-', $messageInvalidCharacter], |
437
|
|
|
|
438
|
|
|
'IDN, HTTP, first domain name label starts with hyphen' => [ |
439
|
|
|
'http://-пример.испытание/index.html', |
440
|
|
|
$messageInvalidCharacter, |
441
|
|
|
], |
442
|
|
|
'IDN, HTTP, first domain name label ends with hyphen' => [ |
443
|
|
|
'http://пример-.испытание/index.html', |
444
|
|
|
$messageInvalidCharacter, |
445
|
|
|
], |
446
|
|
|
'IDN, HTTP, last domain name label starts with hyphen' => [ |
447
|
|
|
'http://пример.-испытание/index.html', |
448
|
|
|
$messageInvalidCharacter, |
449
|
|
|
], |
450
|
|
|
'IDN, HTTP, last domain name label ends with hyphen' => [ |
451
|
|
|
'http://пример.испытание-/index.html', |
452
|
|
|
$messageInvalidCharacter, |
453
|
|
|
], |
454
|
|
|
|
455
|
|
|
'last domain name label starts with number' => ['example.4om', $messageLabelStartEnd], |
456
|
|
|
|
457
|
|
|
'domain name label too long' => [str_repeat('a', 64), $messageLabelTooLong], |
458
|
|
|
|
459
|
|
|
'dot' => ['.', $messageLabelTooShort], |
460
|
|
|
'domain name starts with dot' => ['.example.com', $messageLabelTooShort], |
461
|
|
|
'domain name ends with two dots' => ['example.com..', $messageLabelTooShort], |
462
|
|
|
'domain name contains two dots in a row' => ['example..com', $messageLabelTooShort], |
463
|
|
|
|
464
|
|
|
'domain name contains underscore' => ['ex_ample.com', $messageInvalidCharacter], |
465
|
|
|
'domain name contains space' => ['ex ample.com', $messageInvalidCharacter], |
466
|
|
|
'domain name contains disallowed character' => ['a⒈com', $messageInvalidCharacter], |
467
|
|
|
|
468
|
|
|
'IDN, domain name too long' => [ |
469
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
470
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
471
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
472
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.', |
473
|
|
|
$messageInvalidCharacter, |
474
|
|
|
], |
475
|
|
|
'IDN, domain name label too long' => [ |
476
|
|
|
'фффффффффффффффффффффффффффффффффффффффффффффффффффффффффs', |
477
|
|
|
$messageInvalidCharacter, |
478
|
|
|
], |
479
|
|
|
|
480
|
|
|
'invalid url with valid domain name' => ['http//example.com/index.html', $messageInvalidCharacter], |
481
|
|
|
'IDN, invalid url with valid domain name' => ['http//пример.com/index.html', $messageInvalidCharacter], |
482
|
|
|
]; |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
/** |
486
|
|
|
* @param string $value |
487
|
|
|
* @param string $expectedErrorMessage |
488
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
489
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
490
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
491
|
|
|
* @dataProvider invalidDomainProvider |
492
|
|
|
* @small |
493
|
|
|
*/ |
494
|
|
|
public function testInvalidDomain($value, $expectedErrorMessage) |
495
|
|
|
{ |
496
|
|
|
$this->assertFalse($this->validator->validate($value, $errorMessage)); |
497
|
|
|
$this->assertEquals($expectedErrorMessage, $errorMessage); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
public static function invalidDomainWithEnabledIdnProvider() |
501
|
|
|
{ |
502
|
|
|
$message = 'the input value is invalid.'; |
503
|
|
|
$messageLabelStartEnd = 'Each label of the input value should start and end with letter or number.' . |
504
|
|
|
' The rightmost label of the input value should start with letter.'; |
505
|
|
|
$messageLabelTooLong = 'Label of the input value is too long.'; |
506
|
|
|
$messageTooLong = 'the input value is too long.'; |
507
|
|
|
return array_merge( |
508
|
|
|
static::invalidDomainProvider('testInvalidDomainWithEnabledIdn'), |
509
|
|
|
[ |
510
|
|
|
/* todo it causes fatal error |
|
|
|
|
511
|
|
|
'IDN, domain name too long, fatal' => [ |
512
|
|
|
'ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.s.s.s.s', |
513
|
|
|
$messageTooLong, |
514
|
|
|
], |
515
|
|
|
//*/ |
516
|
|
|
/* todo it causes fatal error |
517
|
|
|
'IDN, domain name too long, fatal' => [ |
518
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
519
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
520
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
521
|
|
|
'фффффффффффффффффффффффффффффффффффффффффффффффффффффффф.', |
522
|
|
|
$messageTooLong, |
523
|
|
|
], |
524
|
|
|
//*/ |
525
|
|
|
|
526
|
|
|
'IDN, first domain name label starts with hyphen' => ['-пример.испытание', $messageLabelStartEnd], |
527
|
|
|
'IDN, first domain name label ends with hyphen' => ['пример-.испытание', $messageLabelStartEnd], |
528
|
|
|
'IDN, last domain name label starts with hyphen' => ['пример.-испытание', $messageLabelStartEnd], |
529
|
|
|
'IDN, last domain name label ends with hyphen' => ['пример.испытание-', $messageLabelStartEnd], |
530
|
|
|
|
531
|
|
|
'IDN, HTTP, first domain name label starts with hyphen' => [ |
532
|
|
|
'http://-пример.испытание/index.html', |
533
|
|
|
$messageLabelStartEnd, |
534
|
|
|
], |
535
|
|
|
'IDN, HTTP, first domain name label ends with hyphen' => [ |
536
|
|
|
'http://пример-.испытание/index.html', |
537
|
|
|
$messageLabelStartEnd, |
538
|
|
|
], |
539
|
|
|
'IDN, HTTP, last domain name label starts with hyphen' => [ |
540
|
|
|
'http://пример.-испытание/index.html', |
541
|
|
|
$messageLabelStartEnd, |
542
|
|
|
], |
543
|
|
|
'IDN, HTTP, last domain name label ends with hyphen' => [ |
544
|
|
|
'http://пример.испытание-/index.html', |
545
|
|
|
$messageLabelStartEnd, |
546
|
|
|
], |
547
|
|
|
|
548
|
|
|
// todo it causes empty array in "idn_to_ascii" $idnaInfo |
549
|
|
|
'IDN, domain name too long' => [ |
550
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
551
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
552
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' . |
553
|
|
|
'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.', |
554
|
|
|
$messageTooLong, |
555
|
|
|
], |
556
|
|
|
'IDN, domain name label too long' => [ |
557
|
|
|
'фффффффффффффффффффффффффффффффффффффффффффффффффффффффффs', |
558
|
|
|
$messageLabelTooLong, |
559
|
|
|
], |
560
|
|
|
|
561
|
|
|
'IDN, IDNA_ERROR_HYPHEN_3_4' => ['aa--a', $message], |
562
|
|
|
'IDN, IDNA_ERROR_LEADING_COMBINING_MARK' => [json_decode('"\u0308c"'), $message], |
563
|
|
|
'IDN, IDNA_ERROR_PUNYCODE' => ['xn--0', $message], |
564
|
|
|
'IDN, IDNA_ERROR_INVALID_ACE_LABEL' => ['xn--a', $message], |
565
|
|
|
'IDN, IDNA_ERROR_BIDI' => [json_decode('"0A.\\u05D0"'), $message], |
566
|
|
|
] |
567
|
|
|
); |
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
/** |
571
|
|
|
* @param string $value |
572
|
|
|
* @param string $expectedErrorMessage |
573
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
574
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
575
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
576
|
|
|
* @dataProvider invalidDomainWithEnabledIdnProvider |
577
|
|
|
* @small |
578
|
|
|
*/ |
579
|
|
|
public function testInvalidDomainWithEnabledIdn($value, $expectedErrorMessage) |
580
|
|
|
{ |
581
|
|
|
if (!function_exists('idn_to_ascii')) { |
582
|
|
|
$this->markTestSkipped('intl extension required.'); |
583
|
|
|
return; |
584
|
|
|
} |
585
|
|
|
|
586
|
|
|
$this->validator->enableIDN = true; |
587
|
|
|
$this->testInvalidDomain($value, $expectedErrorMessage); |
588
|
|
|
} |
589
|
|
|
|
590
|
|
|
/** |
591
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
592
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
593
|
|
|
* @small |
594
|
|
|
*/ |
595
|
|
|
public function testCustomErrorMessage() |
596
|
|
|
{ |
597
|
|
|
$validator = $this->validator; |
598
|
|
|
$messageNotString = 'test'; |
599
|
|
|
$validator->messageNotString = $messageNotString; |
600
|
|
|
$this->assertFalse($validator->validate(null, $errorMessage)); |
601
|
|
|
$this->assertEquals($messageNotString, $errorMessage); |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
/** |
605
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
606
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
607
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
608
|
|
|
* @small |
609
|
|
|
*/ |
610
|
|
|
public function testSimpleErrorMessage() |
611
|
|
|
{ |
612
|
|
|
$validator = $this->validator; |
613
|
|
|
$validator->simpleErrorMessage = true; |
614
|
|
|
$this->assertFalse($validator->validate('-', $errorMessage)); |
615
|
|
|
$this->assertEquals('the input value is invalid.', $errorMessage); |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
/** |
619
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages |
620
|
|
|
* @covers kdn\yii2\validators\DomainValidator::getErrorMessage |
621
|
|
|
* @covers kdn\yii2\validators\DomainValidator::validateValue |
622
|
|
|
* @small |
623
|
|
|
*/ |
624
|
|
|
public function testValidateAttributeAndI18n() |
625
|
|
|
{ |
626
|
|
|
Yii::$app->language = 'ru-RU'; |
627
|
|
|
$model = new ModelMock(['domain' => 'example']); |
628
|
|
|
$validator = $this->validator; |
629
|
|
|
|
630
|
|
|
$validator->validateAttribute($model, 'domain'); |
631
|
|
|
$this->assertFalse($model->hasErrors('domain')); |
632
|
|
|
|
633
|
|
|
$validator->labelNumberMin = 2; |
634
|
|
|
$validator->validateAttribute($model, 'domain'); |
635
|
|
|
$this->assertTrue($model->hasErrors('domain')); |
636
|
|
|
$this->assertEquals( |
637
|
|
|
'Значение «Доменное имя» должно состоять минимум из 2 меток, разделённых точкой.', |
638
|
|
|
$model->getFirstError('domain') |
639
|
|
|
); |
640
|
|
|
|
641
|
|
|
$model->clearErrors('domain'); |
642
|
|
|
|
643
|
|
|
$validator->labelNumberMin = 21; |
644
|
|
|
$validator->validateAttribute($model, 'domain'); |
645
|
|
|
$this->assertTrue($model->hasErrors('domain')); |
646
|
|
|
$this->assertEquals( |
647
|
|
|
'Значение «Доменное имя» должно состоять минимум из 21 метки, разделённых точками.', |
648
|
|
|
$model->getFirstError('domain') |
649
|
|
|
); |
650
|
|
|
} |
651
|
|
|
|
652
|
|
|
/** |
653
|
|
|
* Important: this test should be executed last, because it can remove function "idn_to_ascii". |
654
|
|
|
* @covers kdn\yii2\validators\DomainValidator::init |
655
|
|
|
* @expectedException \yii\base\InvalidConfigException |
656
|
|
|
* @expectedExceptionMessage In order to use IDN validation intl extension must be installed and enabled. |
657
|
|
|
* @small |
658
|
|
|
*/ |
659
|
|
|
public function testInitIdnIntlException() |
660
|
|
|
{ |
661
|
|
|
if (!function_exists('runkit_function_remove') || !ini_get('runkit.internal_override')) { |
662
|
|
|
$this->markTestSkipped('runkit extension required. runkit.internal_override should be set to "On".'); |
663
|
|
|
return; |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
runkit_function_remove('idn_to_ascii'); |
667
|
|
|
new DomainValidator(['enableIDN' => true]); |
668
|
|
|
} |
669
|
|
|
|
670
|
|
|
/** |
671
|
|
|
* Add column to array. |
672
|
|
|
* @param array $array |
673
|
|
|
* @param mixed $value |
674
|
|
|
* @return array |
675
|
|
|
*/ |
676
|
|
|
protected static function arrayAddColumn($array, $value) |
677
|
|
|
{ |
678
|
|
|
return array_map( |
679
|
|
|
function ($data) use ($value) { |
680
|
|
|
$data[] = $value; |
681
|
|
|
return $data; |
682
|
|
|
}, |
683
|
|
|
$array |
684
|
|
|
); |
685
|
|
|
} |
686
|
|
|
} |
687
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.