PageRenderTime 77ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/system/libraries/Form_validation.php

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