PageRenderTime 72ms CodeModel.GetById 44ms RepoModel.GetById 0ms app.codeStats 0ms

/saf/lib/MailForm/Rule.php

https://github.com/cbrunet/sitellite
PHP | 435 lines | 227 code | 15 blank | 193 comment | 109 complexity | f2548e5b4bfe2c09588b0d491c2849f3 MD5 | raw file
Possible License(s): Apache-2.0, GPL-2.0, GPL-3.0, LGPL-2.1
  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | Sitellite - Content Management System |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2007 Simian Systems |
  7. // +----------------------------------------------------------------------+
  8. // | This software is released under the GNU General Public License (GPL) |
  9. // | Please see the accompanying file docs/LICENSE for licensing details. |
  10. // | |
  11. // | You should have received a copy of the GPL Software License along |
  12. // | with this program; if not, write to Simian Systems, 242 Lindsay, |
  13. // | Winnipeg, MB, R3N 1H1, CANADA. The License is also available at |
  14. // | the following web site address: |
  15. // | <http://www.sitellite.org/index/license> |
  16. // +----------------------------------------------------------------------+
  17. // | Authors: John Luxford <lux@simian.ca> |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // Handles validation of form fields for the MailForm package.
  21. //
  22. /**
  23. * Handles validation of form fields for the MailForm package.
  24. *
  25. * Rule Format:
  26. *
  27. * type "value"
  28. *
  29. * Validation Rules:
  30. * - is "value"
  31. * - contains "some value"
  32. * - regex "some regex" -- uses ereg()
  33. * - preg "/some regex/" -- uses preg_match()
  34. * - equals "anotherfield"
  35. * - empty
  36. * - length "6+" (eg: 6, 6+, 6-12, 12-)
  37. * - gt "value"
  38. * - ge "value"
  39. * - lt "value"
  40. * - le "value"
  41. * - func "func_name" (or function "func_name")
  42. * - unique "dbtablename.columnname"
  43. * - exists "path/to/directory"
  44. * - numeric
  45. * - email
  46. * - header
  47. *
  48. * Note: Any rule may be negated by preceeding it with a 'not', for example:
  49. * - not empty
  50. * - not contains "some value"
  51. *
  52. * New in 1.2:
  53. * - Added a 'unique' rule, which compares the value against a specified field
  54. * in a database table.
  55. * - Fixed a bug in the 'length' rule evaluation.
  56. *
  57. * New in 1.4:
  58. * - Added 'exists' and 'not exists' rules, which checks if the value given
  59. * exists (or doesn't) as a file name in the path provided by the rule.
  60. *
  61. * New in 1.6:
  62. * - Abstracted 'not empty' and 'not exists' so that 'not' now negates any
  63. * rule, and 'empty' and 'exists' are ordinary rules now. This required
  64. * the addition of two new methods, _validate(), and _validateNegated(),
  65. * and a new $negated property.
  66. *
  67. * New in 1.8:
  68. * - Added warning notices when rules fail the syntax parser.
  69. * - Added new rule type "numeric", which checks the data type of the value
  70. * to see whether it is a valid number or not.
  71. *
  72. * New in 2.0:
  73. * - New rules: 'email' and 'header' which help prevent form abuse by spammers.
  74. * 'email' checks that it is a valid email, and 'header' checks that there
  75. * are no newlines in the field so that it can't pass extra headers to your
  76. * mail() function.
  77. *
  78. * New in 2.2:
  79. * - New rule 'preg' uses preg_match() instead of ereg(). Be sure to include
  80. * slashes in the regular expression now.
  81. * - Custom validation functions can receive the field name as a second parameter.
  82. * e.g. function custom_validation_rule ($values, $field) {}
  83. *
  84. * <code>
  85. * <?php
  86. *
  87. * $widget = new MF_Widget ('name');
  88. * $widget->addRule ('is "foo"', 'You must enter "foo" to pass!');
  89. *
  90. * // note: MailFormRule is never accessed directly.
  91. *
  92. * ? >
  93. * </code>
  94. *
  95. * @package MailForm
  96. * @author John Luxford <lux@simian.ca>
  97. * @copyright Copyright (C) 2001-2003, Simian Systems Inc.
  98. * @license http://www.sitellite.org/index/license Simian Open Software License
  99. * @version 2.2, 2008-10-25, $Id: Rule.php,v 1.5 2007/10/06 00:06:30 lux Exp $
  100. * @access public
  101. *
  102. */
  103. class MailFormRule {
  104. /**
  105. * The original unmodified rule definition.
  106. *
  107. * @access public
  108. *
  109. */
  110. var $rule;
  111. /**
  112. * The name of the widget.
  113. *
  114. * @access public
  115. *
  116. */
  117. var $name;
  118. /**
  119. * The error message for this rule.
  120. *
  121. * @access public
  122. *
  123. */
  124. var $msg;
  125. /**
  126. * The rule type. Can be 'is', 'contains', 'regex', 'not empty',
  127. * 'equals', 'length', 'gt', 'ge', 'lt', 'le', or 'func'.
  128. *
  129. * @access public
  130. *
  131. */
  132. var $type;
  133. /**
  134. * The rule value. This corresponds to the part of the rule
  135. * in double quotes (ie. type "value").
  136. *
  137. * @access public
  138. *
  139. */
  140. var $value;
  141. /**
  142. * If a 'not' is present at the start of the rule, this will be
  143. * set to true, otherwise false.
  144. *
  145. * @access public
  146. *
  147. */
  148. var $negated = false;
  149. /**
  150. * Constructor Method.
  151. *
  152. * @access public
  153. * @param string $rule
  154. * @param string $name
  155. * @param string $msg
  156. *
  157. */
  158. function MailFormRule ($rule, $name, $msg = '') {
  159. $this->rule = $rule;
  160. $this->name = $name;
  161. if (! empty ($msg)) {
  162. $this->msg = $msg;
  163. } else {
  164. $this->msg = 'Oops! The following field was not filled in correctly: ' . $this->name . '. Please fix this to continue.';
  165. }
  166. $this->parseRuleStatement ($rule);
  167. }
  168. /**
  169. * Parses the original rule into the $type and $value properties.
  170. *
  171. * @access public
  172. * @param string $rule
  173. *
  174. */
  175. function parseRuleStatement ($rule) {
  176. if (preg_match ('/^(not )?(empty|length|unique|contains|func|function|regex|preg|equals|is|gt|lt|ge|le|exists|numeric|email|header)( ("|\')(.*)\4)?$/', $rule, $regs)) {
  177. if ($regs[2] == 'function') {
  178. $this->type = 'func';
  179. } else {
  180. $this->type = $regs[2];
  181. }
  182. if ($regs[1] == 'not ') {
  183. $this->negated = true;
  184. }
  185. $this->value = $regs[5];
  186. } else {
  187. trigger_error ('Invalid MailForm rule (' . $this->name . '): ' . $rule, E_USER_WARNING);
  188. }
  189. }
  190. /**
  191. * Validates the value given against itself. Returns false on
  192. * failure and true on success.
  193. *
  194. * @access public
  195. * @param string $value
  196. * @param object $form
  197. * @param object $cgi
  198. * @return boolean
  199. *
  200. */
  201. function validate ($value, $form, $cgi) {
  202. if ($this->negated) {
  203. return $this->_validateNegated ($value, $form, $cgi);
  204. } else {
  205. return $this->_validate ($value, $form, $cgi);
  206. }
  207. }
  208. /**
  209. * Validates the value given against itself. Returns false on
  210. * failure and true on success.
  211. *
  212. * @access public
  213. * @param string $value
  214. * @param object $form
  215. * @param object $cgi
  216. * @return boolean
  217. *
  218. */
  219. function _validate ($value, $form, $cgi) {
  220. if ($this->type == 'empty') {
  221. if (! empty ($value)) {
  222. return false;
  223. }
  224. } elseif ($this->type == 'length') {
  225. if (preg_match ('/^([0-9]+)([+-]?)([0-9]*)$/', $this->value, $regs)) {
  226. if (! empty ($regs[3])) {
  227. if (strlen ($value) < $regs[1] || strlen ($value) > $regs[3]) {
  228. return false;
  229. }
  230. } elseif ($regs[2] == '+' && strlen ($value) < $regs[1]) {
  231. return false;
  232. } elseif ($regs[2] == '-' && strlen ($value) > $regs[1]) {
  233. return false;
  234. } elseif (empty ($regs[2]) && strlen ($value) != $regs[1]) {
  235. return false;
  236. }
  237. }
  238. } elseif ($this->type == 'unique') {
  239. list ($table, $column) = preg_split ('/[\.:\/]/', $this->value);
  240. global $db;
  241. $res = $db->fetch ('select ' . $column . ' from ' . $table . ' where ' . $column . ' = ??', $value);
  242. if ($db->rows > 0) {
  243. // it's not unique
  244. return false;
  245. } elseif (! $res && $db->error) {
  246. return false;
  247. }
  248. } elseif ($this->type == 'exists') {
  249. if (! empty ($value)) {
  250. if (! @file_exists ($this->value . '/' . $value)) {
  251. // file name does not exist
  252. return false;
  253. }
  254. }
  255. } elseif ($this->type == 'contains') {
  256. if (! stristr ($value, $this->value)) {
  257. return false;
  258. }
  259. } elseif ($this->type == 'func') {
  260. $GLOBALS['mailform_current_form'] =& $form;
  261. $func = $this->value;
  262. if (! $func ($form->getValues ($cgi), $this->name)) {
  263. return false;
  264. }
  265. } elseif ($this->type == 'regex') {
  266. if (! ereg ($this->value, $value)) {
  267. return false;
  268. }
  269. } elseif ($this->type == 'preg') {
  270. if (! preg_match ($this->value, $value)) {
  271. return false;
  272. }
  273. } elseif ($this->type == 'equals') {
  274. if ($value != $form->widgets[$this->value]->getValue ($cgi)) {
  275. return false;
  276. }
  277. } elseif ($this->type == 'is') {
  278. if ($value != $this->value) {
  279. return false;
  280. }
  281. } elseif ($this->type == 'gt') {
  282. if ($value <= $this->value) {
  283. return false;
  284. }
  285. } elseif ($this->type == 'lt') {
  286. if ($value >= $this->value) {
  287. return false;
  288. }
  289. } elseif ($this->type == 'ge') {
  290. if ($value < $this->value) {
  291. return false;
  292. }
  293. } elseif ($this->type == 'le') {
  294. if ($value > $this->value) {
  295. return false;
  296. }
  297. } elseif ($this->type == 'numeric') {
  298. if (! is_numeric ($value)) {
  299. return false;
  300. }
  301. } elseif ($this->type == 'email') {
  302. if (strpos ($value, '.@') !== false) {
  303. return false;
  304. } elseif (preg_match ('/\.$/', $value)) {
  305. return false;
  306. } elseif (! preg_match ("/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+\.([a-zA-Z0-9\._-]+)+$/" , $value)) {
  307. return false;
  308. }
  309. } elseif ($this->type == 'header') {
  310. if (preg_match ("/[\r\n]/s" , $value)) {
  311. return false;
  312. }
  313. }
  314. return true;
  315. }
  316. /**
  317. * Validates the value given against itself. Returns false on
  318. * failure and true on success.
  319. *
  320. * @access public
  321. * @param string $value
  322. * @param object $form
  323. * @param object $cgi
  324. * @return boolean
  325. *
  326. */
  327. function _validateNegated ($value, $form, $cgi) {
  328. if ($this->type == 'empty') {
  329. if (empty ($value)) {
  330. return false;
  331. }
  332. } elseif ($this->type == 'length') {
  333. if (preg_match ('/^([0-9]+)([+-]?)([0-9]*)$/', $this->value, $regs)) {
  334. if (! empty ($regs[3])) {
  335. if (strlen ($value) >= $regs[1] || strlen ($value) <= $regs[3]) {
  336. return false;
  337. }
  338. } elseif ($regs[2] == '+' && strlen ($value) >= $regs[1]) {
  339. return false;
  340. } elseif ($regs[2] == '-' && strlen ($value) <= $regs[1]) {
  341. return false;
  342. } elseif (empty ($regs[2]) && strlen ($value) == $regs[1]) {
  343. return false;
  344. }
  345. }
  346. } elseif ($this->type == 'unique') {
  347. list ($table, $column) = preg_split ('/[\.:\/]/', $this->value);
  348. global $db;
  349. $res = $db->fetch ('select ' . $column . ' from ' . $table . ' where ' . $column . ' = ??', $value);
  350. if ($db->rows <= 0) {
  351. // it's not unique
  352. return false;
  353. } elseif (! $res && $db->error) {
  354. return false;
  355. }
  356. } elseif ($this->type == 'exists') {
  357. if (! empty ($value)) {
  358. if (@file_exists ($this->value . '/' . $value)) {
  359. // file name does not exist
  360. return false;
  361. }
  362. }
  363. } elseif ($this->type == 'contains') {
  364. if (stristr ($value, $this->value)) {
  365. return false;
  366. }
  367. } elseif ($this->type == 'func') {
  368. $func = $this->value;
  369. if ($func ($form->getValues ($cgi), $this->name)) {
  370. return false;
  371. }
  372. } elseif ($this->type == 'regex') {
  373. if (ereg ($this->value, $value)) {
  374. return false;
  375. }
  376. } elseif ($this->type == 'preg') {
  377. if (preg_match ($this->value, $value)) {
  378. return false;
  379. }
  380. } elseif ($this->type == 'equals') {
  381. if ($value == $form->widgets[$this->value]->getValue ($cgi)) {
  382. return false;
  383. }
  384. } elseif ($this->type == 'is') {
  385. if ($value == $this->value) {
  386. return false;
  387. }
  388. } elseif ($this->type == 'gt') {
  389. if ($value > $this->value) {
  390. return false;
  391. }
  392. } elseif ($this->type == 'lt') {
  393. if ($value < $this->value) {
  394. return false;
  395. }
  396. } elseif ($this->type == 'ge') {
  397. if ($value >= $this->value) {
  398. return false;
  399. }
  400. } elseif ($this->type == 'le') {
  401. if ($value <= $this->value) {
  402. return false;
  403. }
  404. } elseif ($this->type == 'numeric') {
  405. if (is_numeric ($value)) {
  406. return false;
  407. }
  408. } elseif ($this->type == 'email') {
  409. if (strpos ($value, '.@') === false && ! preg_match ('/\.$/', $value) && preg_match ("/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+\.([a-zA-Z0-9\._-]+)+$/" , $value)) {
  410. return false;
  411. }
  412. } elseif ($this->type == 'header') {
  413. if (! preg_match ("/[\r\n]/s" , $value)) {
  414. return false;
  415. }
  416. }
  417. return true;
  418. }
  419. }
  420. ?>