Index: trunk/extensions/DonationInterface/gateway_common/DonationData.php |
— | — | @@ -17,6 +17,7 @@ |
18 | 18 | |
19 | 19 | protected $normalized = array( ); |
20 | 20 | public $boss; |
| 21 | + protected $validationErrors = false; |
21 | 22 | |
22 | 23 | /** |
23 | 24 | * DonationData constructor |
— | — | @@ -383,6 +384,8 @@ |
384 | 385 | */ |
385 | 386 | protected function normalize() { |
386 | 387 | if ( !empty( $this->normalized ) ) { |
| 388 | + //TODO: Uncomment the next line when we want to start actually using the input validation. |
| 389 | + //$this->validateAllInput(); |
387 | 390 | $this->setUtmSource(); |
388 | 391 | $this->setNormalizedAmount(); |
389 | 392 | $this->setNormalizedOrderIDs(); |
— | — | @@ -433,8 +436,8 @@ |
434 | 437 | throw new MWException( 'Could not find form ' . $class_name_orig . ', nor default form ' . $class_name ); |
435 | 438 | } |
436 | 439 | } |
437 | | - |
438 | | - $this->setVal( 'form_class', $class_name ); |
| 440 | + |
| 441 | + $this->setVal( 'form_class', $class_name ); |
439 | 442 | } |
440 | 443 | |
441 | 444 | /** |
— | — | @@ -1287,6 +1290,303 @@ |
1288 | 1291 | } |
1289 | 1292 | return $posted; |
1290 | 1293 | } |
| 1294 | + |
| 1295 | + /** |
| 1296 | + * validateAllInput |
| 1297 | + * This function will go through all the data we have pulled from wherever |
| 1298 | + * we've pulled it, and make sure it's safe and expected and everything. |
| 1299 | + */ |
| 1300 | + protected function validateAllInput(){ |
| 1301 | + $rules = $this->buildValidationRules(); |
| 1302 | + foreach ( $this->normalized as $key => $val ){ |
| 1303 | + if ( $this->isSomething( $key ) ){ |
| 1304 | + //make sure there's a rule for it. |
| 1305 | + if ( !isset( $rules[$key] ) ){ |
| 1306 | + $this->log( "Validate Error: There is no rule for $key!" ); |
| 1307 | + //TODO: i18n |
| 1308 | + $this->validate_setError( 'general', "Validate Error: There is no rule for $key!" ); |
| 1309 | + } else { |
| 1310 | + $function = $rules[$key]['validate_function']; |
| 1311 | + if (method_exists( $this, $function )){ |
| 1312 | + $this->{$function}( $key, $rules[$key]['error_form_token'] ); |
| 1313 | + } else { |
| 1314 | + $this->log( "Validate Error: There is no $function function!" ); |
| 1315 | + //TODO: i18n |
| 1316 | + $this->validate_setError( 'general', "Validate Error: There is no $function function!" ); |
| 1317 | + } |
| 1318 | + } |
| 1319 | + |
| 1320 | + } |
| 1321 | + } |
| 1322 | + } |
| 1323 | + |
| 1324 | + /** |
| 1325 | + * Builds the validation rule set for all the keys we're pulling. |
| 1326 | + * TODO: Do some mapping here with i18n messages, too. We can't take this |
| 1327 | + * into prod just throwing the generic at everything. |
| 1328 | + * TODO: In general with this whole thing, the alphanumeric strategy should |
| 1329 | + * be... revised. Clearly we can't have a list of 'good' characters. |
| 1330 | + * Instead, we need to clean stuff that is clearly dangerous. |
| 1331 | + * Also, maybe we just auto-assign the alphanumeric clean function to |
| 1332 | + * anything that doesn't have other assignments, instead of dying nastily |
| 1333 | + * when we have one with no assignment. That's probably more pleasant. |
| 1334 | + * @return array An array of keys, the ways we want to validate them, and |
| 1335 | + * what messages to set if they don't pass. |
| 1336 | + * $array[$key] = array( |
| 1337 | + * 'validate_function' => $function_name, |
| 1338 | + * 'error_form_token' => $error_token |
| 1339 | + * ) |
| 1340 | + */ |
| 1341 | + protected function buildValidationRules(){ |
| 1342 | + $rules = array(); |
| 1343 | + |
| 1344 | + //you should group these jerks by type or something. |
| 1345 | + |
| 1346 | + //initial build based on general functions to run for validation. |
| 1347 | + $numeric = array( |
| 1348 | + 'amount', |
| 1349 | + 'amountGiven', |
| 1350 | + 'amountOther', |
| 1351 | + 'card_num', |
| 1352 | + 'cvv', |
| 1353 | + 'contribution_tracking_id', |
| 1354 | + 'utm_source_id', |
| 1355 | + 'account_number', |
| 1356 | + 'expiration', |
| 1357 | + 'order_id', |
| 1358 | + 'i_order_id', |
| 1359 | + 'numAttempt' |
| 1360 | + ); |
| 1361 | + |
| 1362 | + foreach ($numeric as $key){ |
| 1363 | + $rules[$key]['validate_function'] = 'validate_numeric'; |
| 1364 | + } |
| 1365 | + |
| 1366 | + $alphanumeric = array( |
| 1367 | + 'fname', |
| 1368 | + 'mname', |
| 1369 | + 'lname', |
| 1370 | + 'street', |
| 1371 | + 'city', |
| 1372 | + 'state', |
| 1373 | + 'zip', |
| 1374 | + 'country', |
| 1375 | + 'fname2', |
| 1376 | + 'lname2', |
| 1377 | + 'street2', |
| 1378 | + 'city2', |
| 1379 | + 'state2', |
| 1380 | + 'zip2', |
| 1381 | + 'country2', |
| 1382 | + 'size', |
| 1383 | + 'premium_language', |
| 1384 | + 'card_type', |
| 1385 | + 'currency', |
| 1386 | + 'currency_code', |
| 1387 | + 'payment_method', |
| 1388 | + 'payment_submethod', |
| 1389 | + 'form_name', |
| 1390 | + 'ffname', |
| 1391 | + |
| 1392 | + //for lack of a better idea what to do with these things, I'm just gonna leave these here. |
| 1393 | + //If any of them need to be numeric or boolean or dealt with specially, do that. |
| 1394 | + 'issuer_id', |
| 1395 | + 'referrer', |
| 1396 | + 'utm_source', |
| 1397 | + 'utm_medium', |
| 1398 | + 'utm_campaign', |
| 1399 | + 'language', |
| 1400 | + 'uselang', |
| 1401 | + 'comment', |
| 1402 | + 'token', |
| 1403 | + 'data_hash', |
| 1404 | + 'action', |
| 1405 | + 'gateway', |
| 1406 | + 'owa_session', |
| 1407 | + 'owa_ref', |
| 1408 | + 'descriptor', |
| 1409 | + 'account_name', |
| 1410 | + 'authorization_id', |
| 1411 | + 'bank_check_digit', |
| 1412 | + 'bank_name', |
| 1413 | + 'bank_code', |
| 1414 | + 'branch_code', |
| 1415 | + 'country_code_bank', |
| 1416 | + 'date_collect', |
| 1417 | + 'direct_debit_text', |
| 1418 | + 'iban', |
| 1419 | + 'transaction_type', |
| 1420 | + ); |
| 1421 | + |
| 1422 | + foreach ($alphanumeric as $key){ |
| 1423 | + $rules[$key]['validate_function'] = 'validate_alphanumeric_with_cleaning'; |
| 1424 | + } |
| 1425 | + |
| 1426 | + $boolean = array( |
| 1427 | + 'comment-option', |
| 1428 | + 'email-opt', |
| 1429 | + '_cache_', |
| 1430 | + 'anonymous', |
| 1431 | + 'optout', |
| 1432 | + ); |
| 1433 | + |
| 1434 | + foreach ($boolean as $key){ |
| 1435 | + $rules[$key]['validate_function'] = 'validate_boolean'; |
| 1436 | + } |
| 1437 | + |
| 1438 | + $rules['email']['validate_function'] = 'validate_email'; |
| 1439 | + |
| 1440 | + |
| 1441 | + //now, set the error token to use... |
| 1442 | + |
| 1443 | + foreach ( $rules as $key => $value ){ |
| 1444 | + $error_token = 'general'; |
| 1445 | + switch ( $key ) { |
| 1446 | + case 'amountGiven' : |
| 1447 | + case 'amountOther' : |
| 1448 | + $error_token = 'amount'; |
| 1449 | + break; |
| 1450 | + case 'email' : |
| 1451 | + $error_token = 'emailAdd'; |
| 1452 | + break; |
| 1453 | + case 'amount' : |
| 1454 | + case 'card_num': |
| 1455 | + case 'card_type': |
| 1456 | + case 'cvv': |
| 1457 | + case 'fname': |
| 1458 | + case 'lname': |
| 1459 | + case 'city': |
| 1460 | + case 'country': |
| 1461 | + case 'street': |
| 1462 | + case 'state': |
| 1463 | + case 'zip': |
| 1464 | + $error_token = $key; |
| 1465 | + break; |
| 1466 | + } |
| 1467 | + $rules[$key]['error_form_token'] = $error_token; |
| 1468 | + } |
| 1469 | + |
| 1470 | + return $rules; |
| 1471 | + } |
| 1472 | + |
| 1473 | + /** |
| 1474 | + * Sets an error found during validation. |
| 1475 | + * @param string $error_token The error token to set for this error. |
| 1476 | + * (See RapidHTML::$error_tokens for possibilities) |
| 1477 | + * @param string $msg The translated message to display at that error token. |
| 1478 | + */ |
| 1479 | + protected function validate_setError( $error_token, $msg ){ |
| 1480 | + if ( !$this->validationErrors ){ |
| 1481 | + $this->validationErrors = array(); |
| 1482 | + } |
| 1483 | + $this->validationErrors[$error_token] = $msg; |
| 1484 | + |
| 1485 | + } |
| 1486 | + |
| 1487 | + /** |
| 1488 | + * validatedOK |
| 1489 | + * Checks to see if the data validated ok (no errors). |
| 1490 | + * @return boolean True if no errors, false if errors exist. |
| 1491 | + */ |
| 1492 | + public function validatedOK() { |
| 1493 | + if ( is_array( $this->validationErrors ) ){ |
| 1494 | + return false; |
| 1495 | + } |
| 1496 | + return true; |
| 1497 | + } |
| 1498 | + |
| 1499 | + /** |
| 1500 | + * getValidationErrors |
| 1501 | + * Returns the errors set on data validation. |
| 1502 | + * @return mixed Array if errors are set, else false. |
| 1503 | + */ |
| 1504 | + public function getValidationErrors() { |
| 1505 | + return $this->validationErrors; |
| 1506 | + } |
| 1507 | + |
| 1508 | + /** |
| 1509 | + * validate_email |
| 1510 | + * validateAllInput helper function |
| 1511 | + * To validate any input value using this function, add a line to |
| 1512 | + * $this->buildValidationRules() specifying the function name as the field |
| 1513 | + * name's 'validate_function'. |
| 1514 | + * @param string $key The name of the field to validate. |
| 1515 | + * @param string $error_token As in RapidHTML, the pre-defined area of the |
| 1516 | + * form in which to display the error. |
| 1517 | + */ |
| 1518 | + protected function validate_email( $key, $error_token ){ |
| 1519 | + // is email address valid? |
| 1520 | + $isEmail = User::isValidEmailAddr( $this->getVal($key) ); |
| 1521 | + |
| 1522 | + // create error message (supercedes empty field message) |
| 1523 | + if ( !$isEmail ) { |
| 1524 | + $this->log( __FUNCTION__ . " $key is not an email address.", LOG_DEBUG ); |
| 1525 | + $this->validate_setError( $error_token, wfMsg( 'donate_interface-error-msg-email' ) ); |
| 1526 | + } |
| 1527 | + } |
| 1528 | + |
| 1529 | + /** |
| 1530 | + * validate_boolean |
| 1531 | + * validateAllInput helper function |
| 1532 | + * To validate any input value using this function, add a line to |
| 1533 | + * $this->buildValidationRules() specifying the function name as the field |
| 1534 | + * name's 'validate_function'. |
| 1535 | + * @param string $key The name of the field to validate. |
| 1536 | + * @param string $error_token As in RapidHTML, the pre-defined area of the |
| 1537 | + * form in which to display the error. |
| 1538 | + */ |
| 1539 | + protected function validate_boolean( $key, $error_token ){ |
| 1540 | + $val = $this->getVal($key); |
| 1541 | + if ( $val === 0 || $val === 1 ) { |
| 1542 | + $this->log( __FUNCTION__ . " $key is not boolean.", LOG_DEBUG ); |
| 1543 | + $this->validate_setError( $error_token, wfMsg( 'donate_interface-error-msg-general' ) ); |
| 1544 | + } |
| 1545 | + |
| 1546 | + } |
| 1547 | + |
| 1548 | + /** |
| 1549 | + * validate_alphanumeric_with_cleaning |
| 1550 | + * validateAllInput helper function |
| 1551 | + * To validate and clean any input value using this function, add a line to |
| 1552 | + * $this->buildValidationRules() specifying the function name as the field |
| 1553 | + * name's 'validate_function'. |
| 1554 | + * TODO: Something even remotely useful here. Like the cleaning promised in |
| 1555 | + * the function name. |
| 1556 | + * @param string $key The name of the field to validate. |
| 1557 | + * @param string $error_token As in RapidHTML, the pre-defined area of the |
| 1558 | + * form in which to display the error. |
| 1559 | + */ |
| 1560 | + protected function validate_alphanumeric_with_cleaning( $key, $error_token ){ |
| 1561 | + $val = $this->getVal($key); |
| 1562 | + |
| 1563 | + //instead of validating here, we should probably be proactively removing badness. |
| 1564 | + if ( preg_match( '/%/', $val ) ) { //this is dumb and bad. Fixit. |
| 1565 | + $this->log( __FUNCTION__ . " $key is not valid alphanumeric. $val", LOG_DEBUG ); |
| 1566 | + //oooh. This blows. |
| 1567 | + $this->validate_setError( $error_token, wfMsg( 'donate_interface-error-msg-general' ) ); |
| 1568 | + } |
| 1569 | + } |
| 1570 | + |
| 1571 | + /** |
| 1572 | + * validate_numeric |
| 1573 | + * validateAllInput helper function |
| 1574 | + * To validate any input value using this function, add a line to |
| 1575 | + * $this->buildValidationRules() specifying the function name as the field |
| 1576 | + * name's 'validate_function'. |
| 1577 | + * @param string $key The name of the field to validate. |
| 1578 | + * @param string $error_token As in RapidHTML, the pre-defined area of the |
| 1579 | + * form in which to display the error. |
| 1580 | + */ |
| 1581 | + protected function validate_numeric( $key, $error_token ){ |
| 1582 | + $val = $this->getVal($key); |
| 1583 | + |
| 1584 | + //instead of validating here, we should probably be doing something else entirely. |
| 1585 | + if ( !is_numeric( $val ) ) { |
| 1586 | + $this->log( __FUNCTION__ . " $key is not valid numeric format. $val", LOG_DEBUG ); |
| 1587 | + //oooh. This blows. |
| 1588 | + $this->validate_setError( $error_token, wfMsg( 'donate_interface-error-msg-general' ) ); |
| 1589 | + } |
| 1590 | + } |
1291 | 1591 | } |
1292 | 1592 | |
1293 | 1593 | ?> |