=== modified file 'payment/uc_paypal/uc_paypal.module'
--- payment/uc_paypal/uc_paypal.module	2008-11-10 20:17:14 +0000
+++ payment/uc_paypal/uc_paypal.module	2009-10-22 23:27:04 +0000
@@ -602,117 +602,107 @@
     $req .= '&'. $key .'='. $value;
   }
 
-  if (variable_get('uc_paypal_wpp_server', '') == 'https://api-3t.paypal.com/nvp') {
+  // Per the PayPal Sandbox User Guide, test_ipn signifies a SandBox request
+  if (isset($_POST['test_ipn']) && $_POST['test_ipn'] == "1") {
+    $host = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
+  }
+  else {
     $host = 'https://www.paypal.com/cgi-bin/webscr';
   }
-  else {
-    $host = variable_get('uc_paypal_wps_server', 'https://www.sandbox.paypal.com/cgi-bin/webscr');
-  }
-
-  $host = explode('/', substr($host, 8));
-
-  // Post back to PayPal to validate
-  $header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
-  $header .= 'Host: '. $host[0] ."\r\n";
-  $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
-  $header .= 'Content-Length: '. strlen($req) ."\r\n\r\n";
-
-  // Address a screw-up on PayPal's Sandbox that prevents normal validation.
-  if (strpos($host[0], 'sandbox') !== FALSE && function_exists('openssl_open')) {
-    $fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
-  }
-  else {
-    // The old "normal" way of validating an IPN.
-    $fp = fsockopen($host[0], 80, $errno, $errstr, 30);
-  }
-
-
-  if (!$fp) {
-    watchdog('uc_paypal', t('IPN failed with HTTP error.'), WATCHDOG_ERROR);
+
+  $response = drupal_http_request($host, array(), 'POST', $req);
+
+  // TODO: Change this to property_exists when we have a PHP requirement >= 5.1.
+  if (array_key_exists('error', $response)) {
+    watchdog('uc_paypal', t('IPN failed with HTTP error @error, code @code.', array('@error' => $response->error, '@code' => $response->code)), WATCHDOG_ERROR);
+    _uc_paypal_send_error_response();
     return;
   }
 
-  fputs($fp, $header . $req);
-  while (!feof($fp)) {
-    $res = fgets($fp, 1024);
-    if (strcmp ($res, 'VERIFIED') == 0) {
-      watchdog('uc_paypal', t('IPN transaction verified.'));
-
-      $duplicate = db_result(db_query("SELECT COUNT(*) FROM {uc_payment_paypal_ipn} WHERE txn_id = '%s' AND status != 'Pending'", $txn_id));
-      if ($duplicate > 0) {
-        if ($order->payment_method != 'credit') {
-          watchdog('uc_paypal', t('IPN transaction ID has been processed before.'), WATCHDOG_NOTICE);
-        }
-        fclose($fp);
-        return;
-      }
-
-      db_query("INSERT INTO {uc_payment_paypal_ipn} VALUES (%d, '%s', '%s', '%s', "
-              ."'%s', '%s', '%s', %d)", $order_id, $txn_id, $txn_type,
-              $payment_amount, $payment_status, $receiver_email, $payer_email,
-              time());
-
-      /*if (variable_get('uc_paypal_wps_email', '') != $receiver_email) {
-        watchdog('uc_paypal', t('IPN received for an e-mail that is not your primary e-mail: @email', array('@email' => $receiver_email)));
-      }*/
-
-      switch ($payment_status) {
-        case 'Canceled_Reversal':
-          uc_order_comment_save($order_id, 0, t('PayPal has cancelled the reversal and returned !amount !currency to your account.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)), 'admin');
-          break;
-
-        case 'Completed':
-          $comment = t('PayPal transaction ID: @txn_id', array('@txn_id' => $txn_id));
-          uc_payment_enter($order_id, 'paypal_wps', $payment_amount, $order->uid, NULL, $comment);
-          uc_cart_complete_sale($order);
-          uc_order_comment_save($order_id, 0, t('Payment of !amount !currency submitted through PayPal.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)), 'order', 'payment_received');
-          uc_order_comment_save($order_id, 0, t('PayPal IPN reported a payment of !amount !currency.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)));
-          break;
-
-        case 'Denied':
-          uc_order_comment_save($order_id, 0, t("You have denied the customer's payment."), 'admin');
-          break;
-
-        case 'Expired':
-          uc_order_comment_save($order_id, 0, t('The authorization has failed and cannot be captured.'), 'admin');
-          break;
-
-        case 'Failed':
-          uc_order_comment_save($order_id, 0, t("The customer's attempted payment from a bank account failed."), 'admin');
-          break;
-
-        case 'Pending':
-          uc_order_update_status($order_id, 'paypal_pending');
-          uc_order_comment_save($order_id, 0, t('Payment is pending at PayPal: @reason', array('@reason' => _uc_paypal_pending_message($_POST['pending_reason']))), 'admin');
-          break;
-
-        // You, the merchant, refunded the payment.
-        case 'Refunded':
-          $comment = t('PayPal transaction ID: @txn_id', array('@txn_id' => $txn_id));
-          uc_payment_enter($order_id, 'paypal_wps', $payment_amount, $order->uid, NULL, $comment);
-          break;
-
-        case 'Reversed':
-          watchdog('uc_paypal', t('PayPal has reversed a payment!'), WATCHDOG_ERROR);
-          uc_order_comment_save($order_id, 0, t('Payment has been reversed by PayPal: @reason', array('@reason' => _uc_paypal_reversal_message($_POST['reason_code']))), 'admin');
-          break;
-
-        case 'Processed':
-          uc_order_comment_save($order_id, 0, t('A payment has been accepted.'), 'admin');
-          break;
-
-        case 'Voided':
-          uc_order_comment_save($order_id, 0, t('The authorization has been voided.'), 'admin');
-          break;
-      }
-    }
-    elseif (strcmp($res, 'INVALID') == 0) {
-      watchdog('uc_paypal', t('IPN transaction failed verification.'), WATCHDOG_ERROR);
-      uc_order_comment_save($order_id, 0, t('An IPN transaction failed verification for this order.'), 'admin');
-    }
-  }
-
-  fclose ($fp);
+  if (strcmp($response->data, 'VERIFIED') == 0) {
+    watchdog('uc_paypal', t('IPN transaction verified.'));
+
+    $duplicate = db_result(db_query("SELECT COUNT(*) FROM {uc_payment_paypal_ipn} WHERE txn_id = '%s' AND status != 'Pending'", $txn_id));
+    if ($duplicate > 0) {
+      if ($order->payment_method != 'credit') {
+        watchdog('uc_paypal', t('IPN transaction ID has been processed before.'), WATCHDOG_NOTICE);
+      }
+      return;
+    }
+
+    db_query("INSERT INTO {uc_payment_paypal_ipn} VALUES (%d, '%s', '%s', '%s', "
+            ."'%s', '%s', '%s', %d)", $order_id, $txn_id, $txn_type,
+            $payment_amount, $payment_status, $receiver_email, $payer_email,
+            time());
+
+    /*if (variable_get('uc_paypal_wps_email', '') != $receiver_email) {
+      watchdog('uc_paypal', t('IPN received for an e-mail that is not your primary e-mail: @email', array('@email' => $receiver_email)));
+    }*/
+
+    switch ($payment_status) {
+      case 'Canceled_Reversal':
+        uc_order_comment_save($order_id, 0, t('PayPal has cancelled the reversal and returned !amount !currency to your account.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)), 'admin');
+        break;
+
+      case 'Completed':
+        $comment = t('PayPal transaction ID: @txn_id', array('@txn_id' => $txn_id));
+        uc_payment_enter($order_id, 'paypal_wps', $payment_amount, $order->uid, NULL, $comment);
+        uc_cart_complete_sale($order);
+        uc_order_comment_save($order_id, 0, t('Payment of !amount !currency submitted through PayPal.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)), 'order', 'payment_received');
+        uc_order_comment_save($order_id, 0, t('PayPal IPN reported a payment of !amount !currency.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)));
+        break;
+
+      case 'Denied':
+        uc_order_comment_save($order_id, 0, t("You have denied the customer's payment."), 'admin');
+        break;
+
+      case 'Expired':
+        uc_order_comment_save($order_id, 0, t('The authorization has failed and cannot be captured.'), 'admin');
+        break;
+
+      case 'Failed':
+        uc_order_comment_save($order_id, 0, t("The customer's attempted payment from a bank account failed."), 'admin');
+        break;
+
+      case 'Pending':
+        uc_order_update_status($order_id, 'paypal_pending');
+        uc_order_comment_save($order_id, 0, t('Payment is pending at PayPal: @reason', array('@reason' => _uc_paypal_pending_message($_POST['pending_reason']))), 'admin');
+        break;
+
+      // You, the merchant, refunded the payment.
+      case 'Refunded':
+        $comment = t('PayPal transaction ID: @txn_id', array('@txn_id' => $txn_id));
+        uc_payment_enter($order_id, 'paypal_wps', $payment_amount, $order->uid, NULL, $comment);
+        break;
+
+      case 'Reversed':
+        watchdog('uc_paypal', t('PayPal has reversed a payment!'), WATCHDOG_ERROR);
+        uc_order_comment_save($order_id, 0, t('Payment has been reversed by PayPal: @reason', array('@reason' => _uc_paypal_reversal_message($_POST['reason_code']))), 'admin');
+        break;
+
+      case 'Processed':
+        uc_order_comment_save($order_id, 0, t('A payment has been accepted.'), 'admin');
+        break;
+
+      case 'Voided':
+        uc_order_comment_save($order_id, 0, t('The authorization has been voided.'), 'admin');
+        break;
+      default :
+        uc_order_comment_save($order_id, 0, t('Unknown IPN payment status @status', array('@status' => $payment_status)), 'admin');
+        watchdog('uc_paypal', t('Unknown IPN payment status @status', array('@status' => $payment_status)), WATCHDOG_ERROR);
+        _uc_paypal_send_error_response();
+        break;
+    }
+  }
+  elseif (strcmp($response->data, 'INVALID') == 0) {
+    watchdog('uc_paypal', t('IPN transaction failed verification. '.print_r($response, true)), WATCHDOG_ERROR);
+    uc_order_comment_save($order_id, 0, t('An IPN transaction failed verification for this order.'), 'admin');
+    _uc_paypal_send_error_response();
+  }
+  else {
+    watchdog('uc_paypal', t('Unknown IPN verification response @res', array('@res' => $response->data)), WATCHDOG_ERROR);
+    _uc_paypal_send_error_response();
+  }
 }
 
 // Handles a complete Website Payments Standard sale.
@@ -1526,7 +1516,13 @@
   }
 }
 
+// Outputs the proper HTTP response for failed incoming PayPal requests.
+function _uc_paypal_send_error_response() {
+  drupal_set_header('HTTP/1.1 500 Internal Server Error');
+}
+
 // Returns an array of possible currency codes.
 function _uc_paypal_currency_array() {
   return drupal_map_assoc(array('AUD', 'CAD', 'CHF', 'CZK', 'DKK', 'EUR', 'GBP', 'HKD', 'HUF', 'JPY', 'NOK', 'NZD', 'PLN', 'SEK', 'SGD', 'USD'));
 }
+

