3use SmashPig\Core\ValidationError;
39 case 'street_address':
40 case 'state_province':
43 $error_token = $field;
46 $error_token =
'general';
67 'fiscal_number' =>
'',
71 'street_address' =>
'',
72 'state_province' =>
'',
100 if (
$type ===
'not_empty' ) {
101 if ( $token !=
'general' ) {
102 $missingErrorKey =
"donate_interface-error-msg-{$token}";
103 return new ValidationError( $token, $missingErrorKey );
107 if (
$type ===
'valid_type' ||
$type ===
'calculated' ) {
108 $invalidErrorKey =
"donate_interface-error-msg-invalid-{$token}";
109 return new ValidationError( $token, $invalidErrorKey );
113 return new ValidationError( $token,
'donate_interface-error-msg-general' );
153 '_cache_' =>
'validate_boolean',
154 'account_number' =>
'validate_numeric',
155 'anonymous' =>
'validate_boolean',
156 'contribution_tracking_id' =>
'validate_numeric',
157 'currency' =>
'validate_alphanumeric',
158 'gateway' =>
'validate_alphanumeric',
159 'numAttempt' =>
'validate_numeric',
160 'opt-in' =>
'validate_boolean',
161 'posted' =>
'validate_boolean',
162 'recurring' =>
'validate_boolean',
166 'gateway' =>
'validate_gateway',
167 'address' =>
'validate_address',
168 'city' =>
'validate_address',
169 'email' =>
'validate_email',
170 'street_address' =>
'validate_address',
171 'postal_code' =>
'validate_address',
172 'currency' =>
'validate_currency_code',
173 'first_name' =>
'validate_name',
174 'last_name' =>
'validate_name',
175 'name' =>
'validate_name',
176 'employer' =>
'validate_name',
177 'employer_id' =>
'validate_numeric',
182 if ( $check_not_empty ) {
183 $validations[
'not_empty'] = array_unique( array_merge(
184 $check_not_empty, $validations[
'not_empty']
189 $errored_fields = [];
192 foreach ( $validations as $phase => $fields ) {
193 foreach ( $fields as $key => $custom ) {
195 if ( is_numeric( $key ) ) {
197 $validation_function =
"validate_{$phase}";
200 $validation_function = $custom;
203 $value = $data[$field] ??
null;
204 if ( empty( $value ) && $phase !==
'not_empty' ) {
211 if ( array_key_exists( $errorToken, $errored_fields ) ) {
216 $callable = [
'DataValidator', $validation_function ];
217 if ( !is_callable( $callable ) ) {
218 throw new BadMethodCallException( __FUNCTION__ .
" BAD PROGRAMMER. No function {$validation_function} for $field" );
222 switch ( $validation_function ) {
223 case 'validate_currency_code':
224 $result = call_user_func( $callable, $value, $gateway->
getCurrencies( $data ) );
227 $result = call_user_func( $callable, $value );
232 $results[$phase][$field] = $result;
233 if ( $result ===
false ) {
235 $errored_fields[$errorToken] =
true;
256 foreach ( $fields as $field ) {
257 foreach ( $results as $phase => $results_fields ) {
258 if ( array_key_exists( $field, $results_fields )
259 && $results_fields[$field] !==
true
276 return WmfFramework::validateEmail( $value )
286 return in_array( $value, $acceptedCurrencies );
297 if ( !$calculated_card_type ) {
320 return in_array( $value, $validValues,
true );
331 if ( is_numeric( $value ) ) {
345 global $wgDonationInterfaceGatewayAdapters;
347 return array_key_exists( $value, $wgDonationInterfaceGatewayAdapters );
359 return ( $value !==
null && $value !==
'' );
384 $value = html_entity_decode( $value );
385 $regex =
'/([\x20-\x2F]|[\x3A-\x40]|[\x5B-\x60]|[\x7B-\x7E]){' . strlen( $value ) .
'}/';
386 if ( preg_match( $regex, $value ) ) {
415 return ( strpos( $value,
'>' ) !==
false ) ||
416 ( strpos( $value,
'<' ) !== false );
428 $specialCharacterRegex = <<<EOT
431([`!@#$%^&*()_+\-=\[\]{};
':"\\|,.<>\/?~]+$)
434 // Transform the regex to get rid of the new lines
435 $specialCharacterRegex = preg_replace( '/\s/
', '', $specialCharacterRegex );
437 if ( preg_match_all( $specialCharacterRegex, $str, $matches ) > 0 ) {
450 public static function cc_number_exists_in_str( string $str ): bool {
453(?#amex)(3[47][0-9]{13})|
454(?#bankcard)(5610[0-9]{12})|(56022[1-5][0-9]{10})|
455(?#diners carte blanche)(300[0-5][0-9]{11})|
456(?#diners intl)(36[0-9]{12})|
457(?#diners US CA)(5[4-5][0-9]{14})|
458(?#discover)(6011[0-9]{12})|(622[0-9]{13})|(64[4-5][0-9]{13})|(65[0-9]{14})|
459(?#InstaPayment)(63[7-9][0-9]{13})|
460(?#JCB)(35[2-8][0-9]{13})|
461(?#Laser)(6(304|7(06|09|71))[0-9]{12,15})|
462(?#Maestro)((5018|5020|5038|5893|6304|6759|6761|6762|6763|0604)[0-9]{8,15})|
463(?#Mastercard)(5[1-5][0-9]{14})|
464(?#Solo)((6334|6767)[0-9]{12,15})|
465(?#Switch)((4903|4905|4911|4936|6333|6759)[0-9]{12,15})|((564182|633110)[0-9]{10,13})|
466(?#Visa)(4([0-9]{15}|[0-9]{12}))
470 $nonLuhnRegex = <<<EOT
472(?#china union pay)(62[0-9]{14,17})|
473(?#diners enroute)((2014|2149)[0-9]{11})
477 // Transform the regex to get rid of the new lines
478 $luhnRegex = preg_replace( '/\s/
', '', $luhnRegex );
479 $nonLuhnRegex = preg_replace( '/\s/
', '', $nonLuhnRegex );
481 // Remove common CC# delimiters
482 $str = preg_replace( '/[\s\-]/
', '', $str );
484 // Now split the string on everything else and implode again so the regexen have an 'easy
' time
485 $str = implode( ' ', preg_split( '/[^0-9]+/
', $str, PREG_SPLIT_NO_EMPTY ) );
487 // First do we have any numbers that match a pattern but is not luhn checkable?
489 if ( preg_match_all( $nonLuhnRegex, $str, $matches ) > 0 ) {
493 // Find potential CC numbers that do luhn check and run 'em
495 preg_match_all( $luhnRegex, $str,
$matches );
496 foreach (
$matches[0] as $candidate ) {
497 if ( self::luhn_check( $candidate ) ) {
514 $odd = ( strlen( $str ) % 2 );
516 $len = strlen( $str );
518 for ( $i = 0; $i < $len; $i++ ) {
522 if ( ( $str[$i] * 2 ) > 9 ) {
523 $sum += $str[$i] * 2 - 9;
525 $sum += $str[$i] * 2;
531 return( ( $sum % 10 ) == 0 );
541 if ( preg_match(
'/^3[47][0-9]{13}$/', $card_num ) ) {
543 } elseif ( preg_match(
'/^5[1-5][0-9]{14}$/', $card_num ) ) {
545 } elseif ( preg_match(
'/^4[0-9]{12}(?:[0-9]{3})?$/', $card_num ) ) {
547 } elseif ( preg_match(
'/^6(?:011|5[0-9]{2})[0-9]{12}$/', $card_num ) ) {
564 if ( array_key_exists(
'language', $data )
565 && WmfFramework::isValidBuiltInLanguageCode( $data[
'language'] ) ) {
566 return $data[
'language'];
568 return WmfFramework::getLanguageCode();
580 $parts = explode(
'/', $ip );
581 if ( count( $parts ) === 1 ) {
586 $corr = ( pow( 2, 32 ) - 1 ) - ( pow( 2, 32 - $parts[1] ) - 1 );
587 $first = ip2long( $parts[0] ) & ( $corr );
588 $length = pow( 2, 32 - $parts[1] ) - 1;
590 for ( $i = 0; $i <= $length; $i++ ) {
591 $ips[] = long2ip( $first + $i );
608 if ( empty( $ip_list ) ) {
611 foreach ( $ip_list as $address ) {
612 $expanded = array_merge( $expanded, self::expandIPBlockToArray( $address ) );
615 return in_array( $ip, $expanded,
true );
629 $needle = ( is_array( $needle ) ) ? $needle : [ $needle ];
630 $haystack = ( is_array( $haystack ) ) ? $haystack : [ $haystack ];
632 $plusCheck = array_key_exists(
'+', $haystack );
633 $minusCheck = array_key_exists(
'-', $haystack );
635 if ( $plusCheck || $minusCheck ) {
641 if ( $minusCheck && self::value_appears_in( $needle, $haystack[
'-'] ) ) {
644 if ( $plusCheck && self::value_appears_in( $needle, $haystack[
'+'] ) ) {
646 } elseif ( !$plusCheck ) {
653 if ( ( count( $haystack ) === 1 ) && ( in_array(
'ALL', $haystack ) ) ) {
658 $haystack = array_filter( $haystack,
static function ( $value ) {
659 return !is_array( $value );
661 $result = array_intersect( $haystack, $needle );
662 if ( !empty( $result ) ) {
678 $ret = ltrim( $value,
'0' );
682 if ( strlen( $ret ) > $total_length ) {
687 $ret = str_pad( $ret, $total_length,
'0', STR_PAD_LEFT );
DataValidator This class is responsible for performing all kinds of data validation,...
static getZeroPaddedValue( $value, $total_length)
Okay, so this isn't all validation, but there's a validation component in there so I'm calling it clo...
static expandIPBlockToArray( $ip)
Takes either an IP address, or an IP address with a CIDR block, and expands it to an array containing...
static ip_is_listed( $ip, $ip_list)
Check whether IP matches a block list.
static validate_not_just_punctuation( $value)
Validates that somebody didn't just punch in a bunch of punctuation, and nothing else.
static getCardType( $card_num)
Calculates and returns the card type for a given credit card number.
static validate_numeric( $value)
validate_numeric Determines if the $value passed in is numeric.
static validate_alphanumeric( $value)
validate_alphanumeric Checks to make sure the value is populated with an alphanumeric value....
static validate_name( $value)
Some people are silly and enter their CC numbers as their name.
static validate_gateway( $value)
validate_gateway Checks to make sure the gateway is populated with a valid and enabled gateway.
static getEmptyErrorArray()
getEmptyErrorArray
static getErrorToken( $field)
getErrorToken, intended to be used by classes that exist relatively close to the form classes,...
static validate_not_empty( $value)
validate_not_empty Checks to make sure that the $value is present in the $data array,...
static validate_credit_card( $value)
validate_credit_card Determines if the $value passed in is (possibly) a valid credit card number.
static validate_boolean( $value)
validate_boolean Determines if the $value passed in is a valid boolean.
static getError( $field, $type)
getError - returns the error object appropriate for a validation error on the specified field,...
static value_appears_in( $needle, $haystack)
Test to determine if a value appears in a haystack.
static special_characters_in_wrong_locations( $str)
Analyzes a string to see if there are special characters at the beginning/end of a string or right be...
static guessLanguage( $data)
Returns a valid mediawiki language code to use for all the DonationInterface translations.
static luhn_check( $str)
Performs a Luhn algorithm check on a string.
static validate_address( $value)
Gets rid of numbers that pass luhn in address fields -.
static validate_currency_code( $value, $acceptedCurrencies)
static checkValidationPassed( $fields, $results)
checkValidationPassed is a validate helper function.
static cc_number_exists_in_str(string $str)
Analyzes a string to see if any credit card numbers are hiding out in it.
static validate_email( $value)
validate_email Determines if the $value passed in is a valid email address.
static validate(GatewayType $gateway, $data, $check_not_empty=[])
validate Run all the validation rules we have defined against a (hopefully normalized) DonationInterf...
static obviousXssInString( $value)
getCurrencies( $options=[])