PageRenderTime 56ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/system/libraries/Form_validation.php

https://github.com/betchi/CodeIgniter
PHP | 1584 lines | 767 code | 207 blank | 610 comment | 105 complexity | 06f176f4b9e28debf1405eb66cb0c195 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. <?php
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 5.2.4 or newer
  6. *
  7. * NOTICE OF LICENSE
  8. *
  9. * Licensed under the Open Software License version 3.0
  10. *
  11. * This source file is subject to the Open Software License (OSL 3.0) that is
  12. * bundled with this package in the files license.txt / license.rst. It is
  13. * also available through the world wide web at this URL:
  14. * http://opensource.org/licenses/OSL-3.0
  15. * If you did not receive a copy of the license and are unable to obtain it
  16. * through the world wide web, please send an email to
  17. * licensing@ellislab.com so we can send you a copy immediately.
  18. *
  19. * @package CodeIgniter
  20. * @author EllisLab Dev Team
  21. * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
  22. * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
  23. * @link http://codeigniter.com
  24. * @since Version 1.0
  25. * @filesource
  26. */
  27. defined('BASEPATH') OR exit('No direct script access allowed');
  28. /**
  29. * Form Validation Class
  30. *
  31. * @package CodeIgniter
  32. * @subpackage Libraries
  33. * @category Validation
  34. * @author EllisLab Dev Team
  35. * @link http://codeigniter.com/user_guide/libraries/form_validation.html
  36. */
  37. class CI_Form_validation {
  38. /**
  39. * Reference to the CodeIgniter instance
  40. *
  41. * @var object
  42. */
  43. protected $CI;
  44. /**
  45. * Validation data for the current form submission
  46. *
  47. * @var array
  48. */
  49. protected $_field_data = array();
  50. /**
  51. * Validation rules for the current form
  52. *
  53. * @var array
  54. */
  55. protected $_config_rules = array();
  56. /**
  57. * Array of validation errors
  58. *
  59. * @var array
  60. */
  61. protected $_error_array = array();
  62. /**
  63. * Array of custom error messages
  64. *
  65. * @var array
  66. */
  67. protected $_error_messages = array();
  68. /**
  69. * Start tag for error wrapping
  70. *
  71. * @var string
  72. */
  73. protected $_error_prefix = '<p>';
  74. /**
  75. * End tag for error wrapping
  76. *
  77. * @var string
  78. */
  79. protected $_error_suffix = '</p>';
  80. /**
  81. * Custom error message
  82. *
  83. * @var string
  84. */
  85. protected $error_string = '';
  86. /**
  87. * Whether the form data has been validated as safe
  88. *
  89. * @var bool
  90. */
  91. protected $_safe_form_data = FALSE;
  92. /**
  93. * Custom data to validate
  94. *
  95. * @var array
  96. */
  97. public $validation_data = array();
  98. /**
  99. * Initialize Form_Validation class
  100. *
  101. * @param array $rules
  102. * @return void
  103. */
  104. public function __construct($rules = array())
  105. {
  106. $this->CI =& get_instance();
  107. // applies delimiters set in config file.
  108. if (isset($rules['error_prefix']))
  109. {
  110. $this->_error_prefix = $rules['error_prefix'];
  111. unset($rules['error_prefix']);
  112. }
  113. if (isset($rules['error_suffix']))
  114. {
  115. $this->_error_suffix = $rules['error_suffix'];
  116. unset($rules['error_suffix']);
  117. }
  118. // Validation rules can be stored in a config file.
  119. $this->_config_rules = $rules;
  120. // Automatically load the form helper
  121. $this->CI->load->helper('form');
  122. log_message('debug', 'Form Validation Class Initialized');
  123. }
  124. // --------------------------------------------------------------------
  125. /**
  126. * Set Rules
  127. *
  128. * This function takes an array of field names and validation
  129. * rules as input, any custom error messages, validates the info,
  130. * and stores it
  131. *
  132. * @param mixed $field
  133. * @param string $label
  134. * @param mixed $rules
  135. * @param array $errors
  136. * @return CI_Form_validation
  137. */
  138. public function set_rules($field, $label = '', $rules = array(), $errors = array())
  139. {
  140. // No reason to set rules if we have no POST data
  141. // or a validation array has not been specified
  142. if ($this->CI->input->method() !== 'post' && empty($this->validation_data))
  143. {
  144. return $this;
  145. }
  146. // If an array was passed via the first parameter instead of individual string
  147. // values we cycle through it and recursively call this function.
  148. if (is_array($field))
  149. {
  150. foreach ($field as $row)
  151. {
  152. // Houston, we have a problem...
  153. if ( ! isset($row['field'], $row['rules']))
  154. {
  155. continue;
  156. }
  157. // If the field label wasn't passed we use the field name
  158. $label = isset($row['label']) ? $row['label'] : $row['field'];
  159. // Add the custom error message array
  160. $errors = (isset($row['errors']) && is_array($row['errors'])) ? $row['errors'] : array();
  161. // Here we go!
  162. $this->set_rules($row['field'], $label, $row['rules'], $errors);
  163. }
  164. return $this;
  165. }
  166. // No fields? Nothing to do...
  167. if ( ! is_string($field) OR $field === '')
  168. {
  169. return $this;
  170. }
  171. elseif ( ! is_array($rules))
  172. {
  173. // BC: Convert pipe-separated rules string to an array
  174. if (is_string($rules))
  175. {
  176. $rules = explode('|', $rules);
  177. }
  178. else
  179. {
  180. return $this;
  181. }
  182. }
  183. // If the field label wasn't passed we use the field name
  184. $label = ($label === '') ? $field : $label;
  185. $indexes = array();
  186. // Is the field name an array? If it is an array, we break it apart
  187. // into its components so that we can fetch the corresponding POST data later
  188. if (($is_array = (bool) preg_match_all('/\[(.*?)\]/', $field, $matches)) === TRUE)
  189. {
  190. sscanf($field, '%[^[][', $indexes[0]);
  191. for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
  192. {
  193. if ($matches[1][$i] !== '')
  194. {
  195. $indexes[] = $matches[1][$i];
  196. }
  197. }
  198. }
  199. // Build our master array
  200. $this->_field_data[$field] = array(
  201. 'field' => $field,
  202. 'label' => $label,
  203. 'rules' => $rules,
  204. 'errors' => $errors,
  205. 'is_array' => $is_array,
  206. 'keys' => $indexes,
  207. 'postdata' => NULL,
  208. 'error' => ''
  209. );
  210. return $this;
  211. }
  212. // --------------------------------------------------------------------
  213. /**
  214. * By default, form validation uses the $_POST array to validate
  215. *
  216. * If an array is set through this method, then this array will
  217. * be used instead of the $_POST array
  218. *
  219. * Note that if you are validating multiple arrays, then the
  220. * reset_validation() function should be called after validating
  221. * each array due to the limitations of CI's singleton
  222. *
  223. * @param array $data
  224. * @return CI_Form_validation
  225. */
  226. public function set_data(array $data)
  227. {
  228. if ( ! empty($data))
  229. {
  230. $this->validation_data = $data;
  231. }
  232. return $this;
  233. }
  234. // --------------------------------------------------------------------
  235. /**
  236. * Set Error Message
  237. *
  238. * Lets users set their own error messages on the fly. Note:
  239. * The key name has to match the function name that it corresponds to.
  240. *
  241. * @param array
  242. * @param string
  243. * @return CI_Form_validation
  244. */
  245. public function set_message($lang, $val = '')
  246. {
  247. if ( ! is_array($lang))
  248. {
  249. $lang = array($lang => $val);
  250. }
  251. $this->_error_messages = array_merge($this->_error_messages, $lang);
  252. return $this;
  253. }
  254. // --------------------------------------------------------------------
  255. /**
  256. * Set The Error Delimiter
  257. *
  258. * Permits a prefix/suffix to be added to each error message
  259. *
  260. * @param string
  261. * @param string
  262. * @return CI_Form_validation
  263. */
  264. public function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
  265. {
  266. $this->_error_prefix = $prefix;
  267. $this->_error_suffix = $suffix;
  268. return $this;
  269. }
  270. // --------------------------------------------------------------------
  271. /**
  272. * Get Error Message
  273. *
  274. * Gets the error message associated with a particular field
  275. *
  276. * @param string $field Field name
  277. * @param string $prefix HTML start tag
  278. * @param string $suffix HTML end tag
  279. * @return string
  280. */
  281. public function error($field, $prefix = '', $suffix = '')
  282. {
  283. if (empty($this->_field_data[$field]['error']))
  284. {
  285. return '';
  286. }
  287. if ($prefix === '')
  288. {
  289. $prefix = $this->_error_prefix;
  290. }
  291. if ($suffix === '')
  292. {
  293. $suffix = $this->_error_suffix;
  294. }
  295. return $prefix.$this->_field_data[$field]['error'].$suffix;
  296. }
  297. // --------------------------------------------------------------------
  298. /**
  299. * Get Array of Error Messages
  300. *
  301. * Returns the error messages as an array
  302. *
  303. * @return array
  304. */
  305. public function error_array()
  306. {
  307. return $this->_error_array;
  308. }
  309. // --------------------------------------------------------------------
  310. /**
  311. * Error String
  312. *
  313. * Returns the error messages as a string, wrapped in the error delimiters
  314. *
  315. * @param string
  316. * @param string
  317. * @return string
  318. */
  319. public function error_string($prefix = '', $suffix = '')
  320. {
  321. // No errors, validation passes!
  322. if (count($this->_error_array) === 0)
  323. {
  324. return '';
  325. }
  326. if ($prefix === '')
  327. {
  328. $prefix = $this->_error_prefix;
  329. }
  330. if ($suffix === '')
  331. {
  332. $suffix = $this->_error_suffix;
  333. }
  334. // Generate the error string
  335. $str = '';
  336. foreach ($this->_error_array as $val)
  337. {
  338. if ($val !== '')
  339. {
  340. $str .= $prefix.$val.$suffix."\n";
  341. }
  342. }
  343. return $str;
  344. }
  345. // --------------------------------------------------------------------
  346. /**
  347. * Run the Validator
  348. *
  349. * This function does all the work.
  350. *
  351. * @param string $group
  352. * @return bool
  353. */
  354. public function run($group = '')
  355. {
  356. // Do we even have any data to process? Mm?
  357. $validation_array = empty($this->validation_data) ? $_POST : $this->validation_data;
  358. if (count($validation_array) === 0)
  359. {
  360. return FALSE;
  361. }
  362. // Does the _field_data array containing the validation rules exist?
  363. // If not, we look to see if they were assigned via a config file
  364. if (count($this->_field_data) === 0)
  365. {
  366. // No validation rules? We're done...
  367. if (count($this->_config_rules) === 0)
  368. {
  369. return FALSE;
  370. }
  371. if (empty($group))
  372. {
  373. // Is there a validation rule for the particular URI being accessed?
  374. $group = trim($this->CI->uri->ruri_string(), '/');
  375. isset($this->_config_rules[$group]) OR $group = $this->CI->router->class.'/'.$this->CI->router->method;
  376. }
  377. $this->set_rules(isset($this->_config_rules[$group]) ? $this->_config_rules[$group] : $this->_config_rules);
  378. // Were we able to set the rules correctly?
  379. if (count($this->_field_data) === 0)
  380. {
  381. log_message('debug', 'Unable to find validation rules');
  382. return FALSE;
  383. }
  384. }
  385. // Load the language file containing error messages
  386. $this->CI->lang->load('form_validation');
  387. // Cycle through the rules for each field and match the corresponding $validation_data item
  388. foreach ($this->_field_data as $field => $row)
  389. {
  390. // Fetch the data from the validation_data array item and cache it in the _field_data array.
  391. // Depending on whether the field name is an array or a string will determine where we get it from.
  392. if ($row['is_array'] === TRUE)
  393. {
  394. $this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);
  395. }
  396. elseif (isset($validation_array[$field]) && $validation_array[$field] !== '')
  397. {
  398. $this->_field_data[$field]['postdata'] = $validation_array[$field];
  399. }
  400. }
  401. // Execute validation rules
  402. // Note: A second foreach (for now) is required in order to avoid false-positives
  403. // for rules like 'matches', which correlate to other validation fields.
  404. foreach ($this->_field_data as $field => $row)
  405. {
  406. // Don't try to validate if we have no rules set
  407. if (empty($row['rules']))
  408. {
  409. continue;
  410. }
  411. $this->_execute($row, $row['rules'], $this->_field_data[$field]['postdata']);
  412. }
  413. // Did we end up with any errors?
  414. $total_errors = count($this->_error_array);
  415. if ($total_errors > 0)
  416. {
  417. $this->_safe_form_data = TRUE;
  418. }
  419. // Now we need to re-set the POST data with the new, processed data
  420. $this->_reset_post_array();
  421. return ($total_errors === 0);
  422. }
  423. // --------------------------------------------------------------------
  424. /**
  425. * Traverse a multidimensional $_POST array index until the data is found
  426. *
  427. * @param array
  428. * @param array
  429. * @param int
  430. * @return mixed
  431. */
  432. protected function _reduce_array($array, $keys, $i = 0)
  433. {
  434. if (is_array($array) && isset($keys[$i]))
  435. {
  436. return isset($array[$keys[$i]]) ? $this->_reduce_array($array[$keys[$i]], $keys, ($i+1)) : NULL;
  437. }
  438. // NULL must be returned for empty fields
  439. return ($array === '') ? NULL : $array;
  440. }
  441. // --------------------------------------------------------------------
  442. /**
  443. * Re-populate the _POST array with our finalized and processed data
  444. *
  445. * @return void
  446. */
  447. protected function _reset_post_array()
  448. {
  449. foreach ($this->_field_data as $field => $row)
  450. {
  451. if ($row['postdata'] !== NULL)
  452. {
  453. if ($row['is_array'] === FALSE)
  454. {
  455. if (isset($_POST[$row['field']]))
  456. {
  457. $_POST[$row['field']] = $row['postdata'];
  458. }
  459. }
  460. else
  461. {
  462. // start with a reference
  463. $post_ref =& $_POST;
  464. // before we assign values, make a reference to the right POST key
  465. if (count($row['keys']) === 1)
  466. {
  467. $post_ref =& $post_ref[current($row['keys'])];
  468. }
  469. else
  470. {
  471. foreach ($row['keys'] as $val)
  472. {
  473. $post_ref =& $post_ref[$val];
  474. }
  475. }
  476. if (is_array($row['postdata']))
  477. {
  478. $array = array();
  479. foreach ($row['postdata'] as $k => $v)
  480. {
  481. $array[$k] = $v;
  482. }
  483. $post_ref = $array;
  484. }
  485. else
  486. {
  487. $post_ref = $row['postdata'];
  488. }
  489. }
  490. }
  491. }
  492. }
  493. // --------------------------------------------------------------------
  494. /**
  495. * Executes the Validation routines
  496. *
  497. * @param array
  498. * @param array
  499. * @param mixed
  500. * @param int
  501. * @return mixed
  502. */
  503. protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
  504. {
  505. // If the $_POST data is an array we will run a recursive call
  506. if (is_array($postdata))
  507. {
  508. foreach ($postdata as $key => $val)
  509. {
  510. $this->_execute($row, $rules, $val, $key);
  511. }
  512. return;
  513. }
  514. // If the field is blank, but NOT required, no further tests are necessary
  515. $callback = FALSE;
  516. if ( ! in_array('required', $rules) && ($postdata === NULL OR $postdata === ''))
  517. {
  518. // Before we bail out, does the rule contain a callback?
  519. foreach ($rules as &$rule)
  520. {
  521. if (is_string($rule))
  522. {
  523. if (strncmp($rule, 'callback_', 9) === 0)
  524. {
  525. $callback = TRUE;
  526. $rules = array(1 => $rule);
  527. break;
  528. }
  529. }
  530. elseif (is_callable($rule))
  531. {
  532. $callback = TRUE;
  533. $rules = array(1 => $rule);
  534. break;
  535. }
  536. }
  537. if ( ! $callback)
  538. {
  539. return;
  540. }
  541. }
  542. // Isset Test. Typically this rule will only apply to checkboxes.
  543. if (($postdata === NULL OR $postdata === '') && ! $callback)
  544. {
  545. if (in_array('isset', $rules, TRUE) OR in_array('required', $rules))
  546. {
  547. // Set the message type
  548. $type = in_array('required', $rules) ? 'required' : 'isset';
  549. // Check if a custom message is defined
  550. if (isset($this->_field_data[$row['field']]['errors'][$type]))
  551. {
  552. $line = $this->_field_data[$row['field']]['errors'][$type];
  553. }
  554. elseif (isset($this->_error_messages[$type]))
  555. {
  556. $line = $this->_error_messages[$type];
  557. }
  558. elseif (FALSE === ($line = $this->CI->lang->line('form_validation_'.$type))
  559. // DEPRECATED support for non-prefixed keys
  560. && FALSE === ($line = $this->CI->lang->line($type, FALSE)))
  561. {
  562. $line = 'The field was not set';
  563. }
  564. // Build the error message
  565. $message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']));
  566. // Save the error message
  567. $this->_field_data[$row['field']]['error'] = $message;
  568. if ( ! isset($this->_error_array[$row['field']]))
  569. {
  570. $this->_error_array[$row['field']] = $message;
  571. }
  572. }
  573. return;
  574. }
  575. // --------------------------------------------------------------------
  576. // Cycle through each rule and run it
  577. foreach ($rules as $rule)
  578. {
  579. $_in_array = FALSE;
  580. // We set the $postdata variable with the current data in our master array so that
  581. // each cycle of the loop is dealing with the processed data from the last cycle
  582. if ($row['is_array'] === TRUE && is_array($this->_field_data[$row['field']]['postdata']))
  583. {
  584. // We shouldn't need this safety, but just in case there isn't an array index
  585. // associated with this cycle we'll bail out
  586. if ( ! isset($this->_field_data[$row['field']]['postdata'][$cycles]))
  587. {
  588. continue;
  589. }
  590. $postdata = $this->_field_data[$row['field']]['postdata'][$cycles];
  591. $_in_array = TRUE;
  592. }
  593. else
  594. {
  595. // If we get an array field, but it's not expected - then it is most likely
  596. // somebody messing with the form on the client side, so we'll just consider
  597. // it an empty field
  598. $postdata = is_array($this->_field_data[$row['field']]['postdata'])
  599. ? NULL
  600. : $this->_field_data[$row['field']]['postdata'];
  601. }
  602. // Is the rule a callback?
  603. $callback = $callable = FALSE;
  604. if (is_string($rule))
  605. {
  606. if (strpos($rule, 'callback_') === 0)
  607. {
  608. $rule = substr($rule, 9);
  609. $callback = TRUE;
  610. }
  611. }
  612. elseif (is_callable($rule))
  613. {
  614. $callable = TRUE;
  615. }
  616. // Strip the parameter (if exists) from the rule
  617. // Rules can contain a parameter: max_length[5]
  618. $param = FALSE;
  619. if ( ! $callable && preg_match('/(.*?)\[(.*)\]/', $rule, $match))
  620. {
  621. $rule = $match[1];
  622. $param = $match[2];
  623. }
  624. // Call the function that corresponds to the rule
  625. if ($callback OR $callable)
  626. {
  627. if ($callback)
  628. {
  629. if ( ! method_exists($this->CI, $rule))
  630. {
  631. log_message('debug', 'Unable to find callback validation rule: '.$rule);
  632. $result = FALSE;
  633. }
  634. else
  635. {
  636. // Run the function and grab the result
  637. $result = $this->CI->$rule($postdata, $param);
  638. }
  639. }
  640. else
  641. {
  642. $result = is_array($rule)
  643. ? $rule[0]->{$rule[1]}($postdata, $param)
  644. : $rule($postdata, $param);
  645. }
  646. // Re-assign the result to the master data array
  647. if ($_in_array === TRUE)
  648. {
  649. $this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
  650. }
  651. else
  652. {
  653. $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
  654. }
  655. // If the field isn't required and we just processed a callback we'll move on...
  656. if ( ! in_array('required', $rules, TRUE) && $result !== FALSE)
  657. {
  658. continue;
  659. }
  660. }
  661. elseif ( ! method_exists($this, $rule))
  662. {
  663. // If our own wrapper function doesn't exist we see if a native PHP function does.
  664. // Users can use any native PHP function call that has one param.
  665. if (function_exists($rule))
  666. {
  667. // Native PHP functions issue warnings if you pass them more parameters than they use
  668. $result = ($param !== FALSE) ? $rule($postdata, $param) : $rule($postdata);
  669. if ($_in_array === TRUE)
  670. {
  671. $this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
  672. }
  673. else
  674. {
  675. $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
  676. }
  677. }
  678. else
  679. {
  680. log_message('debug', 'Unable to find validation rule: '.$rule);
  681. $result = FALSE;
  682. }
  683. }
  684. else
  685. {
  686. $result = $this->$rule($postdata, $param);
  687. if ($_in_array === TRUE)
  688. {
  689. $this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
  690. }
  691. else
  692. {
  693. $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
  694. }
  695. }
  696. // Did the rule test negatively? If so, grab the error.
  697. if ($result === FALSE)
  698. {
  699. // Callable rules don't have named error messages
  700. if ( ! is_string($rule))
  701. {
  702. return;
  703. }
  704. // Check if a custom message is defined
  705. if (isset($this->_field_data[$row['field']]['errors'][$rule]))
  706. {
  707. $line = $this->_field_data[$row['field']]['errors'][$rule];
  708. }
  709. elseif ( ! isset($this->_error_messages[$rule]))
  710. {
  711. if (FALSE === ($line = $this->CI->lang->line('form_validation_'.$rule))
  712. // DEPRECATED support for non-prefixed keys
  713. && FALSE === ($line = $this->CI->lang->line($rule, FALSE)))
  714. {
  715. $line = 'Unable to access an error message corresponding to your field name.';
  716. }
  717. }
  718. else
  719. {
  720. $line = $this->_error_messages[$rule];
  721. }
  722. // Is the parameter we are inserting into the error message the name
  723. // of another field? If so we need to grab its "field label"
  724. if (isset($this->_field_data[$param], $this->_field_data[$param]['label']))
  725. {
  726. $param = $this->_translate_fieldname($this->_field_data[$param]['label']);
  727. }
  728. // Build the error message
  729. $message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']), $param);
  730. // Save the error message
  731. $this->_field_data[$row['field']]['error'] = $message;
  732. if ( ! isset($this->_error_array[$row['field']]))
  733. {
  734. $this->_error_array[$row['field']] = $message;
  735. }
  736. return;
  737. }
  738. }
  739. }
  740. // --------------------------------------------------------------------
  741. /**
  742. * Translate a field name
  743. *
  744. * @param string the field name
  745. * @return string
  746. */
  747. protected function _translate_fieldname($fieldname)
  748. {
  749. // Do we need to translate the field name?
  750. // We look for the prefix lang: to determine this
  751. if (sscanf($fieldname, 'lang:%s', $line) === 1)
  752. {
  753. // Were we able to translate the field name? If not we use $line
  754. if (FALSE === ($fieldname = $this->CI->lang->line('form_validation_'.$line))
  755. // DEPRECATED support for non-prefixed keys
  756. && FALSE === ($fieldname = $this->CI->lang->line($line, FALSE)))
  757. {
  758. return $line;
  759. }
  760. }
  761. return $fieldname;
  762. }
  763. // --------------------------------------------------------------------
  764. /**
  765. * Build an error message using the field and param.
  766. *
  767. * @param string The error message line
  768. * @param string A field's human name
  769. * @param mixed A rule's optional parameter
  770. * @return string
  771. */
  772. protected function _build_error_msg($line, $field = '', $param = '')
  773. {
  774. // Check for %s in the string for legacy support.
  775. if (strpos($line, '%s') !== FALSE)
  776. {
  777. return sprintf($line, $field, $param);
  778. }
  779. return str_replace(array('{field}', '{param}'), array($field, $param), $line);
  780. }
  781. // --------------------------------------------------------------------
  782. /**
  783. * Checks if the rule is present within the validator
  784. *
  785. * Permits you to check if a rule is present within the validator
  786. *
  787. * @param string the field name
  788. * @return bool
  789. */
  790. public function has_rule($field)
  791. {
  792. return isset($this->_field_data[$field]);
  793. }
  794. // --------------------------------------------------------------------
  795. /**
  796. * Get the value from a form
  797. *
  798. * Permits you to repopulate a form field with the value it was submitted
  799. * with, or, if that value doesn't exist, with the default
  800. *
  801. * @param string the field name
  802. * @param string
  803. * @return string
  804. */
  805. public function set_value($field = '', $default = '')
  806. {
  807. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  808. {
  809. return $default;
  810. }
  811. // If the data is an array output them one at a time.
  812. // E.g: form_input('name[]', set_value('name[]');
  813. if (is_array($this->_field_data[$field]['postdata']))
  814. {
  815. return array_shift($this->_field_data[$field]['postdata']);
  816. }
  817. return $this->_field_data[$field]['postdata'];
  818. }
  819. // --------------------------------------------------------------------
  820. /**
  821. * Set Select
  822. *
  823. * Enables pull-down lists to be set to the value the user
  824. * selected in the event of an error
  825. *
  826. * @param string
  827. * @param string
  828. * @param bool
  829. * @return string
  830. */
  831. public function set_select($field = '', $value = '', $default = FALSE)
  832. {
  833. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  834. {
  835. return ($default === TRUE && count($this->_field_data) === 0) ? ' selected="selected"' : '';
  836. }
  837. $field = $this->_field_data[$field]['postdata'];
  838. $value = (string) $value;
  839. if (is_array($field))
  840. {
  841. // Note: in_array('', array(0)) returns TRUE, do not use it
  842. foreach ($field as &$v)
  843. {
  844. if ($value === $v)
  845. {
  846. return ' selected="selected"';
  847. }
  848. }
  849. return '';
  850. }
  851. elseif (($field === '' OR $value === '') OR ($field !== $value))
  852. {
  853. return '';
  854. }
  855. return ' selected="selected"';
  856. }
  857. // --------------------------------------------------------------------
  858. /**
  859. * Set Radio
  860. *
  861. * Enables radio buttons to be set to the value the user
  862. * selected in the event of an error
  863. *
  864. * @param string
  865. * @param string
  866. * @param bool
  867. * @return string
  868. */
  869. public function set_radio($field = '', $value = '', $default = FALSE)
  870. {
  871. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  872. {
  873. return ($default === TRUE && count($this->_field_data) === 0) ? ' checked="checked"' : '';
  874. }
  875. $field = $this->_field_data[$field]['postdata'];
  876. $value = (string) $value;
  877. if (is_array($field))
  878. {
  879. // Note: in_array('', array(0)) returns TRUE, do not use it
  880. foreach ($field as &$v)
  881. {
  882. if ($value === $v)
  883. {
  884. return ' checked="checked"';
  885. }
  886. }
  887. return '';
  888. }
  889. elseif (($field === '' OR $value === '') OR ($field !== $value))
  890. {
  891. return '';
  892. }
  893. return ' checked="checked"';
  894. }
  895. // --------------------------------------------------------------------
  896. /**
  897. * Set Checkbox
  898. *
  899. * Enables checkboxes to be set to the value the user
  900. * selected in the event of an error
  901. *
  902. * @param string
  903. * @param string
  904. * @param bool
  905. * @return string
  906. */
  907. public function set_checkbox($field = '', $value = '', $default = FALSE)
  908. {
  909. // Logic is exactly the same as for radio fields
  910. return $this->set_radio($field, $value, $default);
  911. }
  912. // --------------------------------------------------------------------
  913. /**
  914. * Required
  915. *
  916. * @param string
  917. * @return bool
  918. */
  919. public function required($str)
  920. {
  921. return is_array($str) ? (bool) count($str) : (trim($str) !== '');
  922. }
  923. // --------------------------------------------------------------------
  924. /**
  925. * Performs a Regular Expression match test.
  926. *
  927. * @param string
  928. * @param string regex
  929. * @return bool
  930. */
  931. public function regex_match($str, $regex)
  932. {
  933. return (bool) preg_match($regex, $str);
  934. }
  935. // --------------------------------------------------------------------
  936. /**
  937. * Match one field to another
  938. *
  939. * @param string $str string to compare against
  940. * @param string $field
  941. * @return bool
  942. */
  943. public function matches($str, $field)
  944. {
  945. return isset($this->_field_data[$field], $this->_field_data[$field]['postdata'])
  946. ? ($str === $this->_field_data[$field]['postdata'])
  947. : FALSE;
  948. }
  949. // --------------------------------------------------------------------
  950. /**
  951. * Differs from another field
  952. *
  953. * @param string
  954. * @param string field
  955. * @return bool
  956. */
  957. public function differs($str, $field)
  958. {
  959. return ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str);
  960. }
  961. // --------------------------------------------------------------------
  962. /**
  963. * Is Unique
  964. *
  965. * Check if the input value doesn't already exist
  966. * in the specified database field.
  967. *
  968. * @param string $str
  969. * @param string $field
  970. * @return bool
  971. */
  972. public function is_unique($str, $field)
  973. {
  974. sscanf($field, '%[^.].%[^.]', $table, $field);
  975. return isset($this->CI->db)
  976. ? ($this->CI->db->limit(1)->get_where($table, array($field => $str))->num_rows() === 0)
  977. : FALSE;
  978. }
  979. // --------------------------------------------------------------------
  980. /**
  981. * Minimum Length
  982. *
  983. * @param string
  984. * @param string
  985. * @return bool
  986. */
  987. public function min_length($str, $val)
  988. {
  989. if ( ! is_numeric($val))
  990. {
  991. return FALSE;
  992. }
  993. return (MB_ENABLED === TRUE)
  994. ? ($val <= mb_strlen($str))
  995. : ($val <= strlen($str));
  996. }
  997. // --------------------------------------------------------------------
  998. /**
  999. * Max Length
  1000. *
  1001. * @param string
  1002. * @param string
  1003. * @return bool
  1004. */
  1005. public function max_length($str, $val)
  1006. {
  1007. if ( ! is_numeric($val))
  1008. {
  1009. return FALSE;
  1010. }
  1011. return (MB_ENABLED === TRUE)
  1012. ? ($val >= mb_strlen($str))
  1013. : ($val >= strlen($str));
  1014. }
  1015. // --------------------------------------------------------------------
  1016. /**
  1017. * Exact Length
  1018. *
  1019. * @param string
  1020. * @param string
  1021. * @return bool
  1022. */
  1023. public function exact_length($str, $val)
  1024. {
  1025. if ( ! is_numeric($val))
  1026. {
  1027. return FALSE;
  1028. }
  1029. return (MB_ENABLED === TRUE)
  1030. ? (mb_strlen($str) === (int) $val)
  1031. : (strlen($str) === (int) $val);
  1032. }
  1033. // --------------------------------------------------------------------
  1034. /**
  1035. * Valid URL
  1036. *
  1037. * @param string $str
  1038. * @return bool
  1039. */
  1040. public function valid_url($str)
  1041. {
  1042. if (empty($str))
  1043. {
  1044. return FALSE;
  1045. }
  1046. elseif (preg_match('/^(?:([^:]*)\:)?\/\/(.+)$/', $str, $matches))
  1047. {
  1048. if (empty($matches[2]))
  1049. {
  1050. return FALSE;
  1051. }
  1052. elseif ( ! in_array($matches[1], array('http', 'https'), TRUE))
  1053. {
  1054. return FALSE;
  1055. }
  1056. $str = $matches[2];
  1057. }
  1058. $str = 'http://'.$str;
  1059. // There's a bug affecting PHP 5.2.13, 5.3.2 that considers the
  1060. // underscore to be a valid hostname character instead of a dash.
  1061. // Reference: https://bugs.php.net/bug.php?id=51192
  1062. if (version_compare(PHP_VERSION, '5.2.13', '==') OR version_compare(PHP_VERSION, '5.3.2', '=='))
  1063. {
  1064. sscanf($str, 'http://%[^/]', $host);
  1065. $str = substr_replace($str, strtr($host, array('_' => '-', '-' => '_')), 7, strlen($host));
  1066. }
  1067. return (filter_var($str, FILTER_VALIDATE_URL) !== FALSE);
  1068. }
  1069. // --------------------------------------------------------------------
  1070. /**
  1071. * Valid Email
  1072. *
  1073. * @param string
  1074. * @return bool
  1075. */
  1076. public function valid_email($str)
  1077. {
  1078. if (function_exists('idn_to_ascii') && $atpos = strpos($str, '@'))
  1079. {
  1080. $str = substr($str, 0, ++$atpos).idn_to_ascii(substr($str, $atpos));
  1081. }
  1082. return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
  1083. }
  1084. // --------------------------------------------------------------------
  1085. /**
  1086. * Valid Emails
  1087. *
  1088. * @param string
  1089. * @return bool
  1090. */
  1091. public function valid_emails($str)
  1092. {
  1093. if (strpos($str, ',') === FALSE)
  1094. {
  1095. return $this->valid_email(trim($str));
  1096. }
  1097. foreach (explode(',', $str) as $email)
  1098. {
  1099. if (trim($email) !== '' && $this->valid_email(trim($email)) === FALSE)
  1100. {
  1101. return FALSE;
  1102. }
  1103. }
  1104. return TRUE;
  1105. }
  1106. // --------------------------------------------------------------------
  1107. /**
  1108. * Validate IP Address
  1109. *
  1110. * @param string
  1111. * @param string 'ipv4' or 'ipv6' to validate a specific IP format
  1112. * @return bool
  1113. */
  1114. public function valid_ip($ip, $which = '')
  1115. {
  1116. return $this->CI->input->valid_ip($ip, $which);
  1117. }
  1118. // --------------------------------------------------------------------
  1119. /**
  1120. * Alpha
  1121. *
  1122. * @param string
  1123. * @return bool
  1124. */
  1125. public function alpha($str)
  1126. {
  1127. return ctype_alpha($str);
  1128. }
  1129. // --------------------------------------------------------------------
  1130. /**
  1131. * Alpha-numeric
  1132. *
  1133. * @param string
  1134. * @return bool
  1135. */
  1136. public function alpha_numeric($str)
  1137. {
  1138. return ctype_alnum((string) $str);
  1139. }
  1140. // --------------------------------------------------------------------
  1141. /**
  1142. * Alpha-numeric w/ spaces
  1143. *
  1144. * @param string
  1145. * @return bool
  1146. */
  1147. public function alpha_numeric_spaces($str)
  1148. {
  1149. return (bool) preg_match('/^[A-Z0-9 ]+$/i', $str);
  1150. }
  1151. // --------------------------------------------------------------------
  1152. /**
  1153. * Alpha-numeric with underscores and dashes
  1154. *
  1155. * @param string
  1156. * @return bool
  1157. */
  1158. public function alpha_dash($str)
  1159. {
  1160. return (bool) preg_match('/^[a-z0-9_-]+$/i', $str);
  1161. }
  1162. // --------------------------------------------------------------------
  1163. /**
  1164. * Numeric
  1165. *
  1166. * @param string
  1167. * @return bool
  1168. */
  1169. public function numeric($str)
  1170. {
  1171. return (bool) preg_match('/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
  1172. }
  1173. // --------------------------------------------------------------------
  1174. /**
  1175. * Integer
  1176. *
  1177. * @param string
  1178. * @return bool
  1179. */
  1180. public function integer($str)
  1181. {
  1182. return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
  1183. }
  1184. // --------------------------------------------------------------------
  1185. /**
  1186. * Decimal number
  1187. *
  1188. * @param string
  1189. * @return bool
  1190. */
  1191. public function decimal($str)
  1192. {
  1193. return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
  1194. }
  1195. // --------------------------------------------------------------------
  1196. /**
  1197. * Greater than
  1198. *
  1199. * @param string
  1200. * @param int
  1201. * @return bool
  1202. */
  1203. public function greater_than($str, $min)
  1204. {
  1205. return is_numeric($str) ? ($str > $min) : FALSE;
  1206. }
  1207. // --------------------------------------------------------------------
  1208. /**
  1209. * Equal to or Greater than
  1210. *
  1211. * @param string
  1212. * @param int
  1213. * @return bool
  1214. */
  1215. public function greater_than_equal_to($str, $min)
  1216. {
  1217. return is_numeric($str) ? ($str >= $min) : FALSE;
  1218. }
  1219. // --------------------------------------------------------------------
  1220. /**
  1221. * Less than
  1222. *
  1223. * @param string
  1224. * @param int
  1225. * @return bool
  1226. */
  1227. public function less_than($str, $max)
  1228. {
  1229. return is_numeric($str) ? ($str < $max) : FALSE;
  1230. }
  1231. // --------------------------------------------------------------------
  1232. /**
  1233. * Equal to or Less than
  1234. *
  1235. * @param string
  1236. * @param int
  1237. * @return bool
  1238. */
  1239. public function less_than_equal_to($str, $max)
  1240. {
  1241. return is_numeric($str) ? ($str <= $max) : FALSE;
  1242. }
  1243. // --------------------------------------------------------------------
  1244. /**
  1245. * Is a Natural number (0,1,2,3, etc.)
  1246. *
  1247. * @param string
  1248. * @return bool
  1249. */
  1250. public function is_natural($str)
  1251. {
  1252. return ctype_digit((string) $str);
  1253. }
  1254. // --------------------------------------------------------------------
  1255. /**
  1256. * Is a Natural number, but not a zero (1,2,3, etc.)
  1257. *
  1258. * @param string
  1259. * @return bool
  1260. */
  1261. public function is_natural_no_zero($str)
  1262. {
  1263. return ($str != 0 && ctype_digit((string) $str));
  1264. }
  1265. // --------------------------------------------------------------------
  1266. /**
  1267. * Valid Base64
  1268. *
  1269. * Tests a string for characters outside of the Base64 alphabet
  1270. * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
  1271. *
  1272. * @param string
  1273. * @return bool
  1274. */
  1275. public function valid_base64($str)
  1276. {
  1277. return (base64_encode(base64_decode($str)) === $str);
  1278. }
  1279. // --------------------------------------------------------------------
  1280. /**
  1281. * Prep data for form
  1282. *
  1283. * This function allows HTML to be safely shown in a form.
  1284. * Special characters are converted.
  1285. *
  1286. * @param string
  1287. * @return string
  1288. */
  1289. public function prep_for_form($data = '')
  1290. {
  1291. if ($this->_safe_form_data === FALSE OR empty($data))
  1292. {
  1293. return $data;
  1294. }
  1295. if (is_array($data))
  1296. {
  1297. foreach ($data as $key => $val)
  1298. {
  1299. $data[$key] = $this->prep_for_form($val);
  1300. }
  1301. return $data;
  1302. }
  1303. return str_replace(array("'", '"', '<', '>'), array('&#39;', '&quot;', '&lt;', '&gt;'), stripslashes($data));
  1304. }
  1305. // --------------------------------------------------------------------
  1306. /**
  1307. * Prep URL
  1308. *
  1309. * @param string
  1310. * @return string
  1311. */
  1312. public function prep_url($str = '')
  1313. {
  1314. if ($str === 'http://' OR $str === '')
  1315. {
  1316. return '';
  1317. }
  1318. if (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)
  1319. {
  1320. return 'http://'.$str;
  1321. }
  1322. return $str;
  1323. }
  1324. // --------------------------------------------------------------------
  1325. /**
  1326. * Strip Image Tags
  1327. *
  1328. * @param string
  1329. * @return string
  1330. */
  1331. public function strip_image_tags($str)
  1332. {
  1333. return $this->CI->security->strip_image_tags($str);
  1334. }
  1335. // --------------------------------------------------------------------
  1336. /**
  1337. * XSS Clean
  1338. *
  1339. * @param string
  1340. * @return string
  1341. */
  1342. public function xss_clean($str)
  1343. {
  1344. return $this->CI->security->xss_clean($str);
  1345. }
  1346. // --------------------------------------------------------------------
  1347. /**
  1348. * Convert PHP tags to entities
  1349. *
  1350. * @param string
  1351. * @return string
  1352. */
  1353. public function encode_php_tags($str)
  1354. {
  1355. return str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);
  1356. }
  1357. // --------------------------------------------------------------------
  1358. /**
  1359. * Reset validation vars
  1360. *
  1361. * Prevents subsequent validation routines from being affected by the
  1362. * results of any previous validation routine due to the CI singleton.
  1363. *
  1364. * @return CI_Form_validation
  1365. */
  1366. public function reset_validation()
  1367. {
  1368. $this->_field_data = array();
  1369. $this->_config_rules = array();
  1370. $this->_error_array = array();
  1371. $this->_error_messages = array();
  1372. $this->error_string = '';
  1373. return $this;
  1374. }
  1375. }
  1376. /* End of file Form_validation.php */
  1377. /* Location: ./system/libraries/Form_validation.php */