Hi again Everett
the event hooks in webloginpe.class.php are somewhat useless unless you make some changes. Specifically you need to reference the weblogin instance if you actually want to do use methods within the class (such as wlpe->FormatMessage()) . I rewrote the hook to look like this:
function OnBeforeWebSaveUser($service='')
{
global $modx;
$parameters = array(
'wlpe' => &$this, // reference $wlpe instance
'service' => $service
);
$modx->invokeEvent('OnBeforeWebSaveUser', $parameters);
}
You then need to make sure the events are invoked in the right places in the class methods (and nowhere else!). Eg at around line 419:
function Register($regType, $groups, $regRequired, $notify, $notifyTpl, $notifySubject, $regSuccessId=0)
{
global $modx;
# mcroxton -->
$this->OnBeforeWebSaveUser('Register');
if (!empty($this->Report))
{
return $this->Report;
}
# <-- end
...
This is my custom plugin attached to the OnBeforeWebSaveUser which does custom form validation on register and on edit profile, creating custom error messages and passing error fields as a string that can be used by jQuery to highlight individual fields:
<?php
/*
plugin for WebLogin PE events
*/
# note $service is passed to this plugin from the event call
include ($_SERVER["DOCUMENT_ROOT"].'/assets/snippets/validation.inc.php');
# custom validation
$error= array();
$errorTxt= array();
$errorMessage='';
# make safe
if (isset($_POST['title'])) { $_POST['title'] = sanitize_string($_POST['title'], 0, 255); }
if (isset($_POST['firstname'])) { $_POST['firstname'] = sanitize_string($_POST['firstname'], 0, 255); }
if (isset($_POST['lastname'])) { $_POST['lastname'] = sanitize_string($_POST['lastname'], 0, 255); }
if (isset($_POST['suffix'])) { $_POST['suffix'] = sanitize_string($_POST['suffix'], 0, 255); }
if (isset($_POST['email'])) { $_POST['email'] = sanitize_string($_POST['email'], 0, 255); }
if (isset($_POST['telephone'])) { $_POST['telephone'] = sanitize_string($_POST['telephone'], 0, 255); }
if (isset($_POST['address1'])) { $_POST['address1'] = sanitize_string($_POST['address1'], 0, 255); }
if (isset($_POST['address2'])) { $_POST['address2'] = sanitize_string($_POST['address2'], 0, 255); }
if (isset($_POST['city'])) { $_POST['city'] = sanitize_string($_POST['city'], 0, 255); }
if (isset($_POST['state'])) { $_POST['state'] = sanitize_string($_POST['state'], 0, 255); }
if (isset($_POST['zip'])) { $_POST['zip'] = sanitize_string($_POST['zip'], 0, 16); }
if (isset($_POST['region'])) { $_POST['region'] = sanitize_string($_POST['region'], 0, 2); }
if (isset($_POST['phone'])) { $_POST['phone'] = sanitize_string($_POST['phone']); }
if (isset($_POST['mobilephone'])) { $_POST['mobilephone'] = sanitize_string($_POST['mobilephone']); }
if (isset($_POST['occupation'])) { $_POST['occupation'] = sanitize_string($_POST['occupation']); }
if (isset($_POST['privacy'])) { $_POST['privacy'] = sanitize_string($_POST['privacy']); }
if (isset($_POST['tos'])) { $_POST['tos'] = sanitize_string($_POST['tos']); }
# add fields to $_POST
$_POST['fullname'] = $_POST['firstname'].' '.$_POST['lastname'];
$_POST['username'] = $_POST['email'];
# required fields
if (!is_filled($_POST['title'])) {
$error[] = "title";
$errorTxt[] = "Title";
}
if (!is_filled($_POST['firstname'])) {
$error[] = "firstname";
$errorTxt[] = "First name";
}
if (!is_filled($_POST['lastname'])) {
$error[] = "lastname";
$errorTxt[] = "Last name";
}
if (!is_filled($_POST['email'])) {
$error[] = "email";
$errorTxt[] = "Email address";
} else if(!is_email($_POST['email'])) {
$error[] = "email";
$errorTxt[] = "Email » must be a valid email address";
}
if (!is_filled($_POST['phone'])) {
$error[] = "phone";
$errorTxt[] = "Telephone";
} else if (!is_phone($_POST['phone'])) {
$error[] = "phone";
$errorTxt[] = "Telephone » can only contain the characters 0-9()+";
}
if (!is_filled($_POST['address1'])) {
$error[] = "address1";
$errorTxt[] = "Address 1";
}
if (!is_filled($_POST['city'])) {
$error[] = "city";
$errorTxt[] = "Town/City";
}
if (!is_filled($_POST['zip'])) {
$error[] = "postcode";
$errorTxt[] = "Postcode";
} else if (!is_ukpostcode($_POST['zip'])) {
$error[] = "postcode";
$errorTxt[] = "Postcode » must be a valid UK postcode";
}
if ($service == 'Register') {
if (!is_filled($_POST['privacy'])) {
$error[] = "privacy";
$errorTxt[] = "Privacy policy - please confirm that you have read and understood the policy";
}
if (!is_filled($_POST['tos'])) {
$error[] = "tos";
$errorTxt[] = "Terms & conditions - please confirm your agreement";
}
// non-required fields that if filled, should be validated...
if (is_filled($_POST['mobilephone'])) {
if (!is_phone($_POST['mobilephone'])) {
$error[] = "mobilephone";
$errorTxt[] = "Evening/mobile telephone » can only contain the characters 0-9()+";
}
}
}
if (count($error)>0) {
# create a string of error field ids for use by jQuery
for ($i=0;$i<count($error);$i++) {
$errorJS.="#".$error[$i];
if ($i<count($error)-1) {
$errorJS.=',';
}
}
# format error message
$errorMessage = '<strong title="'.$errorJS.'">Please correct errors</strong> The following required field(s) are missing: ';
for ($i=0;$i<count($errorTxt);$i++) {
$errorMessage .=$errorTxt[$i];
if ($i<count($errorTxt)-1) {
$errorMessage.=', ';
}
}
$wlpe->FormatMessage($errorMessage);
}
?>
My validation functions (validation.inc.php) are as follows:
<?php
// Validation functions
// paranoid sanitization -- strip everything except the alphanumeric set plus @-.:, and whitespace
function sanitize_string($string, $min='', $max=''){
$string = preg_replace("/[^a-zA-Z0-9@\,\:\.\-\s]/", "", $string);
$len = strlen($string);
// trim length
if((($min != '') && ($len < $min)) || (($max != '') && ($len > $max)))
return FALSE;
// Now check if string contains email headers to prevent injection attempts
if (!is_safe($string)) {
return false;
}
return $string;
}
// make int int!
function sanitize_int($integer, $min='', $max=''){
$int = intval($integer);
if((($min != '') && ($int < $min)) || (($max != '') && ($int > $max)))
return FALSE;
return $int;
}
function is_safe($string) {
$badStrings = array("Content-Type:","MIME-Version:","Content-Transfer-Encoding:","bcc:","cc:");
foreach($badStrings as $bad){
if(strpos(strtolower($string), strtolower($bad)) !== false){
return false;
}
}
return true;
}
function is_filled($string) {
if (isset($string) && ($string != "")) {
return true;
} else return false;
}
function is_email($string) {
if (eregi("^[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3}$", $string)) {
return true;
} else return false;
}
function is_phone($string) {
if (preg_match ("/^[0-9+\-x() ]*$/ ", $string)) { // match a string made only of 0123456789-+x() and space
return true;
} else return false;
}
function is_name($string) {
if (preg_match ("/\w+\s+\w+/ ", $string)) { // match at least 2 words if we have asked for the full name in one field
return true;
} else return false;
}
function is_alphanumeric($string) { // just a-z and 0-9
if(!preg_match("/[^a-zA-Z0-9\.\-\\\\\\\\ ]+$/s",$string)) {
return true;
} else return false;
}
function is_ukpostcode($postcode) {
$postcode = strtoupper(str_replace(chr(32),'',$postcode));
$suffix = substr($postcode,-3,3);
$prefix = substr($postcode,0,(strlen($postcode)-3));
if (preg_match('/(^[A-Z]{1,2}[0-9]{1,2}|^[A-Z]{1,2}[0-9]{1}[A-Z]{1})$/',$prefix) && preg_match('/^[0-9]{1}[ABD-HJLNP-UW-Z]{2}$/',$suffix)) {
return TRUE;
} else {
return FALSE;
}
}
function is_ukdate($value, $format = 'dd/mm/yyyy'){
if(strlen($value) >= 6 && strlen($format) == 10){
// find separator. Remove all other characters from $format
$separator_only = str_replace(array('m','d','y'),'', $format);
$separator = $separator_only[0]; // separator is first character
if($separator && strlen($separator_only) == 2){
// make regex
$regexp = str_replace('mm', '(0?[1-9]|1[0-2])', $format);
$regexp = str_replace('dd', '(0?[1-9]|[1-2][0-9]|3[0-1])', $regexp);
$regexp = str_replace('yyyy', '(19|20)?[0-9][0-9]', $regexp);
$regexp = str_replace($separator, "\\" . $separator, $regexp);
if($regexp != $value && preg_match('/'.$regexp.'\z/', $value)){
// check date
$arr=explode($separator,$value);
$day=$arr[0];
$month=$arr[1];
$year=$arr[2];
if(@checkdate($month, $day, $year))
return true;
}
}
}
return false;
}
?>