Issues (13)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Validator.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @package   Fuel\Validation
4
 * @version   2.0
5
 * @author    Fuel Development Team
6
 * @license   MIT License
7
 * @copyright 2010 - 2013 Fuel Development Team
8
 * @link      http://fuelphp.com
9
 */
10
11
namespace Fuel\Validation;
12
13
use InvalidArgumentException;
14
use LogicException;
15
16
/**
17
 * Main entry point for the validation functionality. Handles registering validation rules and loading validation
18
 * adaptors.
19
 *
20
 * @package Fuel\Validation
21
 * @author  Fuel Development Team
22
 * @since   2.0
23
 *
24
 * @method $this email()
25
 * @method $this ip()
26
 * @method $this matchField(string $matchAgainst)
27
 * @method $this minLength(integer $minLength)
28
 * @method $this maxLength(integer $maxLength)
29
 * @method $this number()
30
 * @method $this numericBetween([integer $min, integer $max])
31
 * @method $this numericMax(integer $max)
32
 * @method $this numericMin(integer $min)
33
 * @method $this regex(string $regex)
34
 * @method $this required()
35
 * @method $this url()
36
 * @method $this date(['format' => string $format])
37
 * @method $this type(string $type)
38
 * @method $this enum(array $values)
39
 * @method $this enumMulti(array $values)
40
 * @method $this validator(ValidatableInterface $validator)
41
 */
42
class Validator implements ValidatableInterface
43
{
44
45
	/**
46
	 * Contains a list of fields to be validated
47
	 *
48
	 * @var FieldInterface[]
49
	 */
50
	protected $fields = array();
51
52
	/**
53
	 * Contains a list of any custom validation rules
54
	 *
55
	 * @var string[]
56
	 */
57
	protected $customRules = array();
58
59
	/**
60
	 * @var string[]
61
	 */
62
	protected $messages = array();
63
64
	/**
65
	 * Keeps track of the last field added for magic method chaining
66
	 *
67
	 * @var FieldInterface
68
	 */
69
	protected $lastAddedField;
70
71
	/**
72
	 * Keeps track of the last rule added for message setting
73
	 *
74
	 * @var RuleInterface
75
	 */
76
	protected $lastAddedRule;
77
78
	/**
79
	 * Default namespace to look for rules in when a rule is not known
80
	 *
81
	 * @var string
82
	 */
83
	protected $ruleNamespace = 'Fuel\Validation\Rule\\';
84
85
	/**
86
	 * Adds a rule that can be used to validate a field
87
	 *
88
	 * @param string|FieldInterface $field
89
	 * @param RuleInterface         $rule
90
	 *
91
	 * @return $this
92
	 *
93
	 * @since 2.0
94
	 */
95 19
	public function addRule($field, RuleInterface $rule)
96
	{
97 19
		if (is_string($field))
98
		{
99
			try
100
			{
101 11
				$field = $this->getField($field);
102
			}
103 5
			catch (InvalidFieldException $ife)
104
			{
105
				// The field does not exist so create it
106 5
				$this->addField($field);
107 5
				$field = $this->getField($field);
108
			}
109
		}
110
111
		// We have a valid field now so add the rule
112 19
		$field->addRule($rule);
113
114 19
		$this->lastAddedRule = $rule;
115
116 19
		return $this;
117
	}
118
119
	/**
120
	 * Adds a new field to the validation object
121
	 *
122
	 * @param string|FieldInterface $field
123
	 * @param string                $label Field name to use in messages, set to null to use $field
124
	 *
125
	 * @return $this
126
	 *
127
	 * @throws InvalidArgumentException
128
	 *
129
	 * @since 2.0
130
	 */
131 22
	public function addField($field, $label = null)
132
	{
133 22
		if (is_string($field))
134
		{
135 20
			$field = new Field($field, $label);
136
		}
137
138 22
		if ( ! $field instanceof FieldInterface)
139
		{
140 1
			throw new InvalidArgumentException('VAL-007: Only FieldInterfaces can be added as a field.');
141
		}
142
143 21
		$this->fields[$field->getName()] = $field;
144 21
		$this->lastAddedField = $field;
145
146 21
		return $this;
147
	}
148
149
	/**
150
	 * Returns the given field
151
	 *
152
	 * @param $name
153
	 *
154
	 * @return FieldInterface
155
	 *
156
	 * @throws InvalidFieldException
157
	 *
158
	 * @since 2.0
159
	 */
160 23
	public function getField($name)
161
	{
162 23
		if ( ! isset($this->fields[$name]))
163
		{
164 7
			throw new InvalidFieldException($name);
165
		}
166
167 21
		return $this->fields[$name];
168
	}
169
170
	/**
171
	 * Takes an array of data and validates that against the assigned rules.
172
	 * The array is expected to have keys named after fields.
173
	 * This function will call reset() before it runs.
174
	 *
175
	 * @param array           $data
176
	 * @param ResultInterface $result
177
	 *
178
	 * @return ResultInterface
179
	 *
180
	 * @since 2.0
181
	 */
182 14
	public function run($data, ResultInterface $result = null)
183
	{
184 14
		if ($result === null)
185
		{
186 14
			$result = new Result;
187
		}
188
189 14
		$result->setResult(true);
190
191 14
		foreach ($this->fields as $fieldName => $rules)
192
		{
193 14
			$fieldResult = $this->validateField($fieldName, $data, $result);
194
195 14
			if ( ! $fieldResult)
196
			{
197
				// There was a failure so log it to the result object
198 14
				$result->setResult(false);
199
			}
200
		}
201
202 14
		return $result;
203
	}
204
205
	/**
206
	 * Takes a field name and an array of data and validates the field against the assigned rules.
207
	 * The array is expected to have keys named after fields.
208
	 * This function will call reset() before it runs.
209
	 *
210
	 * @param string          $field
211
	 * @param array           $data
212
	 * @param ResultInterface $result
213
	 *
214
	 * @return ResultInterface
215
	 *
216
	 * @since 2.0
217
	 */
218 2
	public function runField($field, array $data, ResultInterface $result = null)
219
	{
220 2
		if ($result === null)
221
		{
222 2
			$result = new Result;
223
		}
224
225 2
		$fieldResult = false;
226
227 2
		if (isset($data[$field]))
228
		{
229 1
			$fieldResult = $this->validateField($field, $data, $result);
230
		}
231
232
		// Log the result
233 2
		$result->setResult($fieldResult);
234
235 2
		return $result;
236
	}
237
238
	/**
239
	 * Validates a single field
240
	 *
241
	 * @param string          $field
242
	 * @param mixed[]         $data
243
	 * @param ResultInterface $result
244
	 *
245
	 * @return bool
246
	 *
247
	 * @since 2.0
248
	 */
249 15
	protected function validateField($field, $data, ResultInterface $result)
250
	{
251 15
		$value = null;
252
253
		// If there is data, and the data is not empty and not numeric. This allows for strings such as '0' to be passed
254
		// as valid values.
255 15
		$dataPresent = isset($data[$field]) && ! (empty($data[$field]) && ! is_numeric($data[$field]));
256
257 15
		if ($dataPresent)
258
		{
259 13
			$value = $data[$field];
260
		}
261
262 15
		$rules = $this->getFieldRules($field);
263
264 15
		foreach ($rules as $rule)
265
		{
266 15
			if ( ! $dataPresent && ! $rule->canAlwaysRun())
267
			{
268 4
				continue;
269
			}
270
271 14
			$validateResult = $rule->validate($value, $field, $data);
272
273 14
			if ($validateResult instanceof ResultInterface)
274
			{
275 2
				$result->merge($validateResult, $field . '.');
276 2
				return $validateResult->isValid();
277
			}
278
279 14
			if ( ! $validateResult)
280
			{
281
				// Don't allow any others to run if this one failed
282 7
				$result->setError($field, $this->buildMessage($this->getField($field), $rule, $value), $rule);
0 ignored issues
show
$rule is of type object<Fuel\Validation\RuleInterface>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
283
284 14
				return false;
285
			}
286
		}
287
288
		// All is good so make sure the field gets added as one of the validated fields
289 12
		$result->setValidated($field);
290
291 12
		return true;
292
	}
293
294
	/**
295
	 * Gets a Rule's message and processes that with various tokens
296
	 *
297
	 * @param FieldInterface $field
298
	 * @param RuleInterface  $rule
299
	 *
300
	 * @return string
301
	 */
302 7
	protected function buildMessage(FieldInterface $field, RuleInterface $rule, $value)
303
	{
304
		// Build an array with all the token values
305
		$tokens = array(
306 7
			'name' => $field->getName(),
307 7
			'label' => $field->getLabel(),
308 7
			'value' => $value,
309 7
		) + $rule->getMessageParameters();
310
311 7
		return $this->processMessageTokens($tokens, $rule->getMessage());
312
	}
313
314
	/**
315
	 * Replaces any {} tokens with the matching value from $tokens.
316
	 *
317
	 * @param array $tokens   Associative array of token names and values
318
	 * @param string $message
319
	 *
320
	 * @return string
321
	 *
322
	 * @since 2.0
323
	 */
324 7
	protected function processMessageTokens(array $tokens, $message)
325
	{
326 7
		foreach ($tokens as $token => $value)
327
		{
328 7
			$message = str_replace('{' . $token . '}', $value, $message);
329
		}
330
331 7
		return $message;
332
	}
333
334
	/**
335
	 * @param string $fieldName
336
	 *
337
	 * @return RuleInterface[]
338
	 */
339 18
	public function getFieldRules($fieldName)
340
	{
341
		try
342
		{
343 18
			$field = $this->getField($fieldName);
344
		}
345 1
		catch (InvalidFieldException $ife)
346
		{
347
			// No field found so no rules
348 1
			return array();
349
		}
350
351 17
		return $field->getRules();
352
	}
353
354
	/**
355
	 * Allows validation rules to be dynamically added using method chaining.
356
	 *
357
	 * @param string $name
358
	 * @param array  $arguments
359
	 *
360
	 * @return $this
361
	 * @throws InvalidRuleException
362
	 *
363
	 * @since 2.0
364
	 */
365 9
	public function __call($name, $arguments)
366
	{
367
		// Create and then add the new rule to the last added field
368 9
		$rule = $this->createRuleInstance($name, $arguments);
369
370 8
		$this->addRule($this->lastAddedField, $rule);
371
372 8
		return $this;
373
	}
374
375
	/**
376
	 * Sets the failure message for the last added rule
377
	 *
378
	 * @param string $message
379
	 *
380
	 * @return $this
381
	 *
382
	 * @throws LogicException
383
	 *
384
	 * @since 2.0
385
	 */
386 3
	public function setMessage($message)
387
	{
388 3
		if ( ! $this->lastAddedRule)
389
		{
390 1
			throw new LogicException('VAL-006: A rule should be added before setting a message.');
391
		}
392
393 2
		$this->lastAddedRule->setMessage($message);
394
395 2
		return $this;
396
	}
397
398
	/**
399
	 * Creates an instance of the given rule name
400
	 *
401
	 * @param string $name
402
	 * @param mixed  $parameters
403
	 *
404
	 * @return RuleInterface
405
	 *
406
	 * @throws InvalidRuleException
407
	 *
408
	 * @since 2.0
409
	 */
410 13
	public function createRuleInstance($name, $parameters = [])
411
	{
412 13
		$className = $this->getRuleClassName($name);
413
414 13
		if ( ! class_exists($className))
415
		{
416 2
			throw new InvalidRuleException($name);
417
		}
418
419
		/* @var RuleInterface $instance */
420 11
		$reflection = new \ReflectionClass($className);
421 11
		$instance = $reflection->newInstanceArgs($parameters);
422
423
		// Check if there is a custom message
424 11
		$message = $this->getGlobalMessage($name);
425
426 11
		if ($message !== null)
427
		{
428 1
			$instance->setMessage($message);
429
		}
430
431 11
		return $instance;
432
	}
433
434
	/**
435
	 * Returns the full class name for the given validation rule
436
	 *
437
	 * @param string $name
438
	 *
439
	 * @return string
440
	 *
441
	 * @since 2.0
442
	 */
443 13
	protected function getRuleClassName($name)
444
	{
445
		// Check if we have a custom rule registered
446 13
		if (isset($this->customRules[$name]))
447
		{
448
			// We do so grab the class name from the store
449 3
			return $this->customRules[$name];
450
		}
451
452 10
		return $this->ruleNamespace . ucfirst($name);
453
	}
454
455
	/**
456
	 * Adds custom validation rules and allows for core rules to be overridden.
457
	 * When wanting to override a core rule just specify the rule name as $name.
458
	 * Eg, 'required', 'minLength'. Note the lowercase first letter.
459
	 *
460
	 * The name of the rule should not contain any whitespace or special characters as the name will be available
461
	 * to use as a function name in the method chaining syntax.
462
	 *
463
	 * @param string $name
464
	 * @param string $class
465
	 *
466
	 * @return $this
467
	 *
468
	 * @since 2.0
469
	 */
470 3
	public function addCustomRule($name, $class)
471
	{
472 3
		$this->customRules[$name] = $class;
473
474 3
		return $this;
475
	}
476
477
	/**
478
	 * Sets a custom message for all fields of the given type that are created after the message has been set.
479
	 *
480
	 * @param string      $ruleName Name of the rule to set a message for, eg, required, number, exactLength
481
	 * @param string|null $message  Set to null to disable the custom message
482
	 *
483
	 * @return $this
484
	 *
485
	 * @since 2.0
486
	 */
487 2
	public function setGlobalMessage($ruleName, $message)
488
	{
489 2
		$this->messages[$ruleName] = $message;
490
491 2
		if ($message === null)
492
		{
493 1
			$this->removeGlobalMessage($ruleName);
494
		}
495
496 2
		return $this;
497
	}
498
499
	/**
500
	 * Sets custom messages for one or more rules. Setting the value to "null" will remove the message
501
	 *
502
	 * @param string[] $messages
503
	 *
504
	 * @return $this
505
	 *
506
	 * @since 2.0
507
	 */
508
	public function setGlobalMessages($messages)
509
	{
510
		foreach ($messages as $name => $value)
511
		{
512
			$this->setGlobalMessage($name, $value);
513
		}
514
515
		return $this;
516
	}
517
518
	/**
519
	 * Removes a global rule message
520
	 *
521
	 * @param string $ruleName
522
	 *
523
	 * @return $this
524
	 *
525
	 * @since 2.0
526
	 */
527 1
	public function removeGlobalMessage($ruleName)
528
	{
529 1
		unset($this->messages[$ruleName]);
530
531 1
		return $this;
532
	}
533
534
	/**
535
	 * Gets the global message set for a rule
536
	 *
537
	 * @param string $ruleName
538
	 *
539
	 * @return null|string Will be null if there is no message
540
	 */
541 12
	public function getGlobalMessage($ruleName)
542
	{
543 12
		if ( ! isset($this->messages[$ruleName]))
544
		{
545 11
			return null;
546
		}
547
548 2
		return $this->messages[$ruleName];
549
	}
550
551
}
552