From acb6cada796d45e47b4aa487fedeb913b90fac44 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sat, 6 Jan 2018 21:59:18 -0500 Subject: [PATCH 01/14] Fix for plus signs in data $_POST can decode plus signs incorrectly and should not be used. I have done extensive testing so far and have not found a better way than this to fix this problem from this end. This problem will only be completely solved when the posted data is sent with plus signs always encoded to %2B. --- php/PaypalIPN.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 443e802..3698ce2 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -63,7 +63,7 @@ public function getPaypalUri() * Verification Function * Sends the incoming post data back to PayPal using the cURL library. * - * @return bool + * @return array or bool false * @throws Exception */ public function verifyIPN() @@ -78,13 +78,14 @@ public function verifyIPN() foreach ($raw_post_array as $keyval) { $keyval = explode('=', $keyval); if (count($keyval) == 2) { - // Since we do not want the plus in the datetime string to be encoded to a space, we manually encode it. - if ($keyval[0] === 'payment_date') { - if (substr_count($keyval[1], '+') === 1) { - $keyval[1] = str_replace('+', '%2B', $keyval[1]); - } + // Since we do not want the plus signs in the date and email strings to be encoded to a space, we use rawurldecode instead of urldecode + if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || filter_var(rawurldecode($keyval[1]), FILTER_VALIDATE_EMAIL)) { + // Keep plus signs + $myPost[$keyval[0]] = rawurldecode($keyval[1]); + } else { + // Convert plus signs to spaces + $myPost[$keyval[0]] = urldecode($keyval[1]); } - $myPost[$keyval[0]] = urldecode($keyval[1]); } } @@ -96,9 +97,9 @@ public function verifyIPN() } foreach ($myPost as $key => $value) { if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { - $value = urlencode(stripslashes($value)); + $value = rawurlencode(stripslashes($value)); } else { - $value = urlencode($value); + $value = rawurlencode($value); } $req .= "&$key=$value"; } @@ -138,9 +139,8 @@ public function verifyIPN() // Check if PayPal verifies the IPN data, and if so, return true. if ($res == self::VALID) { - return true; - } else { - return false; + return $myPost; } + return false; } } From 896a6eb569baac82d24edabe1389684c7de7eb8a Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sat, 6 Jan 2018 23:44:59 -0500 Subject: [PATCH 02/14] data array --- php/PaypalIPN.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 3698ce2..5033a63 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -137,7 +137,7 @@ public function verifyIPN() curl_close($ch); - // Check if PayPal verifies the IPN data, and if so, return true. + // Check if PayPal verifies the IPN data, and if so, return data array. if ($res == self::VALID) { return $myPost; } From d69f6540f01446d8dae0c2abd30aece6e538548e Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sat, 6 Jan 2018 23:48:28 -0500 Subject: [PATCH 03/14] Update PaypalIPN.php --- php/PaypalIPN.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 5033a63..6c1ccec 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -63,7 +63,7 @@ public function getPaypalUri() * Verification Function * Sends the incoming post data back to PayPal using the cURL library. * - * @return array or bool false + * @return array or false * @throws Exception */ public function verifyIPN() From c30a01917e0709b6838a93e2601409e14ee41739 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sun, 7 Jan 2018 00:25:33 -0500 Subject: [PATCH 04/14] moved stripslashes --- php/PaypalIPN.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 6c1ccec..27a761d 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -72,6 +72,11 @@ public function verifyIPN() throw new Exception("Missing POST Data"); } + $get_magic_quotes_exists = false; + if (function_exists('get_magic_quotes_gpc')) { + $get_magic_quotes_exists = true; + } + $raw_post_data = file_get_contents('php://input'); $raw_post_array = explode('&', $raw_post_data); $myPost = array(); @@ -86,21 +91,16 @@ public function verifyIPN() // Convert plus signs to spaces $myPost[$keyval[0]] = urldecode($keyval[1]); } + if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { + $myPost[$keyval[0]] = stripslashes($myPost[$keyval[0]]); + } } } // Build the body of the verification post request, adding the _notify-validate command. $req = 'cmd=_notify-validate'; - $get_magic_quotes_exists = false; - if (function_exists('get_magic_quotes_gpc')) { - $get_magic_quotes_exists = true; - } foreach ($myPost as $key => $value) { - if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { - $value = rawurlencode(stripslashes($value)); - } else { - $value = rawurlencode($value); - } + $value = rawurlencode($value); $req .= "&$key=$value"; } From bb60d8f884beaa7140900eec4e455963ee16f5ca Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sun, 7 Jan 2018 00:44:50 -0500 Subject: [PATCH 05/14] edit magic_quotes_enabled check --- php/PaypalIPN.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 27a761d..1b2dd47 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -72,14 +72,13 @@ public function verifyIPN() throw new Exception("Missing POST Data"); } - $get_magic_quotes_exists = false; - if (function_exists('get_magic_quotes_gpc')) { - $get_magic_quotes_exists = true; - } - $raw_post_data = file_get_contents('php://input'); $raw_post_array = explode('&', $raw_post_data); $myPost = array(); + $magic_quotes_enabled = false; + if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() == 1) { + $magic_quotes_enabled = true; + } foreach ($raw_post_array as $keyval) { $keyval = explode('=', $keyval); if (count($keyval) == 2) { @@ -91,7 +90,7 @@ public function verifyIPN() // Convert plus signs to spaces $myPost[$keyval[0]] = urldecode($keyval[1]); } - if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { + if ($magic_quotes_enabled) { $myPost[$keyval[0]] = stripslashes($myPost[$keyval[0]]); } } From b27dc98f8c83dca1756fff014ac501a05ba36601 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sun, 7 Jan 2018 01:10:57 -0500 Subject: [PATCH 06/14] don't use magic_quotes with rawurldecode --- php/PaypalIPN.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 1b2dd47..e46b8d5 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -89,9 +89,9 @@ public function verifyIPN() } else { // Convert plus signs to spaces $myPost[$keyval[0]] = urldecode($keyval[1]); - } - if ($magic_quotes_enabled) { - $myPost[$keyval[0]] = stripslashes($myPost[$keyval[0]]); + if ($magic_quotes_enabled) { + $myPost[$keyval[0]] = stripslashes($myPost[$keyval[0]]); + } } } } From aa09c2623a53cc7c2dba92192bf1010b8b7bd527 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sun, 7 Jan 2018 03:08:51 -0500 Subject: [PATCH 07/14] Update PaypalIPN.php --- php/PaypalIPN.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index e46b8d5..73c676d 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -83,7 +83,7 @@ public function verifyIPN() $keyval = explode('=', $keyval); if (count($keyval) == 2) { // Since we do not want the plus signs in the date and email strings to be encoded to a space, we use rawurldecode instead of urldecode - if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || filter_var(rawurldecode($keyval[1]), FILTER_VALIDATE_EMAIL)) { + if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || ($_POST["test_ipn"] == 1 && filter_var(rawurldecode($keyval[1]), FILTER_VALIDATE_EMAIL))) { // Keep plus signs $myPost[$keyval[0]] = rawurldecode($keyval[1]); } else { From 470468e62ed3f31b79f11945f9ba1a302443ca33 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sun, 7 Jan 2018 03:12:34 -0500 Subject: [PATCH 08/14] Update PaypalIPN.php --- php/PaypalIPN.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 73c676d..1df6653 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -83,7 +83,7 @@ public function verifyIPN() $keyval = explode('=', $keyval); if (count($keyval) == 2) { // Since we do not want the plus signs in the date and email strings to be encoded to a space, we use rawurldecode instead of urldecode - if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || ($_POST["test_ipn"] == 1 && filter_var(rawurldecode($keyval[1]), FILTER_VALIDATE_EMAIL))) { + if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || ($_POST["test_ipn"] == 1 && filter_var($keyval[1], FILTER_VALIDATE_EMAIL))) { // Keep plus signs $myPost[$keyval[0]] = rawurldecode($keyval[1]); } else { From 034a7d9b9720b6f247fd00c1c6ba901c055fc831 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sun, 7 Jan 2018 03:20:08 -0500 Subject: [PATCH 09/14] Update PaypalIPN.php --- php/PaypalIPN.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 1df6653..d570bd1 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -83,7 +83,7 @@ public function verifyIPN() $keyval = explode('=', $keyval); if (count($keyval) == 2) { // Since we do not want the plus signs in the date and email strings to be encoded to a space, we use rawurldecode instead of urldecode - if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || ($_POST["test_ipn"] == 1 && filter_var($keyval[1], FILTER_VALIDATE_EMAIL))) { + if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || filter_var($keyval[1], FILTER_VALIDATE_EMAIL)) { // Keep plus signs $myPost[$keyval[0]] = rawurldecode($keyval[1]); } else { From efbb2169b1ae17f8a3a324ae00640eb5a40ad4dd Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Sun, 7 Jan 2018 03:59:37 -0500 Subject: [PATCH 10/14] Update PaypalIPN.php --- php/PaypalIPN.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index d570bd1..1df6653 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -83,7 +83,7 @@ public function verifyIPN() $keyval = explode('=', $keyval); if (count($keyval) == 2) { // Since we do not want the plus signs in the date and email strings to be encoded to a space, we use rawurldecode instead of urldecode - if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || filter_var($keyval[1], FILTER_VALIDATE_EMAIL)) { + if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || ($_POST["test_ipn"] == 1 && filter_var($keyval[1], FILTER_VALIDATE_EMAIL))) { // Keep plus signs $myPost[$keyval[0]] = rawurldecode($keyval[1]); } else { From c8b5b8ec4d7ad0bd344932340b9b47ab09aacc96 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Wed, 10 Jan 2018 13:12:43 -0500 Subject: [PATCH 11/14] implemented requests from reviewer --- php/PaypalIPN.php | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 1df6653..10d39ef 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -63,12 +63,15 @@ public function getPaypalUri() * Verification Function * Sends the incoming post data back to PayPal using the cURL library. * - * @return array or false + * @return array|bool * @throws Exception */ public function verifyIPN() { - if ( ! count($_POST)) { + if (version_compare(phpversion(), '5.3.0', '<')) { + throw new Exception("Requires PHP version 5.3.0 or greater"); + } + if ( ! count($_POST) ) { throw new Exception("Missing POST Data"); } @@ -76,22 +79,23 @@ public function verifyIPN() $raw_post_array = explode('&', $raw_post_data); $myPost = array(); $magic_quotes_enabled = false; - if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() == 1) { - $magic_quotes_enabled = true; - } foreach ($raw_post_array as $keyval) { $keyval = explode('=', $keyval); if (count($keyval) == 2) { // Since we do not want the plus signs in the date and email strings to be encoded to a space, we use rawurldecode instead of urldecode - if (($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) || strpos(rawurldecode($keyval[1]), ' ') !== false || ($_POST["test_ipn"] == 1 && filter_var($keyval[1], FILTER_VALIDATE_EMAIL))) { + if ( + // If a single plus sign is found in date, then do not replace plus signs with spaces + ($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) + // If a space is found that was not encoded using a plus sign, then do not replace plus signs with spaces + || strpos(rawurldecode($keyval[1]), ' ') !== false + // If an un-encoded email address is found when receiving data from the sandbox, then do not replace plus signs with spaces + || ($_POST["test_ipn"] == 1 && filter_var($keyval[1], FILTER_VALIDATE_EMAIL)) + ) { // Keep plus signs $myPost[$keyval[0]] = rawurldecode($keyval[1]); } else { // Convert plus signs to spaces $myPost[$keyval[0]] = urldecode($keyval[1]); - if ($magic_quotes_enabled) { - $myPost[$keyval[0]] = stripslashes($myPost[$keyval[0]]); - } } } } @@ -121,7 +125,7 @@ public function verifyIPN() curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close')); $res = curl_exec($ch); - if ( ! ($res)) { + if ( ! ($res) ) { $errno = curl_errno($ch); $errstr = curl_error($ch); curl_close($ch); @@ -140,6 +144,6 @@ public function verifyIPN() if ($res == self::VALID) { return $myPost; } - return false; + return null; } } From 3c5da673033b8e47e64fbe6d89ea85f5a6212593 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Wed, 10 Jan 2018 13:16:02 -0500 Subject: [PATCH 12/14] Update PaypalIPN.php --- php/PaypalIPN.php | 1 - 1 file changed, 1 deletion(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 10d39ef..08d3fd7 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -78,7 +78,6 @@ public function verifyIPN() $raw_post_data = file_get_contents('php://input'); $raw_post_array = explode('&', $raw_post_data); $myPost = array(); - $magic_quotes_enabled = false; foreach ($raw_post_array as $keyval) { $keyval = explode('=', $keyval); if (count($keyval) == 2) { From ebe5ed10126818c2df8db7b874b3eb6899b06d30 Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Wed, 10 Jan 2018 14:01:55 -0500 Subject: [PATCH 13/14] Update PaypalIPN.php --- php/PaypalIPN.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 08d3fd7..4e449b8 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -83,11 +83,11 @@ public function verifyIPN() if (count($keyval) == 2) { // Since we do not want the plus signs in the date and email strings to be encoded to a space, we use rawurldecode instead of urldecode if ( - // If a single plus sign is found in date, then do not replace plus signs with spaces + // If a single plus sign is found in date... ($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) - // If a space is found that was not encoded using a plus sign, then do not replace plus signs with spaces + // If a space is found that was not encoded using a plus sign... || strpos(rawurldecode($keyval[1]), ' ') !== false - // If an un-encoded email address is found when receiving data from the sandbox, then do not replace plus signs with spaces + // If an un-encoded email address is found when receiving data from the sandbox... || ($_POST["test_ipn"] == 1 && filter_var($keyval[1], FILTER_VALIDATE_EMAIL)) ) { // Keep plus signs From b9956db478cd4165070b5342363fb05dfb6d38bc Mon Sep 17 00:00:00 2001 From: BigRedBot Date: Wed, 10 Jan 2018 18:12:54 -0500 Subject: [PATCH 14/14] Update PaypalIPN.php --- php/PaypalIPN.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php/PaypalIPN.php b/php/PaypalIPN.php index 4e449b8..3091d45 100644 --- a/php/PaypalIPN.php +++ b/php/PaypalIPN.php @@ -83,11 +83,11 @@ public function verifyIPN() if (count($keyval) == 2) { // Since we do not want the plus signs in the date and email strings to be encoded to a space, we use rawurldecode instead of urldecode if ( - // If a single plus sign is found in date... + // single plus sign found in date ($keyval[0] === 'payment_date' && substr_count($keyval[1], '+') === 1) - // If a space is found that was not encoded using a plus sign... + // space found that was not encoded using a plus sign || strpos(rawurldecode($keyval[1]), ' ') !== false - // If an un-encoded email address is found when receiving data from the sandbox... + // un-encoded email address found when receiving data from the simulator || ($_POST["test_ipn"] == 1 && filter_var($keyval[1], FILTER_VALIDATE_EMAIL)) ) { // Keep plus signs