PageRenderTime 55ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/saf/lib/MailForm/Rule.php

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