PageRenderTime 50ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/system/libraries/Form_validation.php

https://github.com/coderkid/No-CMS
PHP | 1540 lines | 734 code | 203 blank | 603 comment | 99 complexity | 10e417706e38c3067429c446da546519 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, GPL-2.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 - 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 errors, 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 ($row['postdata'] !== NULL)
  447. {
  448. if ($row['is_array'] === FALSE)
  449. {
  450. if (isset($_POST[$row['field']]))
  451. {
  452. $_POST[$row['field']] = $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] = $v;
  477. }
  478. $post_ref = $array;
  479. }
  480. else
  481. {
  482. $post_ref = $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) && ($postdata === NULL OR $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 (($postdata === NULL OR $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. * Checks if the rule is present within the validator
  734. *
  735. * Permits you to check if a rule is present within the validator
  736. *
  737. * @param string the field name
  738. * @return bool
  739. */
  740. public function has_rule($field)
  741. {
  742. return isset($this->_field_data[$field]);
  743. }
  744. // --------------------------------------------------------------------
  745. /**
  746. * Get the value from a form
  747. *
  748. * Permits you to repopulate a form field with the value it was submitted
  749. * with, or, if that value doesn't exist, with the default
  750. *
  751. * @param string the field name
  752. * @param string
  753. * @return string
  754. */
  755. public function set_value($field = '', $default = '')
  756. {
  757. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  758. {
  759. return $default;
  760. }
  761. // If the data is an array output them one at a time.
  762. // E.g: form_input('name[]', set_value('name[]');
  763. if (is_array($this->_field_data[$field]['postdata']))
  764. {
  765. return array_shift($this->_field_data[$field]['postdata']);
  766. }
  767. return $this->_field_data[$field]['postdata'];
  768. }
  769. // --------------------------------------------------------------------
  770. /**
  771. * Set Select
  772. *
  773. * Enables pull-down lists to be set to the value the user
  774. * selected in the event of an error
  775. *
  776. * @param string
  777. * @param string
  778. * @param bool
  779. * @return string
  780. */
  781. public function set_select($field = '', $value = '', $default = FALSE)
  782. {
  783. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  784. {
  785. return ($default === TRUE && count($this->_field_data) === 0) ? ' selected="selected"' : '';
  786. }
  787. $field = $this->_field_data[$field]['postdata'];
  788. $value = (string) $value;
  789. if (is_array($field))
  790. {
  791. // Note: in_array('', array(0)) returns TRUE, do not use it
  792. foreach ($field as &$v)
  793. {
  794. if ($value === $v)
  795. {
  796. return ' selected="selected"';
  797. }
  798. }
  799. return '';
  800. }
  801. elseif (($field === '' OR $value === '') OR ($field !== $value))
  802. {
  803. return '';
  804. }
  805. return ' selected="selected"';
  806. }
  807. // --------------------------------------------------------------------
  808. /**
  809. * Set Radio
  810. *
  811. * Enables radio buttons to be set to the value the user
  812. * selected in the event of an error
  813. *
  814. * @param string
  815. * @param string
  816. * @param bool
  817. * @return string
  818. */
  819. public function set_radio($field = '', $value = '', $default = FALSE)
  820. {
  821. if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
  822. {
  823. return ($default === TRUE && count($this->_field_data) === 0) ? ' checked="checked"' : '';
  824. }
  825. $field = $this->_field_data[$field]['postdata'];
  826. $value = (string) $value;
  827. if (is_array($field))
  828. {
  829. // Note: in_array('', array(0)) returns TRUE, do not use it
  830. foreach ($field as &$v)
  831. {
  832. if ($value === $v)
  833. {
  834. return ' checked="checked"';
  835. }
  836. }
  837. return '';
  838. }
  839. elseif (($field === '' OR $value === '') OR ($field !== $value))
  840. {
  841. return '';
  842. }
  843. return ' checked="checked"';
  844. }
  845. // --------------------------------------------------------------------
  846. /**
  847. * Set Checkbox
  848. *
  849. * Enables checkboxes to be set to the value the user
  850. * selected in the event of an error
  851. *
  852. * @param string
  853. * @param string
  854. * @param bool
  855. * @return string
  856. */
  857. public function set_checkbox($field = '', $value = '', $default = FALSE)
  858. {
  859. // Logic is exactly the same as for radio fields
  860. return $this->set_radio($field, $value, $default);
  861. }
  862. // --------------------------------------------------------------------
  863. /**
  864. * Required
  865. *
  866. * @param string
  867. * @return bool
  868. */
  869. public function required($str)
  870. {
  871. return is_array($str) ? (bool) count($str) : (trim($str) !== '');
  872. }
  873. // --------------------------------------------------------------------
  874. /**
  875. * Performs a Regular Expression match test.
  876. *
  877. * @param string
  878. * @param string regex
  879. * @return bool
  880. */
  881. public function regex_match($str, $regex)
  882. {
  883. return (bool) preg_match($regex, $str);
  884. }
  885. // --------------------------------------------------------------------
  886. /**
  887. * Match one field to another
  888. *
  889. * @param string $str string to compare against
  890. * @param string $field
  891. * @return bool
  892. */
  893. public function matches($str, $field)
  894. {
  895. return isset($this->_field_data[$field], $this->_field_data[$field]['postdata'])
  896. ? ($str === $this->_field_data[$field]['postdata'])
  897. : FALSE;
  898. }
  899. // --------------------------------------------------------------------
  900. /**
  901. * Differs from another field
  902. *
  903. * @param string
  904. * @param string field
  905. * @return bool
  906. */
  907. public function differs($str, $field)
  908. {
  909. return ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str);
  910. }
  911. // --------------------------------------------------------------------
  912. /**
  913. * Is Unique
  914. *
  915. * Check if the input value doesn't already exist
  916. * in the specified database field.
  917. *
  918. * @param string
  919. * @param string field
  920. * @return bool
  921. */
  922. public function is_unique($str, $field)
  923. {
  924. sscanf($field, '%[^.].%[^.]', $table, $field);
  925. if (isset($this->CI->db))
  926. {
  927. $query = $this->CI->db->limit(1)->get_where($table, array($field => $str));
  928. return $query->num_rows() === 0;
  929. }
  930. return FALSE;
  931. }
  932. // --------------------------------------------------------------------
  933. /**
  934. * Minimum Length
  935. *
  936. * @param string
  937. * @param string
  938. * @return bool
  939. */
  940. public function min_length($str, $val)
  941. {
  942. if ( ! is_numeric($val))
  943. {
  944. return FALSE;
  945. }
  946. else
  947. {
  948. $val = (int) $val;
  949. }
  950. return (MB_ENABLED === TRUE)
  951. ? ($val <= mb_strlen($str))
  952. : ($val <= strlen($str));
  953. }
  954. // --------------------------------------------------------------------
  955. /**
  956. * Max Length
  957. *
  958. * @param string
  959. * @param string
  960. * @return bool
  961. */
  962. public function max_length($str, $val)
  963. {
  964. if ( ! is_numeric($val))
  965. {
  966. return FALSE;
  967. }
  968. else
  969. {
  970. $val = (int) $val;
  971. }
  972. return (MB_ENABLED === TRUE)
  973. ? ($val >= mb_strlen($str))
  974. : ($val >= strlen($str));
  975. }
  976. // --------------------------------------------------------------------
  977. /**
  978. * Exact Length
  979. *
  980. * @param string
  981. * @param string
  982. * @return bool
  983. */
  984. public function exact_length($str, $val)
  985. {
  986. if ( ! is_numeric($val))
  987. {
  988. return FALSE;
  989. }
  990. else
  991. {
  992. $val = (int) $val;
  993. }
  994. return (MB_ENABLED === TRUE)
  995. ? (mb_strlen($str) === $val)
  996. : (strlen($str) === $val);
  997. }
  998. // --------------------------------------------------------------------
  999. /**
  1000. * Valid URL
  1001. *
  1002. * @param string $str
  1003. * @return bool
  1004. */
  1005. public function valid_url($str)
  1006. {
  1007. if (empty($str))
  1008. {
  1009. return FALSE;
  1010. }
  1011. elseif (preg_match('/^(?:([^:]*)\:)?\/\/(.+)$/', $str, $matches))
  1012. {
  1013. if (empty($matches[2]))
  1014. {
  1015. return FALSE;
  1016. }
  1017. elseif ( ! in_array($matches[1], array('http', 'https'), TRUE))
  1018. {
  1019. return FALSE;
  1020. }
  1021. $str = $matches[2];
  1022. }
  1023. $str = 'http://'.$str;
  1024. // There's a bug affecting PHP 5.2.13, 5.3.2 that considers the
  1025. // underscore to be a valid hostname character instead of a dash.
  1026. // Reference: https://bugs.php.net/bug.php?id=51192
  1027. if (version_compare(PHP_VERSION, '5.2.13', '==') === 0 OR version_compare(PHP_VERSION, '5.3.2', '==') === 0)
  1028. {
  1029. sscanf($str, 'http://%[^/]', $host);
  1030. $str = substr_replace($str, strtr($host, array('_' => '-', '-' => '_')), 7, strlen($host));
  1031. }
  1032. return (filter_var($str, FILTER_VALIDATE_URL) !== FALSE);
  1033. }
  1034. // --------------------------------------------------------------------
  1035. /**
  1036. * Valid Email
  1037. *
  1038. * @param string
  1039. * @return bool
  1040. */
  1041. public function valid_email($str)
  1042. {
  1043. return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
  1044. }
  1045. // --------------------------------------------------------------------
  1046. /**
  1047. * Valid Emails
  1048. *
  1049. * @param string
  1050. * @return bool
  1051. */
  1052. public function valid_emails($str)
  1053. {
  1054. if (strpos($str, ',') === FALSE)
  1055. {
  1056. return $this->valid_email(trim($str));
  1057. }
  1058. foreach (explode(',', $str) as $email)
  1059. {
  1060. if (trim($email) !== '' && $this->valid_email(trim($email)) === FALSE)
  1061. {
  1062. return FALSE;
  1063. }
  1064. }
  1065. return TRUE;
  1066. }
  1067. // --------------------------------------------------------------------
  1068. /**
  1069. * Validate IP Address
  1070. *
  1071. * @param string
  1072. * @param string 'ipv4' or 'ipv6' to validate a specific IP format
  1073. * @return bool
  1074. */
  1075. public function valid_ip($ip, $which = '')
  1076. {
  1077. return $this->CI->input->valid_ip($ip, $which);
  1078. }
  1079. // --------------------------------------------------------------------
  1080. /**
  1081. * Alpha
  1082. *
  1083. * @param string
  1084. * @return bool
  1085. */
  1086. public function alpha($str)
  1087. {
  1088. return ctype_alpha($str);
  1089. }
  1090. // --------------------------------------------------------------------
  1091. /**
  1092. * Alpha-numeric
  1093. *
  1094. * @param string
  1095. * @return bool
  1096. */
  1097. public function alpha_numeric($str)
  1098. {
  1099. return ctype_alnum((string) $str);
  1100. }
  1101. // --------------------------------------------------------------------
  1102. /**
  1103. * Alpha-numeric w/ spaces
  1104. *
  1105. * @param string
  1106. * @return bool
  1107. */
  1108. public function alpha_numeric_spaces($str)
  1109. {
  1110. return (bool) preg_match('/^[A-Z0-9 ]+$/i', $str);
  1111. }
  1112. // --------------------------------------------------------------------
  1113. /**
  1114. * Alpha-numeric with underscores and dashes
  1115. *
  1116. * @param string
  1117. * @return bool
  1118. */
  1119. public function alpha_dash($str)
  1120. {
  1121. return (bool) preg_match('/^[a-z0-9_-]+$/i', $str);
  1122. }
  1123. // --------------------------------------------------------------------
  1124. /**
  1125. * Numeric
  1126. *
  1127. * @param string
  1128. * @return bool
  1129. */
  1130. public function numeric($str)
  1131. {
  1132. return (bool) preg_match('/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
  1133. }
  1134. // --------------------------------------------------------------------
  1135. /**
  1136. * Integer
  1137. *
  1138. * @param string
  1139. * @return bool
  1140. */
  1141. public function integer($str)
  1142. {
  1143. return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
  1144. }
  1145. // --------------------------------------------------------------------
  1146. /**
  1147. * Decimal number
  1148. *
  1149. * @param string
  1150. * @return bool
  1151. */
  1152. public function decimal($str)
  1153. {
  1154. return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
  1155. }
  1156. // --------------------------------------------------------------------
  1157. /**
  1158. * Greater than
  1159. *
  1160. * @param string
  1161. * @param int
  1162. * @return bool
  1163. */
  1164. public function greater_than($str, $min)
  1165. {
  1166. return is_numeric($str) ? ($str > $min) : FALSE;
  1167. }
  1168. // --------------------------------------------------------------------
  1169. /**
  1170. * Equal to or Greater than
  1171. *
  1172. * @param string
  1173. * @param int
  1174. * @return bool
  1175. */
  1176. public function greater_than_equal_to($str, $min)
  1177. {
  1178. return is_numeric($str) ? ($str >= $min) : FALSE;
  1179. }
  1180. // --------------------------------------------------------------------
  1181. /**
  1182. * Less than
  1183. *
  1184. * @param string
  1185. * @param int
  1186. * @return bool
  1187. */
  1188. public function less_than($str, $max)
  1189. {
  1190. return is_numeric($str) ? ($str < $max) : FALSE;
  1191. }
  1192. // --------------------------------------------------------------------
  1193. /**
  1194. * Equal to or Less than
  1195. *
  1196. * @param string
  1197. * @param int
  1198. * @return bool
  1199. */
  1200. public function less_than_equal_to($str, $max)
  1201. {
  1202. return is_numeric($str) ? ($str <= $max) : FALSE;
  1203. }
  1204. // --------------------------------------------------------------------
  1205. /**
  1206. * Is a Natural number (0,1,2,3, etc.)
  1207. *
  1208. * @param string
  1209. * @return bool
  1210. */
  1211. public function is_natural($str)
  1212. {
  1213. return ctype_digit((string) $str);
  1214. }
  1215. // --------------------------------------------------------------------
  1216. /**
  1217. * Is a Natural number, but not a zero (1,2,3, etc.)
  1218. *
  1219. * @param string
  1220. * @return bool
  1221. */
  1222. public function is_natural_no_zero($str)
  1223. {
  1224. return ($str != 0 && ctype_digit((string) $str));
  1225. }
  1226. // --------------------------------------------------------------------
  1227. /**
  1228. * Valid Base64
  1229. *
  1230. * Tests a string for characters outside of the Base64 alphabet
  1231. * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
  1232. *
  1233. * @param string
  1234. * @return bool
  1235. */
  1236. public function valid_base64($str)
  1237. {
  1238. return (base64_encode(base64_decode($str)) === $str);
  1239. }
  1240. // --------------------------------------------------------------------
  1241. /**
  1242. * Prep data for form
  1243. *
  1244. * This function allows HTML to be safely shown in a form.
  1245. * Special characters are converted.
  1246. *
  1247. * @param string
  1248. * @return string
  1249. */
  1250. public function prep_for_form($data = '')
  1251. {
  1252. if ($this->_safe_form_data === FALSE OR empty($data))
  1253. {
  1254. return $data;
  1255. }
  1256. if (is_array($data))
  1257. {
  1258. foreach ($data as $key => $val)
  1259. {
  1260. $data[$key] = $this->prep_for_form($val);
  1261. }
  1262. return $data;
  1263. }
  1264. return str_replace(array("'", '"', '<', '>'), array('&#39;', '&quot;', '&lt;', '&gt;'), stripslashes($data));
  1265. }
  1266. // --------------------------------------------------------------------
  1267. /**
  1268. * Prep URL
  1269. *
  1270. * @param string
  1271. * @return string
  1272. */
  1273. public function prep_url($str = '')
  1274. {
  1275. if ($str === 'http://' OR $str === '')
  1276. {
  1277. return '';
  1278. }
  1279. if (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)
  1280. {
  1281. return 'http://'.$str;
  1282. }
  1283. return $str;
  1284. }
  1285. // --------------------------------------------------------------------
  1286. /**
  1287. * Strip Image Tags
  1288. *
  1289. * @param string
  1290. * @return string
  1291. */
  1292. public function strip_image_tags($str)
  1293. {
  1294. return $this->CI->security->strip_image_tags($str);
  1295. }
  1296. // --------------------------------------------------------------------
  1297. /**
  1298. * XSS Clean
  1299. *
  1300. * @param string
  1301. * @return string
  1302. */
  1303. public function xss_clean($str)
  1304. {
  1305. return $this->CI->security->xss_clean($str);
  1306. }
  1307. // --------------------------------------------------------------------
  1308. /**
  1309. * Convert PHP tags to entities
  1310. *
  1311. * @param string
  1312. * @return string
  1313. */
  1314. public function encode_php_tags($str)
  1315. {
  1316. return str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);
  1317. }
  1318. // --------------------------------------------------------------------
  1319. /**
  1320. * Reset validation vars
  1321. *
  1322. * Prevents subsequent validation routines from being affected by the
  1323. * results of any previous validation routine due to the CI singleton.
  1324. *
  1325. * @return void
  1326. */
  1327. public function reset_validation()
  1328. {
  1329. $this->_field_data = array();
  1330. $this->_config_rules = array();
  1331. $this->_error_array = array();
  1332. $this->_error_messages = array();
  1333. $this->error_string = '';
  1334. }
  1335. }
  1336. /* End of file Form_validation.php */
  1337. /* Location: ./system/libraries/Form_validation.php */