r70610 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r70609‎ | r70610 | r70611 >
Date:01:24, 7 August 2010
Author:awjrichards
Status:deferred (Comments)
Tags:
Comment:
Added a MaxMind minFraud layer to the DonationInterface extension and exposed a hook in the payflow pro gateway before processing transactions to run through some kind of validator (eg minFraud), to determine what kind of action to take on a transaction
Modified paths:
  • /trunk/extensions/DonationInterface/minfraud (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/COPYING (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/Changes (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/CreditCardFraudDetection.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/Example.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/Example_locv.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/Example_telv.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/HTTPBase.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/LocationVerification.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/README (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/ccfd/TelephoneVerification.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/minfraud.il8n.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/minfraud.php (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/tests (added) (history)
  • /trunk/extensions/DonationInterface/minfraud/tests/minfraudTest.php (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php (modified) (history)

Diff [purge]

Index: trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php
@@ -153,6 +153,7 @@
154154 // The submitted data is valid, so process it
155155 //increase the count of attempts
156156 ++$data['numAttempt'];
 157+ wfRunHooks( 'PayflowGatewayValidate', array( &$this, &$data )) ;
157158 $this->fnPayflowProcessTransaction( $data, $payflow_data );
158159 }
159160 } else {
Index: trunk/extensions/DonationInterface/minfraud/ccfd/HTTPBase.php
@@ -0,0 +1,434 @@
 2+<?php
 3+
 4+/* HTTPBase.php
 5+ *
 6+ * Copyright (C) 2008 MaxMind, Inc.
 7+ *
 8+ * This library is free software; you can redistribute it and/or
 9+ * modify it under the terms of the GNU Lesser General Public
 10+ * License as published by the Free Software Foundation; either
 11+ * version 2.1 of the License, or (at your option) any later version.
 12+ *
 13+ * This library is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 16+ * Lesser General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU Lesser General Public
 19+ * License along with this library; if not, write to the Free Software
 20+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 21+ */
 22+
 23+class HTTPBase{
 24+ var $server;
 25+ var $numservers;
 26+ var $url;
 27+ var $queries;
 28+ var $allowed_fields;
 29+ var $num_allowed_fields;
 30+ var $outputstr;
 31+ var $isSecure;
 32+ var $timeout;
 33+ var $debug;
 34+ var $check_field;
 35+ var $wsIpaddrRefreshTimeout;
 36+ var $wsIpaddrCacheFile;
 37+ var $useDNS;
 38+ var $ipstr;
 39+ function HTTPBase() {
 40+ $this->isSecure = 0;
 41+ $this->debug = 0;
 42+ $this->timeout = 0;
 43+ $this->check_field = "score";
 44+ $this->wsIpaddrRefreshTimeout = 18000;
 45+ $this->wsIpaddrCacheFile = $this->_getTempDir()."/maxmind.ws.cache";
 46+ if ($this->debug == 1) {
 47+ print "wsIpaddrRefreshTimeout: " . $this->wsIpaddrRefreshTimeout . "\n";
 48+ print "wsIpaddrCacheFile: " . $this->wsIpaddrCacheFile . "\n";
 49+ print "useDNS: " . $this->useDNS . "\n";
 50+ }
 51+ }
 52+
 53+ // this function sets the checked field
 54+ function set_check_field($f) {
 55+ $check_field = $f;
 56+ }
 57+
 58+ // this function sets the allowed fields
 59+ function set_allowed_fields($i) {
 60+ $this->allowed_fields = $i;
 61+ $this->num_allowed_fields = count($i);
 62+ }
 63+
 64+ //this function queries the servers
 65+ function query() {
 66+ //query every server in the list
 67+ if (!$this->useDNS){
 68+ $ipstr = $this->readIpAddressFromCache();
 69+ if ($this->debug == 1){
 70+ print "using ip addresses, IPs are " . $ipstr . "\n";
 71+ }
 72+ }
 73+ // query every server using its ip address
 74+ // if there was success reading the ip addresses
 75+ // from the web or the cache file
 76+ if ($ipstr) {
 77+ $ipaddr = explode(";",$ipstr);
 78+ $numipaddr = count($ipaddr);
 79+ for ($i = 0;$i < $numipaddr;$i++){
 80+ $result = $this->querySingleServer($ipaddr[$i]);
 81+ if ($this->debug == 1) {
 82+ print "ip address: " . $ipaddr[$i] . "\n";
 83+ print "result: " . $result . "\n";
 84+ }
 85+ if ($result) {
 86+ return $result;
 87+ }
 88+ }
 89+ }
 90+
 91+ // query every server using its domain name
 92+ for ($i = 0; $i < $this->numservers; $i++ ) {
 93+ $result = $this->querySingleServer($this->server[$i]);
 94+ if ($this->debug == 1) {
 95+ print "server: " . $this->server[$i] . "\nresult: " . $result . "\n";
 96+ }
 97+ if ($result) {
 98+ return $result;
 99+ }
 100+ }
 101+ return 0;
 102+ }
 103+
 104+ // this function takes a input hash and stores it in the hash named queries
 105+ function input($vars) {
 106+ $numinputkeys = count($vars); // get the number of keys in the input hash
 107+ $inputkeys = array_keys($vars); // get a array of keys in the input hash
 108+ for ($i = 0; $i < $numinputkeys; $i++) {
 109+ $key = $inputkeys[$i];
 110+ if ($this->allowed_fields[$key] == 1) {
 111+ //if key is a allowed field then store it in
 112+ //the hash named queries
 113+ $this->queries[$key] = urlencode($this->filter_field($key, $vars[$key]));
 114+ } else {
 115+ print "invalid input $key - perhaps misspelled field?";
 116+ return 0;
 117+ }
 118+ }
 119+ $this->queries["clientAPI"] = $this->API_VERSION;
 120+ }
 121+
 122+ //sub-class should override this if it needs to filter inputs
 123+ function filter_field($key, $value) {
 124+ return $value;
 125+ }
 126+
 127+ //this function returns the output from the server
 128+ function output() {
 129+ return $this->outputstr;
 130+ }
 131+
 132+ // write the ip Addresses and the time right now to
 133+ // the cache file
 134+ function writeIpAddressToCache($filename,$ipstr) {
 135+ $datetime = time();
 136+ $fh = fopen($this->wsIpaddrCacheFile,'w');
 137+ fwrite($fh,$ipstr . "\n");
 138+ fwrite($fh,$datetime . "\n");
 139+ fclose($fh);
 140+ if ($this->debug == 1) {
 141+ print "writing ip address to cache\n";
 142+ print "ip str: " . $ipstr . "\n";
 143+ print "date time: " . $datetime . "\n";
 144+ }
 145+ }
 146+
 147+ function readIpAddressFromCache() {
 148+ // if the cache file exists then
 149+ // read the ip addresses and the time
 150+ // IPs were cached
 151+ if (file_exists($this->wsIpaddrCacheFile)) {
 152+ $fh = fopen($this->wsIpaddrCacheFile,'r');
 153+ $ipstr = fgets($fh,1024);
 154+ $ipstr = rtrim($ipstr);
 155+ $datetime = fgets($fh,1024);
 156+ $datetime = rtrim($datetime);
 157+ fclose($fh);
 158+ }
 159+
 160+ // if the ip addresses expired or don't exist then
 161+ // get them from the web and write
 162+ // them to the cache file
 163+ if (((time() - $datetime) > $this->wsIpaddrRefreshTimeout) | (!$ipstr)) {
 164+ $tryIpstr = $this->readIpAddressFromWeb();
 165+ if ($tryIpstr) {
 166+ $ipstr = $tryIpstr;
 167+ } else {
 168+ if ($this->debug == 1){
 169+ print "Warning, unable to get ws_ipaddr from www.maxmind.com\n";
 170+ }
 171+ }
 172+ // we write to cache whether or not we were able to get $tryIpStr, since
 173+ // in case DNS goes down, we don't want to check app/ws_ipaddr over and over
 174+ $this->writeIpAddressToCache($this->wsIpaddrCacheFile,$ipstr);
 175+ }
 176+ if ($this->debug == 1){
 177+ print "reading ip address from cache\n";
 178+ print "ip str: " . $ipstr . "\n";
 179+ print "date time: " . $datetime . "\n";
 180+ }
 181+ //return the ip addresses
 182+ return $ipstr;
 183+ }
 184+
 185+ function readIpAddressFromWeb() {
 186+ //check if the curl module exists
 187+ $url = "http://www.maxmind.com/app/ws_ipaddr";
 188+ if (extension_loaded('curl')) {
 189+ // open curl
 190+ $ch = curl_init();
 191+
 192+ // set curl options
 193+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 194+ curl_setopt($ch, CURLOPT_URL, $url);
 195+ curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
 196+
 197+ //get the content
 198+ $content = curl_exec($ch);
 199+ $content = rtrim($content);
 200+ if ($this->debug == 1) {
 201+ print "using curl\n";
 202+ }
 203+ } else {
 204+ // we using HTTP without curl
 205+
 206+ // parse the url to get
 207+ // host, path and query
 208+ $url3 = parse_url($url);
 209+ $host = $url3["host"];
 210+ $path = $url3["path"];
 211+
 212+ // open the connection
 213+ $fp = fsockopen ($host, 80, $errno, $errstr, $this->timeout);
 214+ if ($fp) {
 215+ // send the request
 216+ fputs ($fp, "GET $path HTTP/1.0\nHost: " . $host . "\n\n");
 217+ while (!feof($fp)) {
 218+ $buf .= fgets($fp, 128);
 219+ }
 220+ $lines = split("\n", $buf);
 221+ // get the content
 222+ $content = $lines[count($lines)-1];
 223+ //close the connection
 224+ fclose($fp);
 225+ }
 226+ if ($this->debug == 1) {
 227+ print "using fsockopen\n";
 228+ }
 229+ }
 230+ if ($this->debug == 1) {
 231+ print "readIpAddressFromWeb found ip addresses: " . $content . "\n";
 232+ }
 233+ // TODO fix regexp so that it checks if it only has IP addresses
 234+ if (ereg ("([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})",$content)) {
 235+ return $content;
 236+ }
 237+ return "";
 238+ }
 239+
 240+ // this function queries a single server
 241+ function querySingleServer($server) {
 242+ // check if we using the Secure HTTPS proctol
 243+ if ($this->isSecure == 1) {
 244+ $scheme = "https://"; // Secure HTTPS proctol
 245+ } else {
 246+ $scheme = "http://"; // Regular HTTP proctol
 247+ }
 248+
 249+ // build a query string from the hash called queries
 250+ $numquerieskeys = count($this->queries); // get the number of keys in the hash called queries
 251+ $querieskeys = array_keys($this->queries); // get a array of keys in the hash called queries
 252+ if ($this->debug == 1) {
 253+ print "number of query keys " + $numquerieskeys + "\n";
 254+ }
 255+
 256+ $query_string = "";
 257+
 258+ for ($i = 0; $i < $numquerieskeys; $i++) {
 259+ //for each element in the hash called queries
 260+ //append the key and value of the element to the query string
 261+ $key = $querieskeys[$i];
 262+ $value = $this->queries[$key];
 263+ //encode the key and value before adding it to the string
 264+ //$key = urlencode($key);
 265+ //$value = urlencode($value);
 266+ if ($this->debug == 1) {
 267+ print " query key " . $key . " query value " . $value . "\n";
 268+ }
 269+ $query_string = $query_string . $key . "=" . $value;
 270+ if ($i < $numquerieskeys - 1) {
 271+ $query_string = $query_string . "&";
 272+ }
 273+ }
 274+
 275+ $content = "";
 276+
 277+ //check if the curl module exists
 278+ if (extension_loaded('curl')) {
 279+ //use curl
 280+ if ($this->debug == 1) {
 281+ print "using curl\n";
 282+ }
 283+
 284+ //open curl
 285+ $ch = curl_init();
 286+
 287+ $url = $scheme . $server . "/" . $this->url;
 288+
 289+ //set curl options
 290+ if ($this->debug == 1){
 291+ print "url " . $url . "\n";
 292+ }
 293+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 294+ curl_setopt($ch, CURLOPT_URL, $url);
 295+ curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
 296+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,0);
 297+
 298+ //this option lets you store the result in a string
 299+ curl_setopt($ch, CURLOPT_POST, 1);
 300+ curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
 301+
 302+ //get the content
 303+ $content = curl_exec($ch);
 304+
 305+ // For some reason curl_errno returns an error even when function works
 306+ // Until we figure this out, will ignore curl errors - (not good i know)
 307+// $e = curl_errno($ch);//get error or sucess
 308+
 309+// if (($e == 1) & ($this->isSecure == 1)) {
 310+ // HTTPS does not work print error message
 311+// print "error: this version of curl does not support HTTPS try build curl with SSL or specify \$ccfs->isSecure = 0\n";
 312+// }
 313+// if ($e > 0) {
 314+ //we get a error msg print it
 315+// print "Received error message $e from curl: " . curl_error($ch) . "\n";
 316+// return 0;
 317+// }
 318+ //close curl
 319+ curl_close($ch);
 320+ } else {
 321+ //curl does not exist
 322+ //use the fsockopen function,
 323+ //the fgets function and the fclose function
 324+ if ($this->debug == 1) {
 325+ print "using fsockopen for querySingleServer\n";
 326+ }
 327+
 328+ $url = $scheme . $server . "/" . $this->url . "?" . $query_string;
 329+ if ($this->debug == 1) {
 330+ print "url " . $url . " " . "\n";
 331+ }
 332+
 333+ //now check if we are using regular HTTP
 334+ if ($this->isSecure == 0) {
 335+ //we using regular HTTP
 336+
 337+ //parse the url to get
 338+ //host, path and query
 339+ $url3 = parse_url($url);
 340+ $host = $url3["host"];
 341+ $path = $url3["path"];
 342+ $query = $url3["query"];
 343+
 344+ //open the connection
 345+ $fp = fsockopen ($host, 80, $errno, $errstr, $this->timeout);
 346+ if ($fp) {
 347+ //send the request
 348+ $post = "POST $path HTTP/1.0\nHost: " . $host . "\nContent-type: application/x-www-form-urlencoded\nUser-Agent: Mozilla 4.0\nContent-length: " . strlen($query) . "\nConnection: close\n\n$query";
 349+ fputs ($fp, $post);
 350+ while (!feof($fp)) {
 351+ $buf .= fgets($fp, 128);
 352+ }
 353+ $lines = split("\n", $buf);
 354+ // get the content
 355+ $content = $lines[count($lines)-1];
 356+ //close the connection
 357+ fclose($fp);
 358+ } else {
 359+ return 0;
 360+ }
 361+ } else {
 362+ //secure HTTPS requires CURL
 363+ print "error: you need to install curl if you want secure HTTPS or specify the variable to be $ccfs->isSecure = 0";
 364+ return 0;
 365+ }
 366+ }
 367+
 368+ if ($this->debug == 1) {
 369+ print "content = " . $content . "\n";
 370+ }
 371+ // get the keys and values from
 372+ // the string content and store them
 373+ // the hash named outputstr
 374+
 375+ // split content into pairs containing both
 376+ // the key and the value
 377+ $keyvaluepairs = explode(";",$content);
 378+
 379+ //get the number of key and value pairs
 380+ $numkeyvaluepairs = count($keyvaluepairs);
 381+
 382+ //for each pair store key and value into the
 383+ //hash named outputstr
 384+ $this->outputstr = array();
 385+ for ($i = 0; $i < $numkeyvaluepairs; $i++) {
 386+ //split the pair into a key and a value
 387+ list($key,$value) = explode("=",$keyvaluepairs[$i]);
 388+ if ($this->debug == 1) {
 389+ print " output " . $key . " = " . $value . "\n";
 390+ }
 391+ //store the key and the value into the
 392+ //hash named outputstr
 393+ $this->outputstr[$key] = $value;
 394+ }
 395+ //check if outputstr has the score if outputstr does not have
 396+ //the score return 0
 397+ if ($this->outputstr[$this->check_field] == "") {
 398+ return 0;
 399+ }
 400+ //one other way to do it
 401+ //if (!array_key_exists("score",$this->outputstr)) {
 402+ // return 0;
 403+ //}
 404+ return 1;
 405+ }
 406+
 407+ function _getTempDir() {
 408+ if (ini_get('upload_tmp_dir')) {
 409+ return ini_get('upload_tmp_dir');
 410+ }
 411+
 412+ if (substr(PHP_OS, 0, 3) != 'WIN') {
 413+ return '/tmp';
 414+ }
 415+
 416+ if (isset($_ENV['TMP'])) {
 417+ return $_ENV['TMP'];
 418+ }
 419+
 420+ if (isset($_ENV['TEMP'])) {
 421+ return $_ENV['TEMP'];
 422+ }
 423+
 424+ if (is_dir('c:\\windows\\temp')) {
 425+ return 'c:\\windows\\temp';
 426+ }
 427+
 428+ if (is_dir('c:\\winnt\\temp')) {
 429+ return 'c:\\winnt\\temp';
 430+ }
 431+
 432+ return '.';
 433+ }
 434+}
 435+?>
Index: trunk/extensions/DonationInterface/minfraud/ccfd/Example.php
@@ -0,0 +1,87 @@
 2+#!/usr/bin/php -q
 3+<?php
 4+require("CreditCardFraudDetection.php");
 5+
 6+// Create a new CreditCardFraudDetection object
 7+$ccfs = new CreditCardFraudDetection;
 8+
 9+// Set inputs and store them in a hash
 10+// See http://www.maxmind.com/app/ccv for more details on the input fields
 11+
 12+// Enter your license key here (Required)
 13+$h["license_key"] = "XBCKSF4gnHA7";
 14+
 15+// Required fields
 16+$h["i"] = "24.24.24.24"; // set the client ip address
 17+$h["city"] = "New York"; // set the billing city
 18+$h["region"] = "NY"; // set the billing state
 19+$h["postal"] = "11434"; // set the billing zip code
 20+$h["country"] = "US"; // set the billing country
 21+
 22+// Recommended fields
 23+$h["domain"] = "yahoo.com"; // Email domain
 24+$h["bin"] = "549099"; // bank identification number
 25+$h["forwardedIP"] = "24.24.24.25"; // X-Forwarded-For or Client-IP HTTP Header
 26+// CreditCardFraudDetection.php will take
 27+// MD5 hash of e-mail address passed to emailMD5 if it detects '@' in the string
 28+$h["emailMD5"] = "Adeeb@Hackstyle.com";
 29+// CreditCardFraudDetection.php will take the MD5 hash of the username/password if the length of the string is not 32
 30+$h["usernameMD5"] = "test_carder_username";
 31+$h["passwordMD5"] = "test_carder_password";
 32+
 33+// Optional fields
 34+$h["binName"] = "MBNA America Bank"; // bank name
 35+$h["binPhone"] = "800-421-2110"; // bank customer service phone number on back of credit card
 36+$h["custPhone"] = "212-242"; // Area-code and local prefix of customer phone number
 37+$h["requested_type"] = "premium"; // Which level (free, city, premium) of CCFD to use
 38+$h["shipAddr"] = "145-50 157TH STREET"; // Shipping Address
 39+$h["shipCity"] = "Jamaica"; // the City to Ship to
 40+$h["shipRegion"] = "NY"; // the Region to Ship to
 41+$h["shipPostal"] = "11434"; // the Postal Code to Ship to
 42+$h["shipCountry"] = "US"; // the country to Ship to
 43+
 44+$h["txnID"] = "1234"; // Transaction ID
 45+$h["sessionID"] = "abcd9876"; // Session ID
 46+
 47+$h["accept_language"] = "de-de";
 48+$h["user_agent"] = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; de-de) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1";
 49+
 50+// If you want to disable Secure HTTPS or don't have Curl and OpenSSL installed
 51+// uncomment the next line
 52+// $ccfs->isSecure = 0;
 53+
 54+// set the timeout to be five seconds
 55+$ccfs->timeout = 5;
 56+
 57+// uncomment to turn on debugging
 58+// $ccfs->debug = 1;
 59+
 60+// how many seconds to cache the ip addresses
 61+// $ccfs->wsIpaddrRefreshTimeout = 3600*5;
 62+
 63+// file to store the ip address for minfraud3.maxmind.com, minfraud1.maxmind.com and minfraud2.maxmind.com
 64+// $ccfs->wsIpaddrCacheFile = "/tmp/maxmind.ws.cache";
 65+
 66+// if useDNS is 1 then use DNS, otherwise use ip addresses directly
 67+$ccfs->useDNS = 0;
 68+
 69+$ccfs->isSecure = 0;
 70+
 71+// next we set up the input hash
 72+$ccfs->input($h);
 73+
 74+// then we query the server
 75+$ccfs->query();
 76+
 77+// then we get the result from the server
 78+$h = $ccfs->output();
 79+
 80+// then finally we print out the result
 81+$outputkeys = array_keys($h);
 82+$numoutputkeys = count($h);
 83+for ($i = 0; $i < $numoutputkeys; $i++) {
 84+ $key = $outputkeys[$i];
 85+ $value = $h[$key];
 86+ print $key . " = " . $value . "\n";
 87+}
 88+?>
Index: trunk/extensions/DonationInterface/minfraud/ccfd/LocationVerification.php
@@ -0,0 +1,50 @@
 2+<?php
 3+
 4+/* LocationVerification.php
 5+ *
 6+ * Copyright (C) 2005 MaxMind LLC
 7+ *
 8+ * This library is free software; you can redistribute it and/or
 9+ * modify it under the terms of the GNU Lesser General Public
 10+ * License as published by the Free Software Foundation; either
 11+ * version 2.1 of the License, or (at your option) any later version.
 12+ *
 13+ * This library is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 16+ * Lesser General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU Lesser General Public
 19+ * License along with this library; if not, write to the Free Software
 20+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 21+ */
 22+
 23+require_once ("HTTPBase.php");
 24+class LocationVerification extends HTTPBase {
 25+ var $server;
 26+ var $numservers;
 27+ var $API_VERSION;
 28+
 29+ function LocationVerification() {
 30+ $this->HTTPBase();
 31+ $this->isSecure = 1; // use HTTPS by default
 32+
 33+ //set the allowed_fields hash
 34+ $this->allowed_fields["i"] = 1;
 35+ $this->allowed_fields["city"] = 1;
 36+ $this->allowed_fields["region"] = 1;
 37+ $this->allowed_fields["postal"] = 1;
 38+ $this->allowed_fields["country"] = 1;
 39+ $this->allowed_fields["license_key"] = 1;
 40+ $this->num_allowed_fields = count($this->allowed_fields);
 41+
 42+ //set the url of the web service
 43+ $this->url = "app/locvr";
 44+ $this->check_field = "distance";
 45+
 46+ $this->server = array("www.maxmind.com", "www2.maxmind.com");
 47+ $this->numservers = count($this->server);
 48+ $this->API_VERSION = 'PHP/1.4';
 49+ }
 50+}
 51+?>
Index: trunk/extensions/DonationInterface/minfraud/ccfd/Example_locv.php
@@ -0,0 +1,54 @@
 2+#!/usr/bin/php -q
 3+<?php
 4+require("LocationVerification.php");
 5+
 6+//first we create a new CreditCardFraudDetection object
 7+$locv = new LocationVerification;
 8+
 9+//Enter your license key here
 10+$h["license_key"] = "XBCKSF4gnHA7";
 11+
 12+// Set inputs and store them in a hash
 13+
 14+// Required fields
 15+$h["i"] = "24.24.24.24"; // set the client ip address
 16+$h["city"] = "New York"; // set the billing city
 17+$h["region"] = "NY"; // set the billing state
 18+$h["postal"] = "10011"; // set the billing zip code
 19+$h["country"] = "US"; // set the billing country
 20+
 21+// If you want to disable Secure HTTPS or don't have Curl and OpenSSL installed
 22+// uncomment the next line
 23+// $locv->isSecure = 0;
 24+
 25+// how many seconds to cache the ip addresses
 26+$locv->wsIpaddrRefreshTimeout = 3600*5;
 27+// file to store the ip address
 28+$locv->wsIpaddrCacheFile = "/tmp/maxmind.ws.cache";
 29+// if useDNS is 1 then use DNS, otherwise use ip addresses directly
 30+// $locv->useDNS = 1;
 31+
 32+// set the time out to be five seconds
 33+$locv->timeout = 5;
 34+
 35+// uncomment to turn on debugging
 36+$locv->debug = 1;
 37+
 38+// next we set up the input hash
 39+$locv->input($h);
 40+
 41+// then we query the server
 42+$locv->query();
 43+
 44+// then we get the result from the server
 45+$h = $locv->output();
 46+
 47+// then finally we print out the result
 48+$outputkeys = array_keys($h);
 49+$numoutputkeys = count($h);
 50+for ($i = 0; $i < $numoutputkeys; $i++) {
 51+ $key = $outputkeys[$i];
 52+ $value = $h[$key];
 53+ print $key . " = " . $value . "\n";
 54+}
 55+?>
Index: trunk/extensions/DonationInterface/minfraud/ccfd/COPYING
@@ -0,0 +1,504 @@
 2+ GNU LESSER GENERAL PUBLIC LICENSE
 3+ Version 2.1, February 1999
 4+
 5+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
 6+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 7+ Everyone is permitted to copy and distribute verbatim copies
 8+ of this license document, but changing it is not allowed.
 9+
 10+[This is the first released version of the Lesser GPL. It also counts
 11+ as the successor of the GNU Library Public License, version 2, hence
 12+ the version number 2.1.]
 13+
 14+ Preamble
 15+
 16+ The licenses for most software are designed to take away your
 17+freedom to share and change it. By contrast, the GNU General Public
 18+Licenses are intended to guarantee your freedom to share and change
 19+free software--to make sure the software is free for all its users.
 20+
 21+ This license, the Lesser General Public License, applies to some
 22+specially designated software packages--typically libraries--of the
 23+Free Software Foundation and other authors who decide to use it. You
 24+can use it too, but we suggest you first think carefully about whether
 25+this license or the ordinary General Public License is the better
 26+strategy to use in any particular case, based on the explanations below.
 27+
 28+ When we speak of free software, we are referring to freedom of use,
 29+not price. Our General Public Licenses are designed to make sure that
 30+you have the freedom to distribute copies of free software (and charge
 31+for this service if you wish); that you receive source code or can get
 32+it if you want it; that you can change the software and use pieces of
 33+it in new free programs; and that you are informed that you can do
 34+these things.
 35+
 36+ To protect your rights, we need to make restrictions that forbid
 37+distributors to deny you these rights or to ask you to surrender these
 38+rights. These restrictions translate to certain responsibilities for
 39+you if you distribute copies of the library or if you modify it.
 40+
 41+ For example, if you distribute copies of the library, whether gratis
 42+or for a fee, you must give the recipients all the rights that we gave
 43+you. You must make sure that they, too, receive or can get the source
 44+code. If you link other code with the library, you must provide
 45+complete object files to the recipients, so that they can relink them
 46+with the library after making changes to the library and recompiling
 47+it. And you must show them these terms so they know their rights.
 48+
 49+ We protect your rights with a two-step method: (1) we copyright the
 50+library, and (2) we offer you this license, which gives you legal
 51+permission to copy, distribute and/or modify the library.
 52+
 53+ To protect each distributor, we want to make it very clear that
 54+there is no warranty for the free library. Also, if the library is
 55+modified by someone else and passed on, the recipients should know
 56+that what they have is not the original version, so that the original
 57+author's reputation will not be affected by problems that might be
 58+introduced by others.
 59+
 60+ Finally, software patents pose a constant threat to the existence of
 61+any free program. We wish to make sure that a company cannot
 62+effectively restrict the users of a free program by obtaining a
 63+restrictive license from a patent holder. Therefore, we insist that
 64+any patent license obtained for a version of the library must be
 65+consistent with the full freedom of use specified in this license.
 66+
 67+ Most GNU software, including some libraries, is covered by the
 68+ordinary GNU General Public License. This license, the GNU Lesser
 69+General Public License, applies to certain designated libraries, and
 70+is quite different from the ordinary General Public License. We use
 71+this license for certain libraries in order to permit linking those
 72+libraries into non-free programs.
 73+
 74+ When a program is linked with a library, whether statically or using
 75+a shared library, the combination of the two is legally speaking a
 76+combined work, a derivative of the original library. The ordinary
 77+General Public License therefore permits such linking only if the
 78+entire combination fits its criteria of freedom. The Lesser General
 79+Public License permits more lax criteria for linking other code with
 80+the library.
 81+
 82+ We call this license the "Lesser" General Public License because it
 83+does Less to protect the user's freedom than the ordinary General
 84+Public License. It also provides other free software developers Less
 85+of an advantage over competing non-free programs. These disadvantages
 86+are the reason we use the ordinary General Public License for many
 87+libraries. However, the Lesser license provides advantages in certain
 88+special circumstances.
 89+
 90+ For example, on rare occasions, there may be a special need to
 91+encourage the widest possible use of a certain library, so that it becomes
 92+a de-facto standard. To achieve this, non-free programs must be
 93+allowed to use the library. A more frequent case is that a free
 94+library does the same job as widely used non-free libraries. In this
 95+case, there is little to gain by limiting the free library to free
 96+software only, so we use the Lesser General Public License.
 97+
 98+ In other cases, permission to use a particular library in non-free
 99+programs enables a greater number of people to use a large body of
 100+free software. For example, permission to use the GNU C Library in
 101+non-free programs enables many more people to use the whole GNU
 102+operating system, as well as its variant, the GNU/Linux operating
 103+system.
 104+
 105+ Although the Lesser General Public License is Less protective of the
 106+users' freedom, it does ensure that the user of a program that is
 107+linked with the Library has the freedom and the wherewithal to run
 108+that program using a modified version of the Library.
 109+
 110+ The precise terms and conditions for copying, distribution and
 111+modification follow. Pay close attention to the difference between a
 112+"work based on the library" and a "work that uses the library". The
 113+former contains code derived from the library, whereas the latter must
 114+be combined with the library in order to run.
 115+
 116+ GNU LESSER GENERAL PUBLIC LICENSE
 117+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 118+
 119+ 0. This License Agreement applies to any software library or other
 120+program which contains a notice placed by the copyright holder or
 121+other authorized party saying it may be distributed under the terms of
 122+this Lesser General Public License (also called "this License").
 123+Each licensee is addressed as "you".
 124+
 125+ A "library" means a collection of software functions and/or data
 126+prepared so as to be conveniently linked with application programs
 127+(which use some of those functions and data) to form executables.
 128+
 129+ The "Library", below, refers to any such software library or work
 130+which has been distributed under these terms. A "work based on the
 131+Library" means either the Library or any derivative work under
 132+copyright law: that is to say, a work containing the Library or a
 133+portion of it, either verbatim or with modifications and/or translated
 134+straightforwardly into another language. (Hereinafter, translation is
 135+included without limitation in the term "modification".)
 136+
 137+ "Source code" for a work means the preferred form of the work for
 138+making modifications to it. For a library, complete source code means
 139+all the source code for all modules it contains, plus any associated
 140+interface definition files, plus the scripts used to control compilation
 141+and installation of the library.
 142+
 143+ Activities other than copying, distribution and modification are not
 144+covered by this License; they are outside its scope. The act of
 145+running a program using the Library is not restricted, and output from
 146+such a program is covered only if its contents constitute a work based
 147+on the Library (independent of the use of the Library in a tool for
 148+writing it). Whether that is true depends on what the Library does
 149+and what the program that uses the Library does.
 150+
 151+ 1. You may copy and distribute verbatim copies of the Library's
 152+complete source code as you receive it, in any medium, provided that
 153+you conspicuously and appropriately publish on each copy an
 154+appropriate copyright notice and disclaimer of warranty; keep intact
 155+all the notices that refer to this License and to the absence of any
 156+warranty; and distribute a copy of this License along with the
 157+Library.
 158+
 159+ You may charge a fee for the physical act of transferring a copy,
 160+and you may at your option offer warranty protection in exchange for a
 161+fee.
 162+
 163+ 2. You may modify your copy or copies of the Library or any portion
 164+of it, thus forming a work based on the Library, and copy and
 165+distribute such modifications or work under the terms of Section 1
 166+above, provided that you also meet all of these conditions:
 167+
 168+ a) The modified work must itself be a software library.
 169+
 170+ b) You must cause the files modified to carry prominent notices
 171+ stating that you changed the files and the date of any change.
 172+
 173+ c) You must cause the whole of the work to be licensed at no
 174+ charge to all third parties under the terms of this License.
 175+
 176+ d) If a facility in the modified Library refers to a function or a
 177+ table of data to be supplied by an application program that uses
 178+ the facility, other than as an argument passed when the facility
 179+ is invoked, then you must make a good faith effort to ensure that,
 180+ in the event an application does not supply such function or
 181+ table, the facility still operates, and performs whatever part of
 182+ its purpose remains meaningful.
 183+
 184+ (For example, a function in a library to compute square roots has
 185+ a purpose that is entirely well-defined independent of the
 186+ application. Therefore, Subsection 2d requires that any
 187+ application-supplied function or table used by this function must
 188+ be optional: if the application does not supply it, the square
 189+ root function must still compute square roots.)
 190+
 191+These requirements apply to the modified work as a whole. If
 192+identifiable sections of that work are not derived from the Library,
 193+and can be reasonably considered independent and separate works in
 194+themselves, then this License, and its terms, do not apply to those
 195+sections when you distribute them as separate works. But when you
 196+distribute the same sections as part of a whole which is a work based
 197+on the Library, the distribution of the whole must be on the terms of
 198+this License, whose permissions for other licensees extend to the
 199+entire whole, and thus to each and every part regardless of who wrote
 200+it.
 201+
 202+Thus, it is not the intent of this section to claim rights or contest
 203+your rights to work written entirely by you; rather, the intent is to
 204+exercise the right to control the distribution of derivative or
 205+collective works based on the Library.
 206+
 207+In addition, mere aggregation of another work not based on the Library
 208+with the Library (or with a work based on the Library) on a volume of
 209+a storage or distribution medium does not bring the other work under
 210+the scope of this License.
 211+
 212+ 3. You may opt to apply the terms of the ordinary GNU General Public
 213+License instead of this License to a given copy of the Library. To do
 214+this, you must alter all the notices that refer to this License, so
 215+that they refer to the ordinary GNU General Public License, version 2,
 216+instead of to this License. (If a newer version than version 2 of the
 217+ordinary GNU General Public License has appeared, then you can specify
 218+that version instead if you wish.) Do not make any other change in
 219+these notices.
 220+
 221+ Once this change is made in a given copy, it is irreversible for
 222+that copy, so the ordinary GNU General Public License applies to all
 223+subsequent copies and derivative works made from that copy.
 224+
 225+ This option is useful when you wish to copy part of the code of
 226+the Library into a program that is not a library.
 227+
 228+ 4. You may copy and distribute the Library (or a portion or
 229+derivative of it, under Section 2) in object code or executable form
 230+under the terms of Sections 1 and 2 above provided that you accompany
 231+it with the complete corresponding machine-readable source code, which
 232+must be distributed under the terms of Sections 1 and 2 above on a
 233+medium customarily used for software interchange.
 234+
 235+ If distribution of object code is made by offering access to copy
 236+from a designated place, then offering equivalent access to copy the
 237+source code from the same place satisfies the requirement to
 238+distribute the source code, even though third parties are not
 239+compelled to copy the source along with the object code.
 240+
 241+ 5. A program that contains no derivative of any portion of the
 242+Library, but is designed to work with the Library by being compiled or
 243+linked with it, is called a "work that uses the Library". Such a
 244+work, in isolation, is not a derivative work of the Library, and
 245+therefore falls outside the scope of this License.
 246+
 247+ However, linking a "work that uses the Library" with the Library
 248+creates an executable that is a derivative of the Library (because it
 249+contains portions of the Library), rather than a "work that uses the
 250+library". The executable is therefore covered by this License.
 251+Section 6 states terms for distribution of such executables.
 252+
 253+ When a "work that uses the Library" uses material from a header file
 254+that is part of the Library, the object code for the work may be a
 255+derivative work of the Library even though the source code is not.
 256+Whether this is true is especially significant if the work can be
 257+linked without the Library, or if the work is itself a library. The
 258+threshold for this to be true is not precisely defined by law.
 259+
 260+ If such an object file uses only numerical parameters, data
 261+structure layouts and accessors, and small macros and small inline
 262+functions (ten lines or less in length), then the use of the object
 263+file is unrestricted, regardless of whether it is legally a derivative
 264+work. (Executables containing this object code plus portions of the
 265+Library will still fall under Section 6.)
 266+
 267+ Otherwise, if the work is a derivative of the Library, you may
 268+distribute the object code for the work under the terms of Section 6.
 269+Any executables containing that work also fall under Section 6,
 270+whether or not they are linked directly with the Library itself.
 271+
 272+ 6. As an exception to the Sections above, you may also combine or
 273+link a "work that uses the Library" with the Library to produce a
 274+work containing portions of the Library, and distribute that work
 275+under terms of your choice, provided that the terms permit
 276+modification of the work for the customer's own use and reverse
 277+engineering for debugging such modifications.
 278+
 279+ You must give prominent notice with each copy of the work that the
 280+Library is used in it and that the Library and its use are covered by
 281+this License. You must supply a copy of this License. If the work
 282+during execution displays copyright notices, you must include the
 283+copyright notice for the Library among them, as well as a reference
 284+directing the user to the copy of this License. Also, you must do one
 285+of these things:
 286+
 287+ a) Accompany the work with the complete corresponding
 288+ machine-readable source code for the Library including whatever
 289+ changes were used in the work (which must be distributed under
 290+ Sections 1 and 2 above); and, if the work is an executable linked
 291+ with the Library, with the complete machine-readable "work that
 292+ uses the Library", as object code and/or source code, so that the
 293+ user can modify the Library and then relink to produce a modified
 294+ executable containing the modified Library. (It is understood
 295+ that the user who changes the contents of definitions files in the
 296+ Library will not necessarily be able to recompile the application
 297+ to use the modified definitions.)
 298+
 299+ b) Use a suitable shared library mechanism for linking with the
 300+ Library. A suitable mechanism is one that (1) uses at run time a
 301+ copy of the library already present on the user's computer system,
 302+ rather than copying library functions into the executable, and (2)
 303+ will operate properly with a modified version of the library, if
 304+ the user installs one, as long as the modified version is
 305+ interface-compatible with the version that the work was made with.
 306+
 307+ c) Accompany the work with a written offer, valid for at
 308+ least three years, to give the same user the materials
 309+ specified in Subsection 6a, above, for a charge no more
 310+ than the cost of performing this distribution.
 311+
 312+ d) If distribution of the work is made by offering access to copy
 313+ from a designated place, offer equivalent access to copy the above
 314+ specified materials from the same place.
 315+
 316+ e) Verify that the user has already received a copy of these
 317+ materials or that you have already sent this user a copy.
 318+
 319+ For an executable, the required form of the "work that uses the
 320+Library" must include any data and utility programs needed for
 321+reproducing the executable from it. However, as a special exception,
 322+the materials to be distributed need not include anything that is
 323+normally distributed (in either source or binary form) with the major
 324+components (compiler, kernel, and so on) of the operating system on
 325+which the executable runs, unless that component itself accompanies
 326+the executable.
 327+
 328+ It may happen that this requirement contradicts the license
 329+restrictions of other proprietary libraries that do not normally
 330+accompany the operating system. Such a contradiction means you cannot
 331+use both them and the Library together in an executable that you
 332+distribute.
 333+
 334+ 7. You may place library facilities that are a work based on the
 335+Library side-by-side in a single library together with other library
 336+facilities not covered by this License, and distribute such a combined
 337+library, provided that the separate distribution of the work based on
 338+the Library and of the other library facilities is otherwise
 339+permitted, and provided that you do these two things:
 340+
 341+ a) Accompany the combined library with a copy of the same work
 342+ based on the Library, uncombined with any other library
 343+ facilities. This must be distributed under the terms of the
 344+ Sections above.
 345+
 346+ b) Give prominent notice with the combined library of the fact
 347+ that part of it is a work based on the Library, and explaining
 348+ where to find the accompanying uncombined form of the same work.
 349+
 350+ 8. You may not copy, modify, sublicense, link with, or distribute
 351+the Library except as expressly provided under this License. Any
 352+attempt otherwise to copy, modify, sublicense, link with, or
 353+distribute the Library is void, and will automatically terminate your
 354+rights under this License. However, parties who have received copies,
 355+or rights, from you under this License will not have their licenses
 356+terminated so long as such parties remain in full compliance.
 357+
 358+ 9. You are not required to accept this License, since you have not
 359+signed it. However, nothing else grants you permission to modify or
 360+distribute the Library or its derivative works. These actions are
 361+prohibited by law if you do not accept this License. Therefore, by
 362+modifying or distributing the Library (or any work based on the
 363+Library), you indicate your acceptance of this License to do so, and
 364+all its terms and conditions for copying, distributing or modifying
 365+the Library or works based on it.
 366+
 367+ 10. Each time you redistribute the Library (or any work based on the
 368+Library), the recipient automatically receives a license from the
 369+original licensor to copy, distribute, link with or modify the Library
 370+subject to these terms and conditions. You may not impose any further
 371+restrictions on the recipients' exercise of the rights granted herein.
 372+You are not responsible for enforcing compliance by third parties with
 373+this License.
 374+
 375+ 11. If, as a consequence of a court judgment or allegation of patent
 376+infringement or for any other reason (not limited to patent issues),
 377+conditions are imposed on you (whether by court order, agreement or
 378+otherwise) that contradict the conditions of this License, they do not
 379+excuse you from the conditions of this License. If you cannot
 380+distribute so as to satisfy simultaneously your obligations under this
 381+License and any other pertinent obligations, then as a consequence you
 382+may not distribute the Library at all. For example, if a patent
 383+license would not permit royalty-free redistribution of the Library by
 384+all those who receive copies directly or indirectly through you, then
 385+the only way you could satisfy both it and this License would be to
 386+refrain entirely from distribution of the Library.
 387+
 388+If any portion of this section is held invalid or unenforceable under any
 389+particular circumstance, the balance of the section is intended to apply,
 390+and the section as a whole is intended to apply in other circumstances.
 391+
 392+It is not the purpose of this section to induce you to infringe any
 393+patents or other property right claims or to contest validity of any
 394+such claims; this section has the sole purpose of protecting the
 395+integrity of the free software distribution system which is
 396+implemented by public license practices. Many people have made
 397+generous contributions to the wide range of software distributed
 398+through that system in reliance on consistent application of that
 399+system; it is up to the author/donor to decide if he or she is willing
 400+to distribute software through any other system and a licensee cannot
 401+impose that choice.
 402+
 403+This section is intended to make thoroughly clear what is believed to
 404+be a consequence of the rest of this License.
 405+
 406+ 12. If the distribution and/or use of the Library is restricted in
 407+certain countries either by patents or by copyrighted interfaces, the
 408+original copyright holder who places the Library under this License may add
 409+an explicit geographical distribution limitation excluding those countries,
 410+so that distribution is permitted only in or among countries not thus
 411+excluded. In such case, this License incorporates the limitation as if
 412+written in the body of this License.
 413+
 414+ 13. The Free Software Foundation may publish revised and/or new
 415+versions of the Lesser General Public License from time to time.
 416+Such new versions will be similar in spirit to the present version,
 417+but may differ in detail to address new problems or concerns.
 418+
 419+Each version is given a distinguishing version number. If the Library
 420+specifies a version number of this License which applies to it and
 421+"any later version", you have the option of following the terms and
 422+conditions either of that version or of any later version published by
 423+the Free Software Foundation. If the Library does not specify a
 424+license version number, you may choose any version ever published by
 425+the Free Software Foundation.
 426+
 427+ 14. If you wish to incorporate parts of the Library into other free
 428+programs whose distribution conditions are incompatible with these,
 429+write to the author to ask for permission. For software which is
 430+copyrighted by the Free Software Foundation, write to the Free
 431+Software Foundation; we sometimes make exceptions for this. Our
 432+decision will be guided by the two goals of preserving the free status
 433+of all derivatives of our free software and of promoting the sharing
 434+and reuse of software generally.
 435+
 436+ NO WARRANTY
 437+
 438+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
 439+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
 440+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
 441+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
 442+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
 443+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 444+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
 445+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
 446+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 447+
 448+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
 449+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
 450+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
 451+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
 452+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
 453+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
 454+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
 455+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
 456+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 457+DAMAGES.
 458+
 459+ END OF TERMS AND CONDITIONS
 460+
 461+ How to Apply These Terms to Your New Libraries
 462+
 463+ If you develop a new library, and you want it to be of the greatest
 464+possible use to the public, we recommend making it free software that
 465+everyone can redistribute and change. You can do so by permitting
 466+redistribution under these terms (or, alternatively, under the terms of the
 467+ordinary General Public License).
 468+
 469+ To apply these terms, attach the following notices to the library. It is
 470+safest to attach them to the start of each source file to most effectively
 471+convey the exclusion of warranty; and each file should have at least the
 472+"copyright" line and a pointer to where the full notice is found.
 473+
 474+ <one line to give the library's name and a brief idea of what it does.>
 475+ Copyright (C) <year> <name of author>
 476+
 477+ This library is free software; you can redistribute it and/or
 478+ modify it under the terms of the GNU Lesser General Public
 479+ License as published by the Free Software Foundation; either
 480+ version 2.1 of the License, or (at your option) any later version.
 481+
 482+ This library is distributed in the hope that it will be useful,
 483+ but WITHOUT ANY WARRANTY; without even the implied warranty of
 484+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 485+ Lesser General Public License for more details.
 486+
 487+ You should have received a copy of the GNU Lesser General Public
 488+ License along with this library; if not, write to the Free Software
 489+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 490+
 491+Also add information on how to contact you by electronic and paper mail.
 492+
 493+You should also get your employer (if you work as a programmer) or your
 494+school, if any, to sign a "copyright disclaimer" for the library, if
 495+necessary. Here is a sample; alter the names:
 496+
 497+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
 498+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
 499+
 500+ <signature of Ty Coon>, 1 April 1990
 501+ Ty Coon, President of Vice
 502+
 503+That's all there is to it!
 504+
 505+
Index: trunk/extensions/DonationInterface/minfraud/ccfd/Changes
@@ -0,0 +1,42 @@
 2+Revision history for MaxMind CreditCardFraudDetection PHP API
 3+1.49 Februar 19th 2009
 4+ - Add minfraud3.maxmind.com to the server list ( Boris Zentner )
 5+1.48 October 3th 2008
 6+ - Add new optional fields user_agent and accept_language for CCFD requests ( Boris Zentner )
 7+
 8+1.47 April 25th 2008
 9+ - Changed license from GPL to LGPL
 10+
 11+1.46 October 4th 2007
 12+ - Replaced www.maxmind.com and www2.maxmind.com with minfraud1.maxmind.com and minfraud2.maxmind.com
 13+
 14+1.43 October 3rd 2006
 15+ - Added support for new input fields, usernameMD5 and passwordMD5
 16+ - Changed require ("HTTPBase.php") to require_once ("HTTPBase.php")
 17+ in case both CCFD and Telephone Verification files are used (Mike Mallinson)
 18+
 19+1.4 August 8th 2005
 20+ - Added support for Telephone Verification
 21+ - Use POST method instead of GET method, fixes bug where query string
 22+ was truncated
 23+ - Added support for bypassing DNS using IP addresses
 24+ - Added shipCity shipRegion shipPostal shipCountry to list of input fields
 25+
 26+1.3 February 9th 2005
 27+ - Added requested_type, forwardedIP, emailMD5, shipAddr,
 28+ txnID, sessionID to list of input fields
 29+ - Added LocationVerification.php
 30+ - Replaced global variables with class fields (David Recordon)
 31+
 32+1.2 July 2nd 2004
 33+ - Added binName, binPhone, custPhone to list of input fields
 34+
 35+1.1 June 8th 2004
 36+ - Replaced h1 and h2 servers with www and www2 (all ending with maxmind.com)
 37+ - Fixed URL encoding bug
 38+ - Fixed curl code
 39+ - Added debug and timeout options
 40+ - Failover if score field not set
 41+
 42+1.0 May 5st 2004
 43+ - original version
Index: trunk/extensions/DonationInterface/minfraud/ccfd/CreditCardFraudDetection.php
@@ -0,0 +1,83 @@
 2+<?php
 3+
 4+/* CreditCardFraudDetection.php
 5+ *
 6+ * Copyright (C) 2008 MaxMind, Inc.
 7+ *
 8+ * This library is free software; you can redistribute it and/or
 9+ * modify it under the terms of the GNU Lesser General Public
 10+ * License as published by the Free Software Foundation; either
 11+ * version 2.1 of the License, or (at your option) any later version.
 12+ *
 13+ * This library is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 16+ * Lesser General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU Lesser General Public
 19+ * License along with this library; if not, write to the Free Software
 20+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 21+ */
 22+
 23+require_once ("HTTPBase.php");
 24+class CreditCardFraudDetection extends HTTPBase {
 25+ var $server;
 26+ var $numservers;
 27+ var $API_VERSION;
 28+
 29+ function CreditCardFraudDetection() {
 30+ $this->HTTPBase();
 31+ $this->isSecure = 1; // use HTTPS by default
 32+
 33+ //set the allowed_fields hash
 34+ $this->allowed_fields["i"] = 1;
 35+ $this->allowed_fields["domain"] = 1;
 36+ $this->allowed_fields["city"] = 1;
 37+ $this->allowed_fields["region"] = 1;
 38+ $this->allowed_fields["postal"] = 1;
 39+ $this->allowed_fields["country"] = 1;
 40+ $this->allowed_fields["bin"] = 1;
 41+ $this->allowed_fields["binName"] = 1;
 42+ $this->allowed_fields["binPhone"] = 1;
 43+ $this->allowed_fields["custPhone"] = 1;
 44+ $this->allowed_fields["license_key"] = 1;
 45+ $this->allowed_fields["requested_type"] = 1;
 46+ $this->allowed_fields["forwardedIP"] = 1;
 47+ $this->allowed_fields["emailMD5"] = 1;
 48+ $this->allowed_fields["shipAddr"] = 1;
 49+ $this->allowed_fields["shipCity"] = 1;
 50+ $this->allowed_fields["shipRegion"] = 1;
 51+ $this->allowed_fields["shipPostal"] = 1;
 52+ $this->allowed_fields["shipCountry"] = 1;
 53+ $this->allowed_fields["txnID"] = 1;
 54+ $this->allowed_fields["sessionID"] = 1;
 55+ $this->allowed_fields["usernameMD5"] = 1;
 56+ $this->allowed_fields["passwordMD5"] = 1;
 57+ $this->allowed_fields["user_agent"] = 1;
 58+ $this->allowed_fields["accept_language"] = 1;
 59+
 60+
 61+ $this->num_allowed_fields = count($this->allowed_fields);
 62+
 63+ //set the url of the web service
 64+ $this->url = "app/ccv2r";
 65+ $this->check_field = "score";
 66+ $this->server = array("minfraud3.maxmind.com", "minfraud1.maxmind.com", "minfraud2.maxmind.com");
 67+ $this->numservers = count($this->server);
 68+ $this->API_VERSION = 'PHP/1.49';
 69+ }
 70+
 71+ function filter_field($key, $value) {
 72+ if ($key == 'emailMD5'){
 73+ if (ereg('\@',$value)){
 74+ return md5(strtolower($value));
 75+ }
 76+ } else if ($key == 'usernameMD5' || $key == 'passwordMD5') {
 77+ if (strlen($value) != 32) {
 78+ return md5(strtolower($value));
 79+ }
 80+ }
 81+ return $value;
 82+ }
 83+}
 84+?>
Index: trunk/extensions/DonationInterface/minfraud/ccfd/Example_telv.php
@@ -0,0 +1,54 @@
 2+#!/usr/bin/php -q
 3+<?php
 4+require("TelephoneVerification.php");
 5+
 6+$tv = new TelephoneVerification;
 7+
 8+// Set inputs and store them in a hash
 9+// See http://www.maxmind.com/app/telephone_form for more details on the input fields
 10+
 11+// Enter your license key here
 12+// $h["l"] = "YOUR_LICENSE_KEY_HERE";
 13+
 14+// Enter your telephone number here
 15+// $h["phone"] = "YOUR_TELEPHONE_NUMBER_HERE";
 16+
 17+// $h["verify_code"] = "5783";
 18+
 19+// If you want to disable Secure HTTPS or don't have Curl and OpenSSL installed
 20+// uncomment the next line
 21+// $tv->isSecure = 0;
 22+
 23+//set the time out to be 30 seconds
 24+$tv->timeout = 30;
 25+
 26+//uncomment to turn on debugging
 27+// $tv->debug = 1;
 28+
 29+//how many seconds the cache the ip addresses
 30+$ccfs->wsIpaddrRefreshTimeout = 3600*5;
 31+
 32+//where to store the ip address
 33+$ccfs->wsIpaddrCacheFile = "/tmp/maxmind.ws.cache";
 34+
 35+// if useDNS is 1 then use DNS, otherwise use ip addresses directly
 36+$ccfs->useDNS = 0;
 37+
 38+// next we set up the input hash to be passed to the server
 39+$tv->input($h);
 40+
 41+// then we query the server
 42+$tv->query();
 43+
 44+// then we get the result from the server
 45+$h = $tv->output();
 46+
 47+//then finally we print out the result
 48+$outputkeys = array_keys($h);
 49+$numoutputkeys = count($h);
 50+for ($i = 0; $i < $numoutputkeys; $i++) {
 51+ $key = $outputkeys[$i];
 52+ $value = $h[$key];
 53+ print $key . " = " . $value . "\n";
 54+}
 55+?>
Index: trunk/extensions/DonationInterface/minfraud/ccfd/TelephoneVerification.php
@@ -0,0 +1,26 @@
 2+<?php
 3+require_once ("HTTPBase.php");
 4+class TelephoneVerification extends HTTPBase {
 5+ var $server;
 6+ var $numservers;
 7+ var $API_VERSION;
 8+ function TelephoneVerification(){
 9+ $this->HTTPBase();
 10+ $this->isSecure = 1; // use HTTPS by default
 11+
 12+ //set the allowed_fields hash
 13+ $this->allowed_fields["l"] = 1;
 14+ $this->allowed_fields["phone"] = 1;
 15+ $this->allowed_fields["verify_code"] = 1;
 16+ $this->num_allowed_fields = count($this->allowed_fields);
 17+
 18+ //set the url of the web service
 19+ $this->url = "app/telephone_http";
 20+ $this->check_field = "refid";
 21+ $this->server = array("www.maxmind.com", "www2.maxmind.com");
 22+ $this->numservers = count($this->server);
 23+ $this->API_VERSION = 'PHP/1.4';
 24+ $this->timeout = 30;
 25+ }
 26+}
 27+?>
Index: trunk/extensions/DonationInterface/minfraud/ccfd/README
@@ -0,0 +1,63 @@
 2+Maxmind Credit Card Fraud Detection Service PHP API Version 1.49
 3+
 4+===============
 5+Example scripts
 6+
 7+See Example.php for complete example how to use this API with the CCFD service.
 8+See Example_telv.php for complete example how to use this API with the Telephone Verification service.
 9+See Example_locv.php for complete example how to use this API with the Location Verification service.
 10+These scripts can be run from the shell.
 11+
 12+==================================
 13+API Documentation for CCFD service
 14+
 15+$ccfs = new CreditCardFraudDetection;
 16+ This creates a new CreditCardFraudDetection object
 17+
 18+$ccfs->isSecure
 19+ If isSecure is set to 0 then it uses regular HTTP.
 20+ If isSecure is set to 1 then it uses Secure HTTPS (requires Curl PHP binding)
 21+
 22+$ccfs->input($hash)
 23+ Takes a hash and uses it as input for the server.
 24+ See http://www.maxmind.com/app/ccv for details on input fields.
 25+
 26+$ccfs->query();
 27+ Queries the server with the fields passed to the input method
 28+ and stores the output.
 29+
 30+$hash = $ccfs->output();
 31+ Returns the output from the server.
 32+ See http://www.maxmind.com/app/ccv for details on output fields.
 33+
 34+============
 35+Secure HTTPS
 36+
 37+If you want secure HTTPS then you need to have
 38+the Curl PHP binding, the curl libary and the OpenSSL libary.
 39+
 40+You can download the curl libary at
 41+http://curl.haxx.se/download.html
 42+http://curl.haxx.se/docs/install.html for installation details
 43+
 44+If you do not have curl PHP binding then you should install it.
 45+See the web page
 46+http://curl.haxx.se/libcurl/php/install.html for details
 47+
 48+It is recommended that you install these packages in this order
 49+install the OpenSSL libary first
 50+then install the Curl libary second
 51+then install the Curl PHP binding last
 52+
 53+Secure HTTPS is off by default.
 54+If you have the Curl PHP binding, the Curl libary
 55+and the OpenSSL libary then you can turn on Secure HTTPS
 56+by setting:
 57+$ccfs->isSecure = 1;
 58+where $ccfs is the CreditCardFraudDetection object.
 59+
 60+===============================
 61+Copyright (c) 2008, MaxMind, Inc
 62+
 63+All rights reserved. This package is licensed under the LGPL. For details see
 64+the COPYING file.
Index: trunk/extensions/DonationInterface/minfraud/tests/minfraudTest.php
@@ -0,0 +1,158 @@
 2+<?php
 3+require_once "PHPUnit/Framework.php";
 4+
 5+class minfraudTest extends PHPUnit_Framework_TestCase
 6+{
 7+ protected function setUp() {
 8+ require_once( __FILE__ . '/../../minfraud.php');
 9+ global $wgMinFraudLog;
 10+ $wgMinFraudLog = dirname(__FILE__) . "/test_log";
 11+ $license_key = 'XBCKSF4gnHA7';
 12+ $this->fixture = new MinFraud( $license_key );
 13+ }
 14+
 15+ protected function tearDown() {
 16+ global $wgMinFraudLog;
 17+ unlink( $wgMinFraudLog );
 18+ }
 19+
 20+ public function testCcfdInstance() {
 21+ $ccfd_instance_test = $this->fixture->get_ccfd() instanceof CreditCardFraudDetection;
 22+ $this->assertTrue( $ccfd_instance_test );
 23+ }
 24+
 25+ /**
 26+ * @dataProvider queryDataProvider
 27+ */
 28+ public function testBuildQuery( $data ) {
 29+ $query = $this->fixture->build_query( $data );
 30+ $this->assertArrayHasKey( "i", $query );
 31+ $this->assertArrayHasKey( "user_agent", $query );
 32+ $this->assertArrayHasKey( "city", $query );
 33+ $this->assertArrayHasKey( "region", $query );
 34+ $this->assertArrayHasKey( "postal", $query );
 35+ $this->assertArrayHasKey( "country", $query );
 36+ $this->assertArrayHasKey( "domain", $query );
 37+ $this->assertArrayHasKey( "emailMD5", $query );
 38+ $this->assertArrayHasKey( "bin", $query );
 39+ $this->assertArrayHasKey( "txnID", $query );
 40+ $this->assertArrayNotHasKey( "foo", $query ); //make sure we're not adding extraneous info
 41+ $this->assertNotContains( "@", $query[ 'domain' ] ); //make sure we're only getting domains from email addresses
 42+ $this->assertEquals( 6, strlen( $query[ 'bin' ] )); //make sure our bin is 6 digits long
 43+ }
 44+
 45+ public function queryDataProvider() {
 46+ $data = array(
 47+ array(
 48+ array(
 49+ "city" => 'san francisco',
 50+ "state" => 'ca',
 51+ "zip" => '94104',
 52+ "country" => 'US',
 53+ "email" => 'test@example.com',
 54+ "card_num" => "378282246310005",
 55+ "contribution_tracking_id" => "banana",
 56+ "foo" => "bar"
 57+ )
 58+ )
 59+ );
 60+ return $data;
 61+ }
 62+
 63+ /**
 64+ * @dataProvider queryDataProvider
 65+ */
 66+/* public function testQueryMinfraud( $data ) {
 67+ $query = $this->fixture->build_query( $data );
 68+ $this->fixture->query_minfraud( $query );
 69+ $this->assertType( 'array', $this->fixture->minfraud_response );
 70+ }*/
 71+
 72+ /**
 73+ * @dataProvider hashValidateFalseData
 74+ */
 75+ public function testValidateMinfraudHashFalse( $data ) {
 76+ $this->assertFalse( $this->fixture->validate_minfraud_hash( $data ));
 77+ }
 78+
 79+ public function hashValidateFalseData() {
 80+ return array(
 81+ array(
 82+ array(),
 83+ array( 'license_key' => 'a' ),
 84+ array(
 85+ 'license_key' => 'a',
 86+ 'i' => 'a',
 87+ ),
 88+ array(
 89+ 'license_key' => 'a',
 90+ 'i' => 'a',
 91+ 'city' => 'a'
 92+ ),
 93+ array(
 94+ 'license_key' => 'a',
 95+ 'i' => 'a',
 96+ 'city' => 'a',
 97+ 'region' => 'a'
 98+ ),
 99+ array(
 100+ 'license_key' => 'a',
 101+ 'i' => 'a',
 102+ 'city' => 'a',
 103+ 'region' => 'a',
 104+ 'postal' => 'a',
 105+ ),
 106+ array(
 107+ 'license_key' => 'a',
 108+ 'country' => 'a',
 109+ )
 110+ )
 111+ );
 112+ }
 113+
 114+ /**
 115+ * @dataProvider hashValidateTrueData
 116+ */
 117+ public function testValidateMinfraudHashTrue( $data ) {
 118+ $this->assertTrue( $this->fixture->validate_minfraud_hash( $data ));
 119+ }
 120+
 121+ public function hashValidateTrueData() {
 122+ return array(
 123+ array(
 124+ array(
 125+ 'license_key' => 'a',
 126+ 'i' => 'a',
 127+ 'city' => 'a',
 128+ 'region' => 'a',
 129+ 'postal' => 'a',
 130+ 'country' => 'a'
 131+ )
 132+ )
 133+ );
 134+ }
 135+
 136+ /**
 137+ * @dataProvider determineActionsData
 138+ */
 139+ public function testDetermineActions( $risk_score, $action_ranges, $expected ) {
 140+ $this->fixture->action_ranges = $action_ranges;
 141+ $this->assertEquals( $expected, $this->fixture->determine_actions( $risk_score ));
 142+ }
 143+
 144+ public function determineActionsData() {
 145+ return array(
 146+ array( '0.1', array( 'process' => array(0, 100)), array('process')),
 147+ array( '75.04', array( 'process' => array(0, 50), 'reject' => array( '50.01', '100')), array('reject')),
 148+ array( '15', array( 'process' => array(0, 50), 'review' => array(10, 20)), array('process','review'))
 149+ );
 150+ }
 151+
 152+ public function testLogging() {
 153+ global $wgMinFraudLog;
 154+ $this->fixture->log( "foo" );
 155+ $new_fh = fopen( $wgMinFraudLog, 'r' );
 156+ $this->assertEquals("foo\n", fread( $new_fh, filesize( $wgMinFraudLog ) ));
 157+ fclose( $new_fh );
 158+ }
 159+}
Index: trunk/extensions/DonationInterface/minfraud/minfraud.il8n.php
Index: trunk/extensions/DonationInterface/minfraud/minfraud.php
@@ -0,0 +1,223 @@
 2+<?php
 3+
 4+class MinFraud {
 5+
 6+ /**
 7+ * Full response from minFraud
 8+ * @var public array
 9+ */
 10+ public $minfraud_response = NULL;
 11+
 12+ /**
 13+ * License key for minfraud
 14+ * @var public string
 15+ */
 16+ public $minfraud_license_key = NULL;
 17+
 18+ /**
 19+ * File handle for log file
 20+ * @var public
 21+ */
 22+ public $log_fh = NULL;
 23+
 24+ /**
 25+ * User-definable riskScore ranges for actions to take
 26+ * @var public array
 27+ */
 28+ public $action_ranges = array(
 29+ 'process' => array( 0, 100 ),
 30+ 'review' => array( -1, -1 ),
 31+ 'challenge' => array( -1, -1 ),
 32+ 'reject' => array( -1, -1 ),
 33+ );
 34+
 35+ function __construct( $license_key = NULL ) {
 36+ require_once( __FILE__ . "/../ccfd/CreditCardFraudDetection.php" );
 37+
 38+ global $wgMinFraudLicenseKey, $wgMinFraudActionRanges, $wgMinFraudLog;
 39+
 40+ // set the minfraud license key, go no further if we don't have it
 41+ if ( !$license_key && !$wgMinFraudLicenseKey ) {
 42+ throw new Exception( "minFraud license key required but not present." );
 43+ }
 44+ $this->minfraud_license_key = ( $license_key ) ? $license_key : $wgMinFraudLicenseKey;
 45+
 46+ if ( isset( $wgMinFraudActionRanges )) $this->action_ranges = $wgMinFraudActionRanges;
 47+
 48+ $log_file = ( $wgMinFraudLog ) ? $wgMinFraudLog : "/var/log/mw/minfraud";
 49+ $this->prepare_log_file( $log_file );
 50+ }
 51+
 52+ /**
 53+ * Query minFraud with the transaction, set actions to take and make a log entry
 54+ *
 55+ * Accessible via $wgHooks[ 'PayflowGatewayValidate' ]
 56+ * @param object PayflowPro Gateway object
 57+ * @param array The array of data generated from an attempted transaction
 58+ */
 59+ public function validate( &$pfp_gateway_object, $data ) {
 60+ $minfraud_hash = $this->build_query( $data );
 61+ $this->query_minfraud( $minfraud_hash );
 62+ $pfp_gateway_object->actions = $this->determine_actions( $this->minfraud_response[ 'riskScore' ] );
 63+ $log_message = '"'. date('c') . '"';
 64+ $log_message .= "\t" . '"' . $data[ 'contribution_tracking_id' ] . '"';
 65+ $log_message .= "\t" . '"' . $data[ 'comment' ] . '"';
 66+ $log_message .= "\t" . '"' . $data[ 'amount' ] . ' ' . $data[ 'currency' ] . '"';
 67+ $log_message .= "\t" . '"' . serialize( $minfraud_hash ) . '"';
 68+ $log_message .= "\t" . '"' . serialize( $this->minfraud_response ) . '"';
 69+ $log_message .= "\t" . '"' . serialize( $pfp_gateway_object->actions ) . '"';
 70+ $this->log( $log_message );
 71+ return TRUE;
 72+ }
 73+
 74+ /**
 75+ * Get instance of CreditCardFraudDetection
 76+ * @return object
 77+ */
 78+ public function get_ccfd() {
 79+ if ( !$this->ccfd ) {
 80+ $this->ccfd = new CreditCardFraudDetection;
 81+ }
 82+ return $this->ccfd;
 83+ }
 84+
 85+ /**
 86+ * Builds minfraud query hash from user input
 87+ * @return array containing hash for minfraud query
 88+ */
 89+ public function build_query( array $data ) {
 90+ // mapping of data keys -> minfraud hash keys
 91+ $map = array(
 92+ "city" => "city",
 93+ "region" => "state",
 94+ "postal" => "zip",
 95+ "country" => "country",
 96+ "domain" => "email",
 97+ "emailMD5" => "email",
 98+ "bin" => "card_num",
 99+ "txnID" => "contribution_tracking_id"
 100+ );
 101+
 102+ // minfraud license key
 103+ $minfraud_hash[ "license_key" ] = $this->minfraud_license_key;
 104+
 105+ // user's IP address
 106+ $minfraud_hash[ "i" ] = $_SERVER[ 'REMOTE_ADDR' ];
 107+
 108+ // user's user agent
 109+ $minfraud_hash[ "user_agent" ] = $_SERVER[ 'HTTP_USER_AGENT' ];
 110+
 111+ // loop through the map and add pertinent values from $data to the hash
 112+ foreach ( $map as $key => $value ) {
 113+
 114+ // do some data processing to clean up values for minfraud
 115+ switch ( $key ) {
 116+ case "domain": // get just the domain from the email address
 117+ $newdata[ $value ] = substr( strstr( $data[ $value ], '@' ), 1 );
 118+ break;
 119+ case "bin": // get just the first 6 digits from CC#
 120+ $newdata[ $value ] = substr( $data[ $value ], 0, 6 );
 121+ break;
 122+ default:
 123+ $newdata[ $value ] = $data[ $value ];
 124+ }
 125+
 126+ $minfraud_hash[ $key ] = $newdata[ $value ];
 127+ }
 128+
 129+ return $minfraud_hash;
 130+ }
 131+
 132+ /**
 133+ * Perform the min fraud query and capture the response
 134+ */
 135+ public function query_minfraud( array $minfraud_hash ) {
 136+ $this->get_ccfd()->input( $minfraud_hash );
 137+ $this->get_ccfd()->query();
 138+ $this->minfraud_response = $this->get_ccfd()->output();
 139+ }
 140+
 141+ /**
 142+ * Validates the minfraud_hash for minimum required fields
 143+ *
 144+ * This is a pretty dumb validator. It just checks to see if
 145+ * there is a value for a required field and if its length is > 0
 146+ *
 147+ * @param array $minfraud_hash which is the hash you would pass to
 148+ * minfraud in a query
 149+ * @result bool
 150+ */
 151+ public function validate_minfraud_hash( array $minfraud_hash ) {
 152+ // array of minfraud required fields
 153+ $reqd_fields = array(
 154+ 'license_key',
 155+ 'i',
 156+ 'city',
 157+ 'region',
 158+ 'postal',
 159+ 'country'
 160+ );
 161+
 162+ foreach ( $reqd_fields as $reqd_field ) {
 163+ if ( !isset( $minfraud_hash[ $reqd_field ] ) ||
 164+ strlen( $minfraud_hash[ $reqd_field ] ) < 1 ) {
 165+ return FALSE;
 166+ }
 167+ }
 168+
 169+ return TRUE;
 170+ }
 171+
 172+ /**
 173+ * Determine the actions for the processor to take
 174+ *
 175+ * Determined based on predefined riskScore ranges for
 176+ * a given action. It is possible to return multiple
 177+ * ranges.
 178+ * @param float risk score (returned from minFraud)
 179+ * @return array of actions to be taken
 180+ */
 181+ public function determine_actions( $risk_score ) {
 182+ $actions = array();
 183+ foreach ( $this->action_ranges as $action => $range ) {
 184+ if ( $risk_score >= $range[0] && $risk_score <= $range[1] ) {
 185+ $actions[] = $action;
 186+ }
 187+ }
 188+ return $actions;
 189+ }
 190+
 191+ /**
 192+ * Prepares a log file
 193+ *
 194+ * @param string path to log file
 195+ * @return resource Pointer for the log file
 196+ */
 197+ protected function prepare_log_file( $log_file ) {
 198+ $this->log_fh = fopen( $log_file, 'a+' );
 199+ }
 200+
 201+ /**
 202+ * Writes message to a log file
 203+ *
 204+ * If a log file does not exist and could not be created,
 205+ * do nothing.
 206+ * @fixme Perhaps lack of log file can be handled better,
 207+ * or maybe it doesn't matter?
 208+ * @param string The message to log
 209+ */
 210+ public function log( $msg ) {
 211+ if ( !$this->log_fh ) {
 212+ return;
 213+ }
 214+ $msg .= "\n";
 215+ fwrite( $this->log_fh, $msg );
 216+ }
 217+
 218+ /**
 219+ * Close the open log file handler if it's open
 220+ */
 221+ public function __destruct() {
 222+ if ( $this->log_fh ) fclose( $this->log_fh );
 223+ }
 224+}

Comments

#Comment by Raymond (talk | contribs)   08:30, 7 August 2010

minfraud.il8n.php has the uncommon name part "il8n" (character l) instead of "i18n" (number 1).

The file size is 0 byte but if it will be filled with messages in the future I recommend to rename it.

#Comment by Tim Starling (talk | contribs)   04:55, 16 August 2010

Please remove the example files, they do scary things when run from the web.

You need to add defaults for any global variables that you use. Documentation should be attached to the default, it should not be in a comment at the top of the implementation file. Put the defaults in the extension setup file. In this case, the extension setup file will probably be minfraud.php, although renaming it may be useful.

In minfraud.php:

 * In LocalSettings.php
 *	$wgPayflowExtraMinFraud = new PayflowProGateway_Extras_MinFraud( '<your minfraud license key>' )

Do not construct objects in the configuration file. It is slow. Do it only when the relevant hook is called. You should follow the example from most other MediaWiki extensions: move the class definitions into separate files, and only set $wgAutoloadClasses in the extension setup file, do not actually include the class definitions. This kind of code:

$dir = dirname( __FILE__ ) . "/";
require_once( $dir . "../extras.php" );

is unnecessary, and can be replaced by autoloading for a substantial performance benefit.

 * $wgHooks["PayflowGatewayValidate"][] = array( $wgPayflowExtraMinFraud, "validate" ); // sets minfraud as a validator for transactions

You should actually set the hook in this file, rather than instructing the user to set it. Use something like:

$wgHooks["PayflowGatewayValidate"][] = array( 'PayflowProGateway_Extras_MinFraud', 'onValidate' );
class PayflowProGateway_Extras_MinFraud {
	static $instance;

	static function onValidate( &$pfp_gateway_object, &$data ) {
		return self::singleton()->validate( &$pfp_gateway_object, &$data );
	}

	static function singleton() {
		if ( !self::$instance ) {
			self::$instance = new self;
		}
		return self::$instance;
	}

This defers creation of the object until it is needed, and allows you to rename the class without requiring that users change their configuration.

throw new Exception( "minFraud license key required but not present." );

Use MWException not Exception.

		// user's IP address
		$minfraud_hash[ "i" ] = $_SERVER[ 'REMOTE_ADDR' ];

Use wfGetIP(), because $_SERVER['REMOTE_ADDR'] only works when the server is directly exposed to the web, it does not work when it is behind a proxy.

		// user's user agent
		$minfraud_hash[ "user_agent" ] = $_SERVER[ 'HTTP_USER_AGENT' ];

Using $_SERVER to fetch headers is insecure, because header names with underscores in them can be made to conflict with the header names with hyphens, in a security-impacting way. Instead, use $wgRequest->getHeader().

	 * Check to see if we can bypass minFraud check
...
	public function bypass_minfraud( &$pfp_gateway_object, &$data ) {

If you want other people to be able to understand your code, you should choose function names that describe what the function does. A function called "bypass_minfraud" should actually bypass minfraud when it is called. This function does not. I suggest "can_bypass_minfraud".

$minfraud_hash = $this->build_query( $data );

May I suggest not calling arrays "hashes", especially in code which also uses actual hashes? I know the MaxMind code does it, so it's important to be especially clear in your own code to avoid confusion. An array is somewhat like a hashtable, but it's not at all like a hash.

		if ( strlen( $data[ 'data_hash' ] ) > 0 && strlen( $data[ 'action' ] ) > 0 ) {
			... 25 lines ...
		}
		return FALSE;

Use early returns to reduce indentation of bulk code and improve clarity:

		if ( !strlen( $data[ 'data_hash' ] ) || !strlen( $data[ 'action' ] ) ) {
			return FALSE;
		}
		... 25 lines ...
#Comment by Tim Starling (talk | contribs)   06:14, 16 August 2010

In build_query(), why do you omit accept_language?

#Comment by Tim Starling (talk | contribs)   06:36, 16 August 2010

Comments above are whole-file reviews as of r71005 and include code added in r70846.

#Comment by Awjrichards (talk | contribs)   23:58, 25 August 2010

Updated code to reflect above suggestions as of r71675

Status & tagging log