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

/sources/DataValidate.class.php

https://github.com/Arantor/Elkarte
PHP | 797 lines | 386 code | 86 blank | 325 comment | 55 complexity | ec0ec9d1c20596167c2f1de4f79407b0 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  1. <?php
  2. /**
  3. * @name ElkArte Forum
  4. * @copyright ElkArte Forum contributors
  5. * @license BSD http://opensource.org/licenses/BSD-3-Clause
  6. *
  7. * @version 1.0 Alpha
  8. *
  9. */
  10. if (!defined('ELKARTE'))
  11. die('No access...');
  12. /**
  13. * Class used to validate and transform data
  14. *
  15. * Set the rule(s)
  16. * sanitation_rules()
  17. * sanitation_rules(array(
  18. * 'username' => 'trim|uppercase',
  19. * 'email' => 'trim|email_normalize',
  20. * ));
  21. *
  22. * validation_rules()
  23. * validation_rules(array(
  24. * 'username' => 'required|alpha_numeric|max_length[10]|min_length[6]',
  25. * 'email' => 'required|valid_email',
  26. * ));
  27. *
  28. * Run the validation
  29. * validation_run($data);
  30. * $data must be an array with keys matching the validation rule e.g. $data['username'], $data['password']
  31. *
  32. * Get the results
  33. * validation_errors()
  34. * validation_data()
  35. *
  36. * Current validation can be one or a combination of:
  37. * max_length[x], min_length[x], length[x],
  38. * alpha, alpha_numeric, alpha_dash
  39. * numeric, integer, boolean, float,
  40. * valid_url, valid_ip, valid_ipv6, valid_email,
  41. * contains[x,y,x], required
  42. */
  43. class data_Validate
  44. {
  45. /**
  46. * Validation rules
  47. */
  48. protected $validation_rules = array();
  49. /**
  50. * Sanitation rules
  51. */
  52. protected $sanitation_rules = array();
  53. /**
  54. * Holds validation errors
  55. */
  56. protected $validation_errors = array();
  57. /**
  58. * Holds our data
  59. */
  60. protected $data = array();
  61. /**
  62. * Stict data processing,
  63. * if true drops data for which no sanitation rule was set
  64. */
  65. protected $strict = false;
  66. /**
  67. * Set the validation rules that will be run against the data
  68. *
  69. * @param array $rules
  70. * @return array
  71. */
  72. public function validation_rules($rules = array())
  73. {
  74. // If its not an array, make it one
  75. if (!is_array($rules))
  76. $rules = array($rules);
  77. // Set the validation rules
  78. if (!empty($rules))
  79. $this->validation_rules = $rules;
  80. else
  81. return $this->validation_rules;
  82. }
  83. /**
  84. * Sets the sanitation rules used to clean data
  85. *
  86. * @param array $rules
  87. * @param boolean $strict
  88. * @return array
  89. */
  90. public function sanitation_rules($rules = array(), $strict = false)
  91. {
  92. // If its not an array, make it one
  93. if (!is_array($rules))
  94. $rules = array($rules);
  95. // Set the sanitation rules
  96. $this->strict = $strict;
  97. if (!empty($rules))
  98. $this->sanitation_rules = $rules;
  99. else
  100. return $this->sanitation_rules;
  101. }
  102. /**
  103. * Run the sanitation and validation on the data
  104. *
  105. * @param array $input
  106. * @return boolean
  107. */
  108. public function validate($input)
  109. {
  110. if (!is_array($input))
  111. $input = array($input);
  112. // Clean em
  113. $this->data = $this->_sanitize($input, $this->sanitation_rules());
  114. // Check em
  115. return $this->_validate($this->data, $this->validation_rules);
  116. }
  117. /**
  118. * Return errors
  119. *
  120. * @return array
  121. */
  122. public function validation_errors()
  123. {
  124. return $this->_get_error_messages();
  125. }
  126. /**
  127. * Return data
  128. *
  129. * @return array
  130. */
  131. public function validation_data()
  132. {
  133. return $this->data;
  134. }
  135. /**
  136. * Performs data validation against the provided rule
  137. *
  138. * @param mixed $input
  139. * @param array $ruleset
  140. * @return mixed
  141. */
  142. private function _validate($input, $ruleset)
  143. {
  144. // No errors ... yet ;)
  145. $this->validation_errors = array();
  146. // For each field, run our rules against the data
  147. foreach ($ruleset as $field => $rules)
  148. {
  149. // Get rules for this field
  150. $rules = explode('|', $rules);
  151. foreach ($rules as $rule)
  152. {
  153. $validation_method = null;
  154. $validation_parameters = null;
  155. // Were any parameters provided for the rule, e.g. min_length[6]
  156. if (preg_match('~(.*)\[(.*)\]~', $rule, $match))
  157. {
  158. $validation_method = '_validate_' . $match[1];
  159. $validation_parameters = $match[2];
  160. }
  161. // Or just a predefined rule e.g. valid_email
  162. else
  163. $validation_method = '_validate_' . $rule;
  164. // Time to validate
  165. $result = array();
  166. if (is_callable(array($this, $validation_method)))
  167. $result = $this->$validation_method($field, $input, $validation_parameters);
  168. else
  169. $result = array(
  170. 'field' => $validation_method,
  171. 'input' => $input[$field],
  172. 'function' => '_validate_invalid_function',
  173. 'param' => $validation_parameters
  174. );
  175. if (is_array($result))
  176. $this->validation_errors[] = $result;
  177. }
  178. }
  179. return count($this->validation_errors) === 0 ? true : false;
  180. }
  181. /**
  182. * Data sanitation is a good thing
  183. *
  184. * @param mixed $input
  185. * @param array $ruleset
  186. * @return mixed
  187. */
  188. private function _sanitize($input, $ruleset)
  189. {
  190. // For each field, run our set of rules against the data
  191. foreach ($ruleset as $field => $rules)
  192. {
  193. // data for which we don't have rules
  194. if (!array_key_exists($field, $input))
  195. {
  196. if ($this->strict)
  197. unset($input[$field]);
  198. continue;
  199. }
  200. // Rules for which we do have data
  201. $rules = explode('|', $rules);
  202. foreach ($rules as $rule)
  203. {
  204. // Set the method
  205. $sanitation_method = '_sanitation_' . $rule;
  206. // Defined method to use?
  207. if (is_callable(array($this, $sanitation_method)))
  208. $input[$field] = $this->$sanitation_method($input[$field]);
  209. // Maybe its a built in php function?
  210. elseif (function_exists($rule))
  211. $input[$field] = $rule($input[$field]);
  212. else
  213. {
  214. $input[$field] = $input[$field];
  215. // @todo fatal_error or other ? being asked to do something we dont know?
  216. }
  217. }
  218. }
  219. return $input;
  220. }
  221. /**
  222. * Process any errors and return the error strings
  223. *
  224. * @return array
  225. * @return string
  226. */
  227. private function _get_error_messages()
  228. {
  229. global $txt;
  230. if (empty($this->validation_errors))
  231. return;
  232. loadLanguage('Validation');
  233. $result = array();
  234. foreach ($this->validation_errors as $error)
  235. {
  236. // Set the error message for this validation failure
  237. if (isset($txt[$error['function']]))
  238. {
  239. if ($error['param'] !== false)
  240. $result[] = sprintf($txt[$error['function']], $error['field'], $error['param']);
  241. else
  242. $result[] = sprintf($txt[$error['function']], $error['field'], $error['input']);
  243. }
  244. }
  245. return $result;
  246. }
  247. //
  248. // Start of validation functions
  249. //
  250. /**
  251. * Contains ... Verify that a value is contained within a list
  252. *
  253. * Usage: '[key]' => 'contains[value,value,value]'
  254. *
  255. * @param string $field
  256. * @param array $input
  257. * @param array or null $validation_parameters
  258. * @return mixed
  259. */
  260. protected function _validate_contains($field, $input, $validation_parameters = null)
  261. {
  262. $validation_parameters = explode(',', trim(strtolower($validation_parameters)));
  263. $value = trim(strtolower($input[$field]));
  264. if (in_array($value, $validation_parameters))
  265. return;
  266. return array(
  267. 'field' => $field,
  268. 'input' => $input[$field],
  269. 'function' => __FUNCTION__,
  270. 'param' => implode(',', $validation_parameters)
  271. );
  272. }
  273. /**
  274. * required ... Check if the specified key is present and not empty
  275. *
  276. * Usage: '[key]' => 'required'
  277. *
  278. * @param string $field
  279. * @param array $input
  280. * @param array or null $validation_parameters
  281. * @return mixed
  282. */
  283. protected function _validate_required($field, $input, $validation_parameters = null)
  284. {
  285. if (isset($input[$field]) && trim($input[$field]) !== '')
  286. return;
  287. return array(
  288. 'field' => $field,
  289. 'input' => $input[$field],
  290. 'function' => __FUNCTION__,
  291. 'param' => $validation_parameters
  292. );
  293. }
  294. /**
  295. * valid_email .... Determine if the provided email is valid
  296. *
  297. * Usage: '[key]' => 'valid_email'
  298. *
  299. * @param string $field
  300. * @param array $input
  301. * @param array or null $validation_parameters
  302. * @return mixed
  303. */
  304. protected function _validate_valid_email($field, $input, $validation_parameters = null)
  305. {
  306. if (!isset($input[$field]))
  307. return;
  308. $valid = true;
  309. $at_index = strrpos($input[$field], '@');
  310. // No @ in the email
  311. if ($at_index === false)
  312. $valid = false;
  313. else
  314. {
  315. // Time to do some checking on the local@domain parts
  316. // http://www.linuxjournal.com/article/9585
  317. $local = substr($input[$field], 0, $at_index);
  318. $local_len = strlen($local);
  319. $domain = substr($input[$field], $at_index + 1);
  320. $domain_len = strlen($domain);
  321. /* Some RFC 2822 email "rules" ...
  322. * - Uppercase and lowercase English letters (a–z, A–Z)
  323. * - Digits 0 to 9
  324. * - Characters !#$%&'*+-/=?^_`{|}~
  325. * - Character . provided that it is not the first/last and that it does not appear two or more times consecutively
  326. * - Special characters Space "(),:;<>@[\] provided they are contained between quotation marks, and that 2 of them, the
  327. * backslash \ and quotation mark ", must also be preceded by a backslash \ (e.g. "\\\"").
  328. */
  329. // local part length problems (RFC 2821)
  330. if ($local_len === 0 || $local_len > 64)
  331. $valid = false;
  332. // local part starts or ends with a '.' (RFC 2822)
  333. elseif ($local[0] === '.' || $local[$local_len - 1] === '.')
  334. $valid = false;
  335. // local part has two consecutive dots (RFC 2822)
  336. elseif (preg_match('~\\.\\.~', $local))
  337. $valid = false;
  338. // domain part length problems (RFC 2821)
  339. elseif ($domain_len === 0 || $domain_len > 255)
  340. $valid = false;
  341. // character not valid in domain part (RFC 1035)
  342. elseif (!preg_match('~^[A-Za-z0-9\\-\\.]+$~', $domain))
  343. $valid = false;
  344. // domain part has two consecutive dots (RFC 1035)
  345. elseif (preg_match('~\\.\\.~', $domain))
  346. $valid = false;
  347. // character not valid in local part unless local part is quoted (RFC 2822)
  348. elseif (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\", "", $local)))
  349. {
  350. if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\", "", $local)))
  351. $valid = false;
  352. }
  353. }
  354. if ($valid)
  355. return;
  356. return array(
  357. 'field' => $field,
  358. 'input' => $input[$field],
  359. 'function' => __FUNCTION__,
  360. 'param' => $validation_parameters
  361. );
  362. }
  363. /**
  364. * max_length ... Determine if the provided value length is less or equal to a specific value
  365. *
  366. * Usage: '[key]' => 'max_length[x]'
  367. *
  368. * @param string $field
  369. * @param array $input
  370. * @param array or null $validation_parameters
  371. * @return mixed
  372. */
  373. protected function _validate_max_length($field, $input, $validation_parameters = null)
  374. {
  375. global $smcFunc;
  376. if (!isset($input[$field]))
  377. return;
  378. if ($smcFunc['strlen']($input[$field]) <= (int) $validation_parameters)
  379. return;
  380. return array(
  381. 'field' => $field,
  382. 'input' => $input[$field],
  383. 'function' => __FUNCTION__,
  384. 'param' => $validation_parameters
  385. );
  386. }
  387. /**
  388. * min_length Determine if the provided value length is greater than or equal to a specific value
  389. *
  390. * Usage: '[key]' => 'min_length[x]'
  391. *
  392. * @param string $field
  393. * @param array $input
  394. * @param array or null $validation_parameters
  395. * @return mixed
  396. */
  397. protected function _validate_min_length($field, $input, $validation_parameters = null)
  398. {
  399. global $smcFunc;
  400. if (!isset($input[$field]))
  401. return;
  402. if ($smcFunc['strlen']($input[$field]) >= (int) $validation_parameters)
  403. return;
  404. return array(
  405. 'field' => $field,
  406. 'input' => $input[$field],
  407. 'function' => __FUNCTION__,
  408. 'param' => $validation_parameters
  409. );
  410. }
  411. /**
  412. * length ... Determine if the provided value length matches a specific value
  413. *
  414. * Usage: '[key]' => 'exact_length[x]'
  415. *
  416. * @param string $field
  417. * @param array $input
  418. * @param array or null $validation_parameters
  419. * @return mixed
  420. */
  421. protected function _validate_length($field, $input, $validation_parameters = null)
  422. {
  423. global $smcFunc;
  424. if (!isset($input[$field]))
  425. return;
  426. if ($smcFunc['strlen']($input[$field]) == (int) $validation_parameters)
  427. return;
  428. return array(
  429. 'field' => $field,
  430. 'input' => $input[$field],
  431. 'function' => __FUNCTION__,
  432. 'param' => $validation_parameters
  433. );
  434. }
  435. /**
  436. * alpha ... Determine if the provided value contains only alpha characters
  437. *
  438. * Usage: '[key]' => 'alpha'
  439. *
  440. * @param string $field
  441. * @param array $input
  442. * @param array or null $validation_parameters
  443. * @return mixed
  444. */
  445. protected function _validate_alpha($field, $input, $validation_parameters = null)
  446. {
  447. if (!isset($input[$field]))
  448. return;
  449. // A character with the Unicode property of letter (any kind of letter from any language)
  450. if (!preg_match('~^(\p{L})+$~iu', $input[$field]))
  451. {
  452. return array(
  453. 'field' => $field,
  454. 'input' => $input[$field],
  455. 'function' => __FUNCTION__,
  456. 'param' => $validation_parameters
  457. );
  458. }
  459. }
  460. /**
  461. * alpha_numeric ... Determine if the provided value contains only alpha-numeric characters
  462. *
  463. * Usage: '[key]' => 'alpha_numeric'
  464. *
  465. * @param string $field
  466. * @param array $input
  467. * @param array or null $validation_parameters
  468. * @return mixed
  469. */
  470. protected function _validate_alpha_numeric($field, $input, $validation_parameters = null)
  471. {
  472. if (!isset($input[$field]))
  473. return;
  474. // A character with the Unicode property of letter or number (any kind of letter or numeric 0-9 from any language)
  475. if (!preg_match('~^([\p{L}\p{Nd}])+$~iu', $input[$field]))
  476. {
  477. return array(
  478. 'field' => $field,
  479. 'input' => $input[$field],
  480. 'function' => __FUNCTION__,
  481. 'param' => $validation_parameters
  482. );
  483. }
  484. }
  485. /**
  486. * alpha_dash ... Determine if the provided value contains only alpha characters plus dashed and underscores
  487. *
  488. * Usage: '[key]' => 'alpha_dash'
  489. *
  490. * @param string $field
  491. * @param array $input
  492. * @param array or null $validation_parameters
  493. * @return mixed
  494. */
  495. protected function _validate_alpha_dash($field, $input, $validation_parameters = null)
  496. {
  497. if (!isset($input[$field]))
  498. return;
  499. if (!preg_match('~^([-_\p{L}])+$~iu', $input[$field]))
  500. {
  501. return array(
  502. 'field' => $field,
  503. 'input' => $input[$field],
  504. 'function' => __FUNCTION__,
  505. 'param' => $validation_parameters
  506. );
  507. }
  508. }
  509. /**
  510. * numeric ... Determine if the provided value is a valid number or numeric string
  511. *
  512. * Usage: '[key]' => 'numeric'
  513. *
  514. * @param string $field
  515. * @param array $input
  516. * @param array or null $validation_parameters
  517. * @return mixed
  518. */
  519. protected function _validate_numeric($field, $input, $validation_parameters = null)
  520. {
  521. if (!isset($input[$field]))
  522. return;
  523. if (!is_numeric($input[$field]))
  524. {
  525. return array(
  526. 'field' => $field,
  527. 'input' => $input[$field],
  528. 'function' => __FUNCTION__,
  529. 'param' => $validation_parameters
  530. );
  531. }
  532. }
  533. /**
  534. * integer ... Determine if the provided value is a valid integer
  535. *
  536. * Usage: '[key]' => 'integer'
  537. *
  538. * @param string $field
  539. * @param array $input
  540. * @param array or null $validation_parameters
  541. * @return mixed
  542. */
  543. protected function _validate_integer($field, $input, $validation_parameters = null)
  544. {
  545. if (!isset($input[$field]))
  546. return;
  547. if (!is_int($input[$field]))
  548. {
  549. return array(
  550. 'field' => $field,
  551. 'input' => $input[$field],
  552. 'function' => __FUNCTION__,
  553. 'param' => $validation_parameters
  554. );
  555. }
  556. }
  557. /**
  558. * boolean ... Determine if the provided value is a boolean
  559. *
  560. * Usage: '[key]' => 'boolean'
  561. *
  562. * @param string $field
  563. * @param array $input
  564. * @param array or null $validation_parameters
  565. * @return mixed
  566. */
  567. protected function _validate_boolean($field, $input, $validation_parameters = null)
  568. {
  569. if (!isset($input[$field]))
  570. return;
  571. if (!is_bool($input[$field]))
  572. {
  573. return array(
  574. 'field' => $field,
  575. 'input' => $input[$field],
  576. 'function' => __FUNCTION__,
  577. 'param' => $validation_parameters
  578. );
  579. }
  580. }
  581. /**
  582. * float ... Determine if the provided value is a valid float
  583. *
  584. * Usage: '[key]' => 'float'
  585. *
  586. * @param string $field
  587. * @param array $input
  588. * @param array or null $validation_parameters
  589. * @return mixed
  590. */
  591. protected function _validate_float($field, $input, $validation_parameters = null)
  592. {
  593. if (!isset($input[$field]))
  594. return;
  595. if (!is_float($input[$field]))
  596. {
  597. return array(
  598. 'field' => $field,
  599. 'input' => $input[$field],
  600. 'function' => __FUNCTION__,
  601. 'param' => $validation_parameters
  602. );
  603. }
  604. }
  605. /**
  606. * valid_url ... Determine if the provided value is a valid-ish URL
  607. *
  608. * Usage: '[key]' => 'valid_url'
  609. *
  610. * @param string $field
  611. * @param array $input
  612. * @param array or null $validation_parameters
  613. * @return mixed
  614. */
  615. protected function _validate_valid_url($field, $input, $validation_parameters = null)
  616. {
  617. if (!isset($input[$field]))
  618. return;
  619. if (!preg_match('`^(https{0,1}?:(//([a-z0-9\-._~%]+)(:[0-9]+)?(/[a-z0-9\-._~%!$&\'()*+,;=:@]+)*/?))(\?[a-z0-9\-._~%!$&\'()*+,;=:@/?]*)?(\#[a-z0-9\-._~%!$&\'()*+,;=:@/?]*)?$`', $input[$field], $matches))
  620. {
  621. var_dump($matches);
  622. return array(
  623. 'field' => $field,
  624. 'input' => $input[$field],
  625. 'function' => __FUNCTION__,
  626. 'param' => $validation_parameters
  627. );
  628. }
  629. }
  630. /**
  631. * valid_ipv6 ... Determine if the provided value is a valid IPv6 address
  632. *
  633. * Usage: '[key]' => 'valid_ipv6'
  634. *
  635. * @param string $field
  636. * @param array $input
  637. * @param array or null $validation_parameters
  638. * @return mixed
  639. */
  640. protected function _validate_valid_ipv6($field, $input, $validation_parameters = null)
  641. {
  642. if (!isset($input[$field]))
  643. return;
  644. if (preg_match('~^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$~', $input[$field]) === 0)
  645. {
  646. return array(
  647. 'field' => $field,
  648. 'input' => $input[$field],
  649. 'function' => __FUNCTION__,
  650. 'param' => $validation_parameters
  651. );
  652. }
  653. }
  654. /**
  655. * valid_ip ... Determine if the provided value is a valid IP4 address
  656. *
  657. * Usage: '[key]' => 'valid_ip'
  658. *
  659. * @param string $field
  660. * @param array $input
  661. * @param array or null $validation_parameters
  662. * @return mixed
  663. */
  664. protected function _validate_valid_ip($field, $input, $validation_parameters = null)
  665. {
  666. if (!isset($input[$field]))
  667. return;
  668. if (preg_match('~^((([1]?\d)?\d|2[0-4]\d|25[0-5])\.){3}(([1]?\d)?\d|2[0-4]\d|25[0-5])$~', $input[$field]) === 0)
  669. {
  670. return array(
  671. 'field' => $field,
  672. 'input' => $input[$field],
  673. 'function' => __FUNCTION__,
  674. 'param' => $validation_parameters
  675. );
  676. }
  677. }
  678. //
  679. // Start of sanitation functions
  680. //
  681. /**
  682. * email_normalize ... Used to normalize a gmail address as many resolve to the same thing address
  683. *
  684. * - Gmail user can use @googlemail.com instead of @gmail.com
  685. * - Gmail ignores all characters after a + (plus sign) in the username
  686. * - Gmail ignores all . (dots) in username
  687. * - ahole@gmail.com, a.hole@gmail.com, ahole+big@gmail.com and a.hole+gigantic@googlemail.com are same email address.
  688. *
  689. * @param string $input
  690. */
  691. protected function _sanitation_email_normalize($input)
  692. {
  693. if (!isset($input))
  694. return;
  695. $at_index = strrpos($input, '@');
  696. // Time to do some checking on the local@domain parts
  697. $local_name = substr($input, 0, $at_index);
  698. $domain_name = strtolower(substr($input, $at_index + 1));
  699. // Gmail address?
  700. if (in_array($domain_name, array('gmail.com', 'googlemail.com')))
  701. {
  702. // Gmail ignores all . (dot) in username
  703. $local_name = str_replace('.', '', $local_name);
  704. // Gmail ignores all characters after a + (plus sign) in username
  705. $temp = explode('+', $local_name);
  706. $local_name = $temp[0];
  707. // @todo should we force gmail.com or use $domain_name, force is safest but perhaps most confusing
  708. }
  709. return $local_name . '@' . $domain_name;
  710. }
  711. }