PageRenderTime 58ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/system/libraries/Form_validation.php

https://github.com/CodeIgniter-TW/Web
PHP | 1498 lines | 716 code | 197 blank | 585 comment | 99 complexity | 59f5ee957ca238108d0f2cbaa125d337 MD5 | raw file
  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 - 2013, 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 CI_Form_validation
  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 CI_Form_validation
  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 CI_Form_validation
  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('form_validation_'.$type))
  536. // DEPRECATED support for non-prefixed keys
  537. && FALSE === ($line = $this->CI->lang->line($type, FALSE)))
  538. {
  539. $line = 'The field was not set';
  540. }
  541. // Build the error message
  542. $message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']));
  543. // Save the error message
  544. $this->_field_data[$row['field']]['error'] = $message;
  545. if ( ! isset($this->_error_array[$row['field']]))
  546. {
  547. $this->_error_array[$row['field']] = $message;
  548. }
  549. }
  550. return;
  551. }
  552. // --------------------------------------------------------------------
  553. // Cycle through each rule and run it
  554. foreach ($rules as $rule)
  555. {
  556. $_in_array = FALSE;
  557. // We set the $postdata variable with the current data in our master array so that
  558. // each cycle of the loop is dealing with the processed data from the last cycle
  559. if ($row['is_array'] === TRUE && is_array($this->_field_data[$row['field']]['postdata']))
  560. {
  561. // We shouldn't need this safety, but just in case there isn't an array index
  562. // associated with this cycle we'll bail out
  563. if ( ! isset($this->_field_data[$row['field']]['postdata'][$cycles]))
  564. {
  565. continue;
  566. }
  567. $postdata = $this->_field_data[$row['field']]['postdata'][$cycles];
  568. $_in_array = TRUE;
  569. }
  570. else
  571. {
  572. // If we get an array field, but it's not expected - then it is most likely
  573. // somebody messing with the form on the client side, so we'll just consider
  574. // it an empty field
  575. $postdata = is_array($this->_field_data[$row['field']]['postdata'])
  576. ? NULL
  577. : $this->_field_data[$row['field']]['postdata'];
  578. }
  579. // Is the rule a callback?
  580. $callback = FALSE;
  581. if (strpos($rule, 'callback_') === 0)
  582. {
  583. $rule = substr($rule, 9);
  584. $callback = TRUE;
  585. }
  586. // Strip the parameter (if exists) from the rule
  587. // Rules can contain a parameter: max_length[5]
  588. $param = FALSE;
  589. if (preg_match('/(.*?)\[(.*)\]/', $rule, $match))
  590. {
  591. $rule = $match[1];
  592. $param = $match[2];
  593. }
  594. // Call the function that corresponds to the rule
  595. if ($callback === TRUE)
  596. {
  597. if ( ! method_exists($this->CI, $rule))
  598. {
  599. log_message('debug', 'Unable to find callback validation rule: '.$rule);
  600. $result = FALSE;
  601. }
  602. else
  603. {
  604. // Run the function and grab the result
  605. $result = $this->CI->$rule($postdata, $param);
  606. }
  607. // Re-assign the result to the master data array
  608. if ($_in_array === TRUE)
  609. {
  610. $this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
  611. }
  612. else
  613. {
  614. $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
  615. }
  616. // If the field isn't required and we just processed a callback we'll move on...
  617. if ( ! in_array('required', $rules, TRUE) && $result !== FALSE)
  618. {
  619. continue;
  620. }
  621. }
  622. elseif ( ! method_exists($this, $rule))
  623. {
  624. // If our own wrapper function doesn't exist we see if a native PHP function does.
  625. // Users can use any native PHP function call that has one param.
  626. if (function_exists($rule))
  627. {
  628. $result = ($param !== FALSE) ? $rule($postdata, $param) : $rule($postdata);
  629. if ($_in_array === TRUE)
  630. {
  631. $this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
  632. }
  633. else
  634. {
  635. $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
  636. }
  637. }
  638. else
  639. {
  640. log_message('debug', 'Unable to find validation rule: '.$rule);
  641. $result = FALSE;
  642. }
  643. }
  644. else
  645. {
  646. $result = $this->$rule($postdata, $param);
  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. }
  656. // Did the rule test negatively? If so, grab the error.
  657. if ($result === FALSE)
  658. {
  659. if ( ! isset($this->_error_messages[$rule]))
  660. {
  661. if (FALSE === ($line = $this->CI->lang->line('form_validation_'.$rule))
  662. // DEPRECATED support for non-prefixed keys
  663. && FALSE === ($line = $this->CI->lang->line($rule, FALSE)))
  664. {
  665. $line = 'Unable to access an error message corresponding to your field name.';
  666. }
  667. }
  668. else
  669. {
  670. $line = $this->_error_messages[$rule];
  671. }
  672. // Is the parameter we are inserting into the error message the name
  673. // of another field? If so we need to grab its "field label"
  674. if (isset($this->_field_data[$param], $this->_field_data[$param]['label']))
  675. {
  676. $param = $this->_translate_fieldname($this->_field_data[$param]['label']);
  677. }
  678. // Build the error message
  679. $message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']), $param);
  680. // Save the error message
  681. $this->_field_data[$row['field']]['error'] = $message;
  682. if ( ! isset($this->_error_array[$row['field']]))
  683. {
  684. $this->_error_array[$row['field']] = $message;
  685. }
  686. return;
  687. }
  688. }
  689. }
  690. // --------------------------------------------------------------------
  691. /**
  692. * Translate a field name
  693. *
  694. * @param string the field name
  695. * @return string
  696. */
  697. protected function _translate_fieldname($fieldname)
  698. {
  699. // Do we need to translate the field name?
  700. // We look for the prefix lang: to determine this
  701. if (sscanf($fieldname, 'lang:%s', $line) === 1)
  702. {
  703. // Were we able to translate the field name? If not we use $line
  704. if (FALSE === ($fieldname = $this->CI->lang->line('form_validation_'.$line))
  705. // DEPRECATED support for non-prefixed keys
  706. && FALSE === ($fieldname = $this->CI->lang->line($line, FALSE)))
  707. {
  708. return $line;
  709. }
  710. }
  711. return $fieldname;
  712. }
  713. // --------------------------------------------------------------------
  714. /**
  715. * Build an error message using the field and param.
  716. *
  717. * @param string The error message line
  718. * @param string A field's human name
  719. * @param mixed A rule's optional parameter
  720. * @return string
  721. */
  722. protected function _build_error_msg($line, $field = '', $param = '')
  723. {
  724. // Check for %s in the string for legacy support.
  725. if (strpos($line, '%s') !== FALSE)
  726. {
  727. return sprintf($line, $field, $param);
  728. }
  729. return str_replace(array('{field}', '{param}'), array($field, $param), $line);
  730. }
  731. // --------------------------------------------------------------------
  732. /**
  733. * Get the value from a form
  734. *
  735. * Permits you to repopulate a form field with the value it was submitted
  736. * with, or, if that value doesn't exist, with the default
  737. *
  738. * @param string the field name
  739. * @param string
  740. * @return string
  741. */
  742. public function set_value($field = '', $default = '')
  743. {
  744. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  745. {
  746. return $default;
  747. }
  748. // If the data is an array output them one at a time.
  749. // E.g: form_input('name[]', set_value('name[]');
  750. if (is_array($this->_field_data[$field]['postdata']))
  751. {
  752. return array_shift($this->_field_data[$field]['postdata']);
  753. }
  754. return $this->_field_data[$field]['postdata'];
  755. }
  756. // --------------------------------------------------------------------
  757. /**
  758. * Set Select
  759. *
  760. * Enables pull-down lists to be set to the value the user
  761. * selected in the event of an error
  762. *
  763. * @param string
  764. * @param string
  765. * @param bool
  766. * @return string
  767. */
  768. public function set_select($field = '', $value = '', $default = FALSE)
  769. {
  770. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  771. {
  772. return ($default === TRUE && count($this->_field_data) === 0) ? ' selected="selected"' : '';
  773. }
  774. $field = $this->_field_data[$field]['postdata'];
  775. if (is_array($field))
  776. {
  777. if ( ! in_array($value, $field))
  778. {
  779. return '';
  780. }
  781. }
  782. elseif (($field === '' OR $value === '') OR ($field !== $value))
  783. {
  784. return '';
  785. }
  786. return ' selected="selected"';
  787. }
  788. // --------------------------------------------------------------------
  789. /**
  790. * Set Radio
  791. *
  792. * Enables radio buttons to be set to the value the user
  793. * selected in the event of an error
  794. *
  795. * @param string
  796. * @param string
  797. * @param bool
  798. * @return string
  799. */
  800. public function set_radio($field = '', $value = '', $default = FALSE)
  801. {
  802. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  803. {
  804. return ($default === TRUE && count($this->_field_data) === 0) ? ' checked="checked"' : '';
  805. }
  806. $field = $this->_field_data[$field]['postdata'];
  807. if (is_array($field))
  808. {
  809. if ( ! in_array($value, $field))
  810. {
  811. return '';
  812. }
  813. }
  814. elseif (($field === '' OR $value === '') OR ($field !== $value))
  815. {
  816. return '';
  817. }
  818. return ' checked="checked"';
  819. }
  820. // --------------------------------------------------------------------
  821. /**
  822. * Set Checkbox
  823. *
  824. * Enables checkboxes to be set to the value the user
  825. * selected in the event of an error
  826. *
  827. * @param string
  828. * @param string
  829. * @param bool
  830. * @return string
  831. */
  832. public function set_checkbox($field = '', $value = '', $default = FALSE)
  833. {
  834. // Logic is exactly the same as for radio fields
  835. return $this->set_radio($field, $value, $default);
  836. }
  837. // --------------------------------------------------------------------
  838. /**
  839. * Required
  840. *
  841. * @param string
  842. * @return bool
  843. */
  844. public function required($str)
  845. {
  846. return is_array($str) ? (bool) count($str) : (trim($str) !== '');
  847. }
  848. // --------------------------------------------------------------------
  849. /**
  850. * Performs a Regular Expression match test.
  851. *
  852. * @param string
  853. * @param string regex
  854. * @return bool
  855. */
  856. public function regex_match($str, $regex)
  857. {
  858. return (bool) preg_match($regex, $str);
  859. }
  860. // --------------------------------------------------------------------
  861. /**
  862. * Match one field to another
  863. *
  864. * @param string $str string to compare against
  865. * @param string $field
  866. * @return bool
  867. */
  868. public function matches($str, $field)
  869. {
  870. return isset($this->_field_data[$field], $this->_field_data[$field]['postdata'])
  871. ? ($str === $this->_field_data[$field]['postdata'])
  872. : FALSE;
  873. }
  874. // --------------------------------------------------------------------
  875. /**
  876. * Differs from another field
  877. *
  878. * @param string
  879. * @param string field
  880. * @return bool
  881. */
  882. public function differs($str, $field)
  883. {
  884. return ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str);
  885. }
  886. // --------------------------------------------------------------------
  887. /**
  888. * Is Unique
  889. *
  890. * Check if the input value doesn't already exist
  891. * in the specified database field.
  892. *
  893. * @param string
  894. * @param string field
  895. * @return bool
  896. */
  897. public function is_unique($str, $field)
  898. {
  899. sscanf($field, '%[^.].%[^.]', $table, $field);
  900. if (isset($this->CI->db))
  901. {
  902. $query = $this->CI->db->limit(1)->get_where($table, array($field => $str));
  903. return $query->num_rows() === 0;
  904. }
  905. return FALSE;
  906. }
  907. // --------------------------------------------------------------------
  908. /**
  909. * Minimum Length
  910. *
  911. * @param string
  912. * @param string
  913. * @return bool
  914. */
  915. public function min_length($str, $val)
  916. {
  917. if ( ! is_numeric($val))
  918. {
  919. return FALSE;
  920. }
  921. else
  922. {
  923. $val = (int) $val;
  924. }
  925. return (MB_ENABLED === TRUE)
  926. ? ($val <= mb_strlen($str))
  927. : ($val <= strlen($str));
  928. }
  929. // --------------------------------------------------------------------
  930. /**
  931. * Max Length
  932. *
  933. * @param string
  934. * @param string
  935. * @return bool
  936. */
  937. public function max_length($str, $val)
  938. {
  939. if ( ! is_numeric($val))
  940. {
  941. return FALSE;
  942. }
  943. else
  944. {
  945. $val = (int) $val;
  946. }
  947. return (MB_ENABLED === TRUE)
  948. ? ($val >= mb_strlen($str))
  949. : ($val >= strlen($str));
  950. }
  951. // --------------------------------------------------------------------
  952. /**
  953. * Exact Length
  954. *
  955. * @param string
  956. * @param string
  957. * @return bool
  958. */
  959. public function exact_length($str, $val)
  960. {
  961. if ( ! is_numeric($val))
  962. {
  963. return FALSE;
  964. }
  965. else
  966. {
  967. $val = (int) $val;
  968. }
  969. return (MB_ENABLED === TRUE)
  970. ? (mb_strlen($str) === $val)
  971. : (strlen($str) === $val);
  972. }
  973. // --------------------------------------------------------------------
  974. /**
  975. * Valid URL
  976. *
  977. * @param string $str
  978. * @return bool
  979. */
  980. public function valid_url($str)
  981. {
  982. if (empty($str))
  983. {
  984. return FALSE;
  985. }
  986. elseif (preg_match('/^(?:([^:]*)\:)?\/\/(.+)$/', $str, $matches))
  987. {
  988. if (empty($matches[2]))
  989. {
  990. return FALSE;
  991. }
  992. elseif ( ! in_array($matches[1], array('http', 'https'), TRUE))
  993. {
  994. return FALSE;
  995. }
  996. $str = $matches[2];
  997. }
  998. $str = 'http://'.$str;
  999. // There's a bug affecting PHP 5.2.13, 5.3.2 that considers the
  1000. // underscore to be a valid hostname character instead of a dash.
  1001. // Reference: https://bugs.php.net/bug.php?id=51192
  1002. if (version_compare(PHP_VERSION, '5.2.13', '==') === 0 OR version_compare(PHP_VERSION, '5.3.2', '==') === 0)
  1003. {
  1004. sscanf($str, 'http://%[^/]', $host);
  1005. $str = substr_replace($str, strtr($host, array('_' => '-', '-' => '_')), 7, strlen($host));
  1006. }
  1007. return (filter_var($str, FILTER_VALIDATE_URL) !== FALSE);
  1008. }
  1009. // --------------------------------------------------------------------
  1010. /**
  1011. * Valid Email
  1012. *
  1013. * @param string
  1014. * @return bool
  1015. */
  1016. public function valid_email($str)
  1017. {
  1018. return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
  1019. }
  1020. // --------------------------------------------------------------------
  1021. /**
  1022. * Valid Emails
  1023. *
  1024. * @param string
  1025. * @return bool
  1026. */
  1027. public function valid_emails($str)
  1028. {
  1029. if (strpos($str, ',') === FALSE)
  1030. {
  1031. return $this->valid_email(trim($str));
  1032. }
  1033. foreach (explode(',', $str) as $email)
  1034. {
  1035. if (trim($email) !== '' && $this->valid_email(trim($email)) === FALSE)
  1036. {
  1037. return FALSE;
  1038. }
  1039. }
  1040. return TRUE;
  1041. }
  1042. // --------------------------------------------------------------------
  1043. /**
  1044. * Validate IP Address
  1045. *
  1046. * @param string
  1047. * @param string 'ipv4' or 'ipv6' to validate a specific IP format
  1048. * @return bool
  1049. */
  1050. public function valid_ip($ip, $which = '')
  1051. {
  1052. return $this->CI->input->valid_ip($ip, $which);
  1053. }
  1054. // --------------------------------------------------------------------
  1055. /**
  1056. * Alpha
  1057. *
  1058. * @param string
  1059. * @return bool
  1060. */
  1061. public function alpha($str)
  1062. {
  1063. return ctype_alpha($str);
  1064. }
  1065. // --------------------------------------------------------------------
  1066. /**
  1067. * Alpha-numeric
  1068. *
  1069. * @param string
  1070. * @return bool
  1071. */
  1072. public function alpha_numeric($str)
  1073. {
  1074. return ctype_alnum((string) $str);
  1075. }
  1076. // --------------------------------------------------------------------
  1077. /**
  1078. * Alpha-numeric with underscores and dashes
  1079. *
  1080. * @param string
  1081. * @return bool
  1082. */
  1083. public function alpha_dash($str)
  1084. {
  1085. return (bool) preg_match('/^[a-z0-9_-]+$/i', $str);
  1086. }
  1087. // --------------------------------------------------------------------
  1088. /**
  1089. * Numeric
  1090. *
  1091. * @param string
  1092. * @return bool
  1093. */
  1094. public function numeric($str)
  1095. {
  1096. return (bool) preg_match('/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
  1097. }
  1098. // --------------------------------------------------------------------
  1099. /**
  1100. * Integer
  1101. *
  1102. * @param string
  1103. * @return bool
  1104. */
  1105. public function integer($str)
  1106. {
  1107. return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
  1108. }
  1109. // --------------------------------------------------------------------
  1110. /**
  1111. * Decimal number
  1112. *
  1113. * @param string
  1114. * @return bool
  1115. */
  1116. public function decimal($str)
  1117. {
  1118. return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
  1119. }
  1120. // --------------------------------------------------------------------
  1121. /**
  1122. * Greater than
  1123. *
  1124. * @param string
  1125. * @param int
  1126. * @return bool
  1127. */
  1128. public function greater_than($str, $min)
  1129. {
  1130. return is_numeric($str) ? ($str > $min) : FALSE;
  1131. }
  1132. // --------------------------------------------------------------------
  1133. /**
  1134. * Equal to or Greater than
  1135. *
  1136. * @param string
  1137. * @param int
  1138. * @return bool
  1139. */
  1140. public function greater_than_equal_to($str, $min)
  1141. {
  1142. return is_numeric($str) ? ($str >= $min) : FALSE;
  1143. }
  1144. // --------------------------------------------------------------------
  1145. /**
  1146. * Less than
  1147. *
  1148. * @param string
  1149. * @param int
  1150. * @return bool
  1151. */
  1152. public function less_than($str, $max)
  1153. {
  1154. return is_numeric($str) ? ($str < $max) : FALSE;
  1155. }
  1156. // --------------------------------------------------------------------
  1157. /**
  1158. * Equal to or Less than
  1159. *
  1160. * @param string
  1161. * @param int
  1162. * @return bool
  1163. */
  1164. public function less_than_equal_to($str, $max)
  1165. {
  1166. return is_numeric($str) ? ($str <= $max) : FALSE;
  1167. }
  1168. // --------------------------------------------------------------------
  1169. /**
  1170. * Is a Natural number (0,1,2,3, etc.)
  1171. *
  1172. * @param string
  1173. * @return bool
  1174. */
  1175. public function is_natural($str)
  1176. {
  1177. return ctype_digit((string) $str);
  1178. }
  1179. // --------------------------------------------------------------------
  1180. /**
  1181. * Is a Natural number, but not a zero (1,2,3, etc.)
  1182. *
  1183. * @param string
  1184. * @return bool
  1185. */
  1186. public function is_natural_no_zero($str)
  1187. {
  1188. return ($str != 0 && ctype_digit((string) $str));
  1189. }
  1190. // --------------------------------------------------------------------
  1191. /**
  1192. * Valid Base64
  1193. *
  1194. * Tests a string for characters outside of the Base64 alphabet
  1195. * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
  1196. *
  1197. * @param string
  1198. * @return bool
  1199. */
  1200. public function valid_base64($str)
  1201. {
  1202. return ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str);
  1203. }
  1204. // --------------------------------------------------------------------
  1205. /**
  1206. * Prep data for form
  1207. *
  1208. * This function allows HTML to be safely shown in a form.
  1209. * Special characters are converted.
  1210. *
  1211. * @param string
  1212. * @return string
  1213. */
  1214. public function prep_for_form($data = '')
  1215. {
  1216. if ($this->_safe_form_data === FALSE OR empty($data))
  1217. {
  1218. return $data;
  1219. }
  1220. if (is_array($data))
  1221. {
  1222. foreach ($data as $key => $val)
  1223. {
  1224. $data[$key] = $this->prep_for_form($val);
  1225. }
  1226. return $data;
  1227. }
  1228. return str_replace(array("'", '"', '<', '>'), array('&#39;', '&quot;', '&lt;', '&gt;'), stripslashes($data));
  1229. }
  1230. // --------------------------------------------------------------------
  1231. /**
  1232. * Prep URL
  1233. *
  1234. * @param string
  1235. * @return string
  1236. */
  1237. public function prep_url($str = '')
  1238. {
  1239. if ($str === 'http://' OR $str === '')
  1240. {
  1241. return '';
  1242. }
  1243. if (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)
  1244. {
  1245. return 'http://'.$str;
  1246. }
  1247. return $str;
  1248. }
  1249. // --------------------------------------------------------------------
  1250. /**
  1251. * Strip Image Tags
  1252. *
  1253. * @param string
  1254. * @return string
  1255. */
  1256. public function strip_image_tags($str)
  1257. {
  1258. return $this->CI->security->strip_image_tags($str);
  1259. }
  1260. // --------------------------------------------------------------------
  1261. /**
  1262. * XSS Clean
  1263. *
  1264. * @param string
  1265. * @return string
  1266. */
  1267. public function xss_clean($str)
  1268. {
  1269. return $this->CI->security->xss_clean($str);
  1270. }
  1271. // --------------------------------------------------------------------
  1272. /**
  1273. * Convert PHP tags to entities
  1274. *
  1275. * @param string
  1276. * @return string
  1277. */
  1278. public function encode_php_tags($str)
  1279. {
  1280. return str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);
  1281. }
  1282. // --------------------------------------------------------------------
  1283. /**
  1284. * Reset validation vars
  1285. *
  1286. * Prevents subsequent validation routines from being affected by the
  1287. * results of any previous validation routine due to the CI singleton.
  1288. *
  1289. * @return void
  1290. */
  1291. public function reset_validation()
  1292. {
  1293. $this->_field_data = array();
  1294. $this->_config_rules = array();
  1295. $this->_error_array = array();
  1296. $this->_error_messages = array();
  1297. $this->error_string = '';
  1298. }
  1299. }
  1300. /* End of file Form_validation.php */
  1301. /* Location: ./system/libraries/Form_validation.php */