diff -x .svn -aruN 2.3.3.src/ext/modules/payment/paypal/standard_ipn.php 2.3.3.cp1.src/ext/modules/payment/paypal/standard_ipn.php
--- 2.3.3.src/ext/modules/payment/paypal/standard_ipn.php	2012-09-24 14:33:44.000000000 -0500
+++ 2.3.3.cp1.src/ext/modules/payment/paypal/standard_ipn.php	2013-04-02 16:01:50.000000000 -0500
@@ -5,7 +5,7 @@
   osCommerce, Open Source E-Commerce Solutions
   http://www.oscommerce.com
 
-  Copyright (c) 2010 osCommerce
+  Copyright (c) 2012 osCommerce
 
   Released under the GNU General Public License
 */
@@ -17,67 +17,45 @@
     exit;
   }
 
-  $parameters = 'cmd=_notify-validate';
-
-  reset($HTTP_POST_VARS);
-  while (list($key, $value) = each($HTTP_POST_VARS)) {
-    $parameters .= '&' . $key . '=' . urlencode(stripslashes($value));
+  if (!class_exists('httpClient')) {
+    include('includes/classes/http_client.php');
   }
 
-  if (MODULE_PAYMENT_PAYPAL_STANDARD_GATEWAY_SERVER == 'Live') {
-    $server = 'www.paypal.com';
-  } else {
-    $server = 'www.sandbox.paypal.com';
-  }
-
-  $fsocket = false;
-  $curl = false;
   $result = false;
 
-  if ( (PHP_VERSION >= 4.3) && ($fp = @fsockopen('ssl://' . $server, 443, $errno, $errstr, 30)) ) {
-    $fsocket = true;
-  } elseif (function_exists('curl_exec')) {
-    $curl = true;
-  } elseif ($fp = @fsockopen($server, 80, $errno, $errstr, 30)) {
-    $fsocket = true;
-  }
+  if ( ($HTTP_POST_VARS['receiver_email'] == MODULE_PAYMENT_PAYPAL_STANDARD_ID) || (defined('MODULE_PAYMENT_PAYPAL_STANDARD_PRIMARY_ID') && tep_not_null(MODULE_PAYMENT_PAYPAL_STANDARD_PRIMARY_ID) && ($HTTP_POST_VARS['receiver_email'] == MODULE_PAYMENT_PAYPAL_STANDARD_PRIMARY_ID)) ) {
+    if (MODULE_PAYMENT_PAYPAL_STANDARD_GATEWAY_SERVER == 'Live') {
+      $server = 'www.paypal.com';
+    } else {
+      $server = 'www.sandbox.paypal.com';
+    }
+
+    $parameters = 'cmd=_notify-validate';
+
+    foreach ($HTTP_POST_VARS as $key => $value) {
+      $parameters .= '&' . $key . '=' . urlencode(stripslashes($value));
+    }
 
-  if ($fsocket == true) {
-    $header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n" .
-              'Host: ' . $server . "\r\n" .
-              'Content-Type: application/x-www-form-urlencoded' . "\r\n" .
-              'Content-Length: ' . strlen($parameters) . "\r\n" .
-              'Connection: close' . "\r\n\r\n";
-
-    @fputs($fp, $header . $parameters);
-
-    $string = '';
-    while (!@feof($fp)) {
-      $res = @fgets($fp, 1024);
-      $string .= $res;
+    $http = new httpClient($server, 443);
 
-      if ( ($res == 'VERIFIED') || ($res == 'INVALID') ) {
-        $result = $res;
+    if (defined('MODULE_PAYMENT_PAYPAL_STANDARD_PROXY') && tep_not_null(MODULE_PAYMENT_PAYPAL_STANDARD_PROXY)) {
+      $proxy_server = MODULE_PAYMENT_PAYPAL_STANDARD_PROXY;
+      $proxy_port = null;
 
-        break;
+      if (strpos(MODULE_PAYMENT_PAYPAL_STANDARD_PROXY, ':') !== false) {
+        list($proxy_server, $proxy_port) = explode(':', MODULE_PAYMENT_PAYPAL_STANDARD_PROXY, 2);
       }
-    }
 
-    @fclose($fp);
-  } elseif ($curl == true) {
-    $ch = curl_init();
-
-    curl_setopt($ch, CURLOPT_URL, 'https://' . $server . '/cgi-bin/webscr');
-    curl_setopt($ch, CURLOPT_POST, true);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-    curl_setopt($ch, CURLOPT_HEADER, false);
-    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
-    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+      $http->setProxy($proxy_server, $proxy_port);
+    }
 
-    $result = curl_exec($ch);
+    if (file_exists(DIR_FS_CACHE . $server . '.crt')) {
+      $http->addParameter('cafile', DIR_FS_CACHE . $server . '.crt');
+    }
 
-    curl_close($ch);
+    if ($http->post('/cgi-bin/webscr', $parameters) == 200) {
+      $result = $http->getBody();
+    }
   }
 
   if ($result == 'VERIFIED') {
@@ -86,17 +64,18 @@
       if (tep_db_num_rows($order_query) > 0) {
         $order = tep_db_fetch_array($order_query);
 
+        $new_order_status = DEFAULT_ORDERS_STATUS_ID;
+
         if ($order['orders_status'] == MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID) {
           $sql_data_array = array('orders_id' => $HTTP_POST_VARS['invoice'],
                                   'orders_status_id' => MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID,
                                   'date_added' => 'now()',
                                   'customer_notified' => '0',
-                                  'comments' => '');
+                                  'comments' => 'PayPal IPN Verified');
 
           tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
-
-
-          tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . (MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID > 0 ? (int)MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID : (int)DEFAULT_ORDERS_STATUS_ID) . "', last_modified = now() where orders_id = '" . (int)$HTTP_POST_VARS['invoice'] . "'");
+        } else {
+          $new_order_status = $order['orders_status'];
         }
 
         $total_query = tep_db_query("select value from " . TABLE_ORDERS_TOTAL . " where orders_id = '" . $HTTP_POST_VARS['invoice'] . "' and class = 'ot_total' limit 1");
@@ -112,10 +91,14 @@
 
         if ($HTTP_POST_VARS['mc_gross'] != number_format($total['value'] * $order['currency_value'], $currencies->get_decimal_places($order['currency']))) {
           $comment_status .= '; PayPal transaction value (' . tep_output_string_protected($HTTP_POST_VARS['mc_gross']) . ') does not match order value (' . number_format($total['value'] * $order['currency_value'], $currencies->get_decimal_places($order['currency'])) . ')';
+        } elseif ($HTTP_POST_VARS['payment_status'] == 'Completed') {
+          $new_order_status = (MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID > 0 ? MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID : $new_order_status);
         }
 
+        tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . (int)$new_order_status . "', last_modified = now() where orders_id = '" . (int)$HTTP_POST_VARS['invoice'] . "'");
+
         $sql_data_array = array('orders_id' => $HTTP_POST_VARS['invoice'],
-                                'orders_status_id' => (MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID > 0 ? (int)MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID : (int)DEFAULT_ORDERS_STATUS_ID),
+                                'orders_status_id' => (int)$new_order_status,
                                 'date_added' => 'now()',
                                 'customer_notified' => '0',
                                 'comments' => 'PayPal IPN Verified [' . $comment_status . ']');
diff -x .svn -aruN 2.3.3.src/.htaccess 2.3.3.cp1.src/.htaccess
--- 2.3.3.src/.htaccess	1969-12-31 18:00:00.000000000 -0600
+++ 2.3.3.cp1.src/.htaccess	2013-04-02 16:01:50.000000000 -0500
@@ -0,0 +1,38 @@
+# $Id$
+#
+# This is used with Apache WebServers
+#
+# For this to work, you must include the parameter 'Options' to
+# the AllowOverride configuration
+#
+# Example:
+#
+# <Directory "/usr/local/apache/htdocs">
+#   AllowOverride Options
+# </Directory>
+#
+# 'All' with also work. (This configuration is in the
+# apache/conf/httpd.conf file)
+
+# The following makes adjustments to the SSL protocol for Internet
+# Explorer browsers
+
+#<IfModule mod_setenvif.c>
+#  <IfDefine SSL>
+#    SetEnvIf User-Agent ".*MSIE.*" \
+#             nokeepalive ssl-unclean-shutdown \
+#             downgrade-1.0 force-response-1.0
+#  </IfDefine>
+#</IfModule>
+
+# If Search Engine Friendly URLs do not work, try enabling the
+# following Apache configuration parameter
+
+# AcceptPathInfo On
+
+# Fix certain PHP values
+# (commented out by default to prevent errors occuring on certain
+# servers)
+
+# php_value session.use_trans_sid 0
+# php_value register_globals 1
diff -x .svn -aruN 2.3.3.src/includes/classes/http_client/curl.php 2.3.3.cp1.src/includes/classes/http_client/curl.php
--- 2.3.3.src/includes/classes/http_client/curl.php	1969-12-31 18:00:00.000000000 -0600
+++ 2.3.3.cp1.src/includes/classes/http_client/curl.php	2013-04-02 16:01:50.000000000 -0500
@@ -0,0 +1,150 @@
+<?php
+/*
+  $Id$
+
+  osCommerce, Open Source E-Commerce Solutions
+  http://www.oscommerce.com
+
+  Copyright (c) 2012 osCommerce
+
+  Released under the GNU General Public License
+*/
+
+  class httpClient_curl {
+    function execute($parameters) {
+      $curl = curl_init($parameters['server']['scheme'] . '://' . $parameters['server']['host'] . $parameters['server']['path'] . (isset($parameters['server']['query']) ? '?' . $parameters['server']['query'] : ''));
+
+      $curl_options = array(CURLOPT_PORT => $parameters['server']['port'],
+                            CURLOPT_HEADER => true,
+                            CURLOPT_SSL_VERIFYPEER => true,
+                            CURLOPT_SSL_VERIFYHOST => 2,
+                            CURLOPT_RETURNTRANSFER => true,
+                            CURLOPT_FORBID_REUSE => true,
+                            CURLOPT_FRESH_CONNECT => true,
+                            CURLOPT_FOLLOWLOCATION => false); // does not work with open_basedir so a workaround is implemented below
+
+      if ( isset($parameters['header']) && !empty($parameters['header']) ) {
+        $curl_options[CURLOPT_HTTPHEADER] = $parameters['header'];
+      }
+
+      if ( isset($parameters['version']) && !empty($parameters['version']) ) {
+        switch ($parameters['version']) {
+          case '1.0':
+            $curl_options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
+            break;
+
+          case '1.1':
+            $curl_options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
+            break;
+        }
+      }
+
+      if ( isset($parameters['proxy']) && !empty($parameters['proxy']) ) {
+        $curl_options[CURLOPT_HTTPPROXYTUNNEL] = true;
+        $curl_options[CURLOPT_PROXY] = $parameters['proxy'];
+      }
+
+      if ( isset($parameters['cafile']) && !empty($parameters['cafile']) && file_exists($parameters['cafile']) ) {
+        $curl_options[CURLOPT_CAINFO] = $parameters['cafile'];
+      }
+
+      if ( isset($parameters['certificate']) && !empty($parameters['certificate']) ) {
+        $curl_options[CURLOPT_SSLCERT] = $parameters['certificate'];
+      }
+
+      if ( $parameters['method'] == 'post' ) {
+        $curl_options[CURLOPT_POST] = true;
+        $curl_options[CURLOPT_POSTFIELDS] = $parameters['parameters'];
+      } elseif ( $parameters['method'] == 'put' ) {
+        $curl_options[CURLOPT_PUT] = true;
+
+        $file_handle = tmpfile();
+        $file_size = fwrite($file_handle, $parameters['parameters']);
+        rewind($file_handle);
+
+        $curl_options[CURLOPT_INFILE] = $file_handle;
+        $curl_options[CURLOPT_INFILESIZE] = $file_size;
+      }
+
+      curl_setopt_array($curl, $curl_options);
+      $result = curl_exec($curl);
+
+      if ( $result === false ) {
+        trigger_error(curl_error($curl));
+
+        curl_close($curl);
+
+        if ( ($parameters['method'] == 'put') && is_resource($file_handle) ) {
+          fclose($file_handle);
+        }
+
+        return false;
+      }
+
+      $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+
+      curl_close($curl);
+
+      if ( ($parameters['method'] == 'put') && is_resource($file_handle) ) {
+        fclose($file_handle);
+      }
+
+      list($headers, $body) = explode("\r\n\r\n", $result, 2);
+
+      $response = array('code' => $http_code,
+                        'headers' => $headers,
+                        'body' => $body);
+
+      if ( ($http_code == 301) || ($http_code == 302) ) {
+        if ( !isset($parameters['redir_counter']) || ($parameters['redir_counter'] < 6) ) {
+          if ( !isset($parameters['redir_counter']) ) {
+            $parameters['redir_counter'] = 0;
+          }
+
+          $matches = array();
+          preg_match('/(Location:|URI:)(.*?)\n/i', $headers, $matches);
+
+          $redir_url = trim(array_pop($matches));
+
+          $parameters['redir_counter']++;
+
+          $redir_params = array('url' => $redir_url,
+                                'method' => $parameters['method'],
+                                'redir_counter', $parameters['redir_counter'],
+                                'header' => array(),
+                                'parameters' => '',
+                                'server' => parse_url($redir_url));
+
+          if ( !isset($redir_params['server']['port']) ) {
+            $redir_params['server']['port'] = ($redir_params['server']['scheme'] == 'https') ? 443 : 80;
+          }
+
+          if ( !isset($redir_params['server']['path']) ) {
+            $redir_params['server']['path'] = '/';
+          }
+
+          $h = new httpClient_curl();
+          $response = $h->execute($redir_params);
+        }
+      }
+
+      return $response;
+    }
+
+    function can_use($with_ssl = false) {
+      return function_exists('curl_init') && (($with_ssl === false) || defined('CURL_VERSION_SSL'));
+    }
+  }
+
+  if (!function_exists('curl_setopt_array')) {
+    function curl_setopt_array(&$ch, $curl_options) {
+      foreach ($curl_options as $option => $value) {
+        if (!curl_setopt($ch, $option, $value)) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+  }
+?>
diff -x .svn -aruN 2.3.3.src/includes/classes/http_client/http_request.php 2.3.3.cp1.src/includes/classes/http_client/http_request.php
--- 2.3.3.src/includes/classes/http_client/http_request.php	1969-12-31 18:00:00.000000000 -0600
+++ 2.3.3.cp1.src/includes/classes/http_client/http_request.php	2013-04-02 16:01:50.000000000 -0500
@@ -0,0 +1,89 @@
+<?php
+/*
+  $Id$
+
+  osCommerce, Open Source E-Commerce Solutions
+  http://www.oscommerce.com
+
+  Copyright (c) 2012 osCommerce
+
+  Released under the GNU General Public License
+*/
+
+  class httpClient_http_request {
+    function execute($parameters) {
+      $_methods = array('get' => HTTP_METH_GET,
+                        'post' => HTTP_METH_POST,
+                        'put' => HTTP_METH_PUT);
+
+      $h = new HttpRequest($parameters['server']['scheme'] . '://' . $parameters['server']['host'] . $parameters['server']['path'] . (isset($parameters['server']['query']) ? '?' . $parameters['server']['query'] : ''), $_methods[$parameters['method']], array('redirect' => 5));
+
+      $h->setOptions(array('port' => $parameters['server']['port']));
+
+      if ( isset($parameters['version']) && !empty($parameters['version']) ) {
+        switch ($parameters['version']) {
+          case '1.0':
+            $h->setOptions(array('protocol' => HTTP_VERSION_1_0));
+            break;
+
+          case '1.1':
+            $h->setOptions(array('protocol' => HTTP_VERSION_1_1));
+            break;
+        }
+      }
+
+      if ( isset($parameters['proxy']) && !empty($parameters['proxy']) ) {
+        $h->setOptions(array('proxyhost' => $parameters['proxy']));
+      }
+
+      if ( $parameters['method'] == 'post' ) {
+        $post_params = array();
+
+        parse_str($parameters['parameters'], $post_params);
+
+        $h->setPostFields($post_params);
+      } elseif ( $parameters['method'] == 'put' ) {
+        $h->setPutData($parameters['parameters']);
+      }
+
+      if ( $parameters['server']['scheme'] === 'https' ) {
+        $h->addSslOptions(array('verifypeer' => true,
+                                'verifyhost' => true));
+
+        if ( isset($parameters['cafile']) && file_exists($parameters['cafile']) ) {
+          $h->addSslOptions(array('cainfo' => $parameters['cafile']));
+        }
+
+        if ( isset($parameters['certificate']) ) {
+          $h->addSslOptions(array('cert' => $parameters['certificate']));
+        }
+      }
+
+      $response = array();
+
+      try {
+        $h->send();
+
+        $result = $h->getResponseMessage()->toString();
+
+        list($headers, $body) = explode("\r\n\r\n", $result, 2);
+
+        $response = array('code' => $h->getResponseCode(),
+                          'headers' => $headers,
+                          'body' => $body);
+      } catch ( Exception $e ) {
+        if ( isset($e->innerException) ) {
+          trigger_error($e->innerException->getMessage());
+        } else {
+          trigger_error($e->getMessage());
+        }
+      }
+
+      return $response;
+    }
+
+    function can_use($with_ssl = false) {
+      return class_exists('HttpRequest') && (($with_ssl === false) || (defined('HTTP_SUPPORT_SSLREQUESTS') && function_exists('http_support') && http_support(HTTP_SUPPORT_SSLREQUESTS)));
+    }
+  }
+?>
diff -x .svn -aruN 2.3.3.src/includes/classes/http_client/socket.php 2.3.3.cp1.src/includes/classes/http_client/socket.php
--- 2.3.3.src/includes/classes/http_client/socket.php	1969-12-31 18:00:00.000000000 -0600
+++ 2.3.3.cp1.src/includes/classes/http_client/socket.php	2013-04-02 16:01:50.000000000 -0500
@@ -0,0 +1,141 @@
+<?php
+/*
+  $Id$
+
+  osCommerce, Open Source E-Commerce Solutions
+  http://www.oscommerce.com
+
+  Copyright (c) 2012 osCommerce
+
+  Released under the GNU General Public License
+*/
+
+  class httpClient_socket {
+    function execute($parameters) {
+      if ( isset($parameters['proxy']) && !empty($parameters['proxy']) ) {
+        list($proxy_server, $proxy_port) = explode(':', $parameters['proxy'], 2);
+
+        if (empty($proxy_port)) {
+          $proxy_port = '80';
+        }
+
+        $conn_server = $proxy_server;
+        $conn_port = $proxy_port;
+
+        $request_url = $parameters['server']['scheme'] . '://' . $parameters['server']['host'] . (isset($parameters['server']['port']) ? ':' . $parameters['server']['port'] : '') . $parameters['server']['path'] . (isset($parameters['server']['query']) ? '?' . $parameters['server']['query'] : '');
+      } else {
+        $conn_server = ($parameters['server']['scheme'] == 'https' ? 'ssl://' : '') . $parameters['server']['host'];
+        $conn_port = $parameters['server']['port'];
+
+        $request_url = $parameters['server']['path'] . (isset($parameters['server']['query']) ? '?' . $parameters['server']['query'] : '');
+      }
+
+      $protocol_version = ( isset($parameters['version']) && !empty($parameters['version']) ) ? $parameters['version'] : '1.1';
+
+      $command = strtoupper($parameters['method']) . ' ' . $request_url . ' HTTP/' . $protocol_version . "\r\n";
+
+      $add_host = true;
+      $add_connection = true;
+      $headers = '';
+
+      if (!empty($parameters['header'])) {
+        foreach ($parameters['header'] as $h) {
+          $headers .= $h . "\r\n";
+
+          if (strtolower(substr($h, 0, 5)) == 'host:') {
+            $add_host = false;
+          } elseif (strtolower(substr($h, 0, 11)) == 'Connection:') {
+            $add_connection = false;
+          }
+        }
+      }
+
+      if ($add_host === true) {
+        $command .= 'Host: ' . $parameters['server']['host'] . ':' . $parameters['server']['port'] . "\r\n";
+      }
+
+      if (isset($parameters['parameters'])) {
+        $command .= 'Content-Length: ' . strlen($parameters['parameters']) . "\r\n";
+      }
+
+      if ($parameters['method'] == 'post') {
+        $command .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
+      }
+
+      if ($add_connection === true) {
+        $command .= 'Connection: Close' . "\r\n";
+      }
+
+      $command .= $headers . "\r\n";
+
+      if (isset($parameters['parameters'])) {
+        $command .= $parameters['parameters'];
+      }
+
+      $agro = fsockopen($conn_server, $conn_port);
+
+      if ($agro === false) {
+        return false;
+      }
+
+      fwrite($agro, $command);
+
+      $result = '';
+
+      $counter = 0;
+
+      do {
+        $status = socket_get_status($agro);
+        if ($status['eof'] == 1) {
+          break;
+        }
+
+        if ($status['unread_bytes'] > 0) {
+          $buffer = fread($agro, $status['unread_bytes']);
+          $counter = 0;
+        } else {
+          $buffer = fread($agro, 128);
+          $counter++;
+          usleep(2);
+        }
+
+        $result .= $buffer;
+      } while ( ($status['unread_bytes'] > 0) || ($counter++ < 10) );
+
+      fclose($agro);
+
+      list($headers, $body) = explode("\r\n\r\n", $result, 2);
+
+      if (strpos(strtolower($headers), 'transfer-encoding: chunked') !== false) {
+        $body = http_chunked_decode($body);
+      }
+
+      $response = array('code' => null,
+                        'headers' => $headers,
+                        'body' => $body);
+
+      if (preg_match('|^HTTP/\S+ (\d+) |i', substr($headers, 0, strpos($headers, "\n")), $a )) {
+        $response['code'] = (int)$a[1];
+      }
+
+      return $response;
+    }
+
+    function can_use($with_ssl = false) {
+      return ($with_ssl === false) || extension_loaded('openssl');
+    }
+  }
+
+  if (!function_exists('http_chunked_decode')) {
+    function http_chunked_decode($str) {
+      for ($res = ''; !empty($str); $str = trim($str)) {
+        $pos = strpos($str, "\r\n");
+        $len = hexdec(substr($str, 0, $pos));
+        $res .= substr($str, $pos + 2, $len);
+        $str = substr($str, $pos + 2 + $len);
+      }
+
+      return $res;
+    }
+  }
+?>
diff -x .svn -aruN 2.3.3.src/includes/classes/http_client/stream.php 2.3.3.cp1.src/includes/classes/http_client/stream.php
--- 2.3.3.src/includes/classes/http_client/stream.php	1969-12-31 18:00:00.000000000 -0600
+++ 2.3.3.cp1.src/includes/classes/http_client/stream.php	2013-04-02 16:01:50.000000000 -0500
@@ -0,0 +1,123 @@
+<?php
+/*
+  $Id$
+
+  osCommerce, Open Source E-Commerce Solutions
+  http://www.oscommerce.com
+
+  Copyright (c) 2012 osCommerce
+
+  Released under the GNU General Public License
+*/
+
+  class httpClient_stream {
+    function execute($parameters) {
+      $http_response_header = array();
+
+      $url = $parameters['server']['scheme'] . '://' . $parameters['server']['host'] . (isset($parameters['server']['port']) ? ':' . $parameters['server']['port'] : '') . $parameters['server']['path'] . (isset($parameters['server']['query']) ? '?' . $parameters['server']['query'] : '');
+
+      $options = array('http' => array('method' => 'GET',
+                                       'protocol_version' => '1.1',
+                                       'request_fulluri' => true,
+                                       'follow_location' => true,
+                                       'max_redirects' => 5));
+
+      if (isset($parameters['parameters'])) {
+        $options['http']['content'] = $parameters['parameters'];
+      }
+
+      if ($parameters['method'] == 'post') {
+        $options['http']['method'] = 'POST';
+      } elseif ($parameters['method'] == 'put') {
+        $options['http']['method'] = 'PUT';
+      }
+
+      if ( (strlen($options['http']['content']) < 1) && ($options['http']['method'] == 'POST') ) {
+        $options['http']['method'] = 'GET';
+      }
+
+      if ( !isset($parameters['header']) ) {
+        $parameters['header'] = array();
+      }
+
+      if ($parameters['method'] == 'post') {
+        $parameters['header'][] = 'Content-Type: application/x-www-form-urlencoded';
+      }
+
+      if (isset($parameters['parameters'])) {
+        $parameters['header'][] = 'Content-Length: ' . strlen($parameters['parameters']);
+      }
+
+      $add_host = true;
+      $add_connection = true;
+
+      foreach ($parameters['header'] as $h) {
+        if (strtolower(substr($h, 0, 5)) == 'host:') {
+          $add_host = false;
+        } elseif (strtolower(substr($h, 0, 11)) == 'Connection:') {
+          $add_connection = false;
+        }
+      }
+
+      if ($add_host === true) {
+        $parameters['header'][] = 'Host: ' . $parameters['server']['host'] . ':' . $parameters['server']['port'];
+      }
+
+      if ($add_connection === true) {
+        $parameters['header'][] = 'Connection: Close';
+      }
+
+      $options['http']['header'] = implode("\r\n", $parameters['header']);
+
+      if ( isset($parameters['version']) && !empty($parameters['version']) ) {
+        switch ($parameters['version']) {
+          case '1.0':
+            $options['http']['protocol_version'] = '1.0';
+            break;
+
+          case '1.1':
+            $options['http']['protocol_version'] = '1.1';
+            break;
+        }
+      }
+
+      if ( isset($parameters['proxy']) && !empty($parameters['proxy']) ) {
+        $options['http']['proxy'] = $parameters['proxy'];
+      }
+
+      if ( $parameters['server']['scheme'] === 'https' ) {
+        $options['ssl'] = array('verify_peer' => true);
+
+        if ( isset($parameters['cafile']) && file_exists($parameters['cafile']) ) {
+          $options['ssl']['cafile'] = $parameters['cafile'];
+        }
+
+        if ( isset($parameters['certificate']) ) {
+          $options['ssl']['local_cert'] = $parameters['certificate'];
+        }
+      }
+
+      $context = stream_context_create($options);
+
+      $result = file_get_contents($url, false, $context);
+
+      if ($result === false) {
+        return false;
+      }
+
+      $response = array('code' => null,
+                        'headers' => implode("\n", $http_response_header), // $http_response_header is automatically set by PHP
+                        'body' => $result);
+
+      if (preg_match('|^HTTP/\S+ (\d+) |i', $http_response_header[0], $a )) {
+        $response['code'] = (int)$a[1];
+      }
+
+      return $response;
+    }
+
+    function can_use($with_ssl = false) {
+      return (PHP_VERSION >= 5) && ((bool)ini_get('allow_url_fopen') === true) && (($with_ssl === false) || extension_loaded('openssl'));
+    }
+  }
+?>
diff -x .svn -aruN 2.3.3.src/includes/classes/http_client.php 2.3.3.cp1.src/includes/classes/http_client.php
--- 2.3.3.src/includes/classes/http_client.php	2012-09-24 14:33:44.000000000 -0500
+++ 2.3.3.cp1.src/includes/classes/http_client.php	2013-04-02 16:01:50.000000000 -0500
@@ -5,455 +5,364 @@
   osCommerce, Open Source E-Commerce Solutions
   http://www.oscommerce.com
 
-  Copyright (c) 2002 osCommerce
+  Copyright (c) 2012 osCommerce
 
   Released under the GNU General Public License
+*/
 
-  Copyright 2001 Leo West <west_leo@yahoo-REMOVE-.com> Net_HTTP_Client v0.6
+  class httpClient {
+    var $drivers = array('curl', 'stream', 'socket');
+    var $driver;
+    var $url; // array containg scheme, host, port, user, pass, path, query, fragment (from parse_url())
+    var $proxyHost, $proxyPort;
+    var $protocolVersion;
+    var $requestHeaders, $requestBody;
+    var $reply; // response code
+    var $replyString; // full response
 
-  Minimal Example:
+    var $params = array();
+    var $response = array();
 
-  $http = new httpClient();
-  $http->Connect("somehost", 80) or die("Connect problem");
-  $status = $http->Get("/index.html");
-  if ($status != 200) {
-    die("Problem : " . $http->getStatusMessage());
-  } else {
-    echo $http->getBody();
-  }
-  $http->Disconnect();
+    function httpClient($host = null, $port = null) {
+      if (PHP_VERSION >= 5) {
+        array_unshift($this->drivers, 'http_request');
+      }
 
-  Persistent Example:
+      if (isset($host)) {
+        $this->connect($host, $port);
+      }
+    }
 
-  $http = new httpClient("dir.yahoo.com", 80);
-  $http->addHeader("Host", "dir.yahoo.com");
-  $http->addHeader("Connection", "keep-alive");
+    function connect($host, $port = null) {
+      $this->url = parse_url($host);
 
-  if ($http->Get("/Reference/Libraries/") == 200) $page1 = $http->getBody();
-  if ($http->Get("/News_and_Media/") == 200 ) $page2 = $http->getBody();
-  $http->disconnect();
-*/
+      if (!isset($this->url['scheme'])) {
+        $this->url['scheme'] = 'http';
+        $this->url['host'] = $this->url['path'];
+        unset($this->url['path']);
+      }
 
-  class httpClient {
-    var $url; // array containg server URL, similar to parseurl() returned array
-    var $reply; // response code
-    var $replyString; // full response
-    var $protocolVersion = '1.1';
-    var $requestHeaders, $requestBody;
-    var $socket = false;
-// proxy stuff
-    var $useProxy = false;
-    var $proxyHost, $proxyPort;
+      if (isset($port)) {
+        $this->url['port'] = $port;
 
-/**
- * httpClient constructor
- * Note: when host and port are defined, the connection is immediate
- * @seeAlso connect
- **/
-    function httpClient($host = '', $port = '') {
-      if (tep_not_null($host)) {
-        $this->connect($host, $port);
+        if (($port == '443') && ($this->url['scheme'] != 'https')) {
+          $this->url['scheme'] = 'https';
+        }
+      } elseif ($this->url['scheme'] == 'http') {
+        $this->url['port'] = '80';
+      } elseif ($this->url['scheme'] == 'https') {
+        $this->url['port'] = '443';
       }
+
+      return true;
     }
 
-/**
- * turn on proxy support
- * @param proxyHost proxy host address eg "proxy.mycorp.com"
- * @param proxyPort proxy port usually 80 or 8080
- **/
     function setProxy($proxyHost, $proxyPort) {
-      $this->useProxy = true;
       $this->proxyHost = $proxyHost;
       $this->proxyPort = $proxyPort;
     }
 
-/**
- * setProtocolVersion
- * define the HTTP protocol version to use
- * @param version string the version number with one decimal: "0.9", "1.0", "1.1"
- * when using 1.1, you MUST set the mandatory headers "Host"
- * @return boolean false if the version number is bad, true if ok
- **/
-    function setProtocolVersion($version) {
-      if ( ($version > 0) && ($version <= 1.1) ) {
-        $this->protocolVersion = $version;
-        return true;
+    function makeUri($uri) {
+      $a = parse_url($uri);
+
+      if ( (isset($a['scheme'])) && (isset($a['host'])) ) {
+        $this->url = $a;
       } else {
-        return false;
+        unset($this->url['query']);
+        unset($this->url['fragment']);
+        $this->url = array_merge($this->url, $a);
       }
+
+      if (isset($this->proxyHost)) {
+        $requesturi = 'http://' . $this->url['host'] . (empty($this->url['port']) ? '' : ':' . $this->url['port']) . $this->url['path'] . (empty($this->url['query']) ? '' : '?' . $this->url['query']);
+      } else {
+        $requesturi = $this->url['path'] . (empty($this->url['query']) ? '' : '?' . $this->url['query']);
+      }
+
+      return $requesturi;
     }
 
-/**
- * set a username and password to access a protected resource
- * Only "Basic" authentication scheme is supported yet
- * @param username string - identifier
- * @param password string - clear password
- **/
-    function setCredentials($username, $password) {
-      $this->addHeader('Authorization', 'Basic ' . base64_encode($username . ':' . $password));
-     }
+    function processReply() {
+      $this->replyString = trim(substr($this->response['headers'], 0, strpos($this->response['headers'], "\n")));
 
-/**
- * define a set of HTTP headers to be sent to the server
- * header names are lowercased to avoid duplicated headers
- * @param headers hash array containing the headers as headerName => headerValue pairs
- **/
-    function setHeaders($headers) {
-      if (is_array($headers)) {
-        reset($headers);
-        while (list($name, $value) = each($headers)) {
-          $this->requestHeaders[$name] = $value;
-        }
+      if (preg_match('|^HTTP/\S+ (\d+) |i', $this->replyString, $a )) {
+        $this->reply = $a[1];
+      } else {
+        $this->reply = 'Bad Response';
       }
-    }
 
-/**
- * addHeader
- * set a unique request header
- * @param headerName the header name
- * @param headerValue the header value, ( unencoded)
- **/
-    function addHeader($headerName, $headerValue) {
-      $this->requestHeaders[$headerName] = $headerValue;
-    }
+//get response headers and body
+      $this->responseHeaders = $this->processHeader();
+      $this->responseBody = $this->processBody();
 
-/**
- * removeHeader
- * unset a request header
- * @param headerName the header name
- **/
-    function removeHeader($headerName) {
-      unset($this->requestHeaders[$headerName]);
+      return $this->reply;
     }
 
-/**
- * Connect
- * open the connection to the server
- * @param host string server address (or IP)
- * @param port string server listening port - defaults to 80
- * @return boolean false is connection failed, true otherwise
- **/
-    function Connect($host, $port = '') {
-      $this->url['scheme'] = 'http';
-      $this->url['host'] = $host;
-      if (tep_not_null($port)) $this->url['port'] = $port;
+    function setDriver($driver = null) {
+      if (empty($driver)) {
+        foreach ($this->drivers as $d) {
+          if (file_exists(DIR_FS_CATALOG . 'includes/classes/http_client/' . $d . '.php')) {
+            if (!class_exists('httpClient_' . $d)) {
+              include(DIR_FS_CATALOG . 'includes/classes/http_client/' . $d . '.php');
+            }
+
+            $class_name = 'httpClient_' . $d;
+            $ecce_homo_fresco = new $class_name();
+
+            if ($ecce_homo_fresco->can_use(($this->url['scheme'] == 'https')) === true) {
+              $this->driver = $ecce_homo_fresco;
+              break;
+            }
+          }
+        }
+      } else {
+        $driver = basename($driver);
 
-      return true;
+        if (in_array($driver, $this->drivers) && file_exists(DIR_FS_CATALOG . 'includes/classes/http_client/' . $driver . '.php')) {
+          if (!class_exists('httpClient_' . $driver)) {
+            include(DIR_FS_CATALOG . 'includes/classes/http_client/' . $driver . '.php');
+          }
+
+          $class_name = 'httpClient_' . $driver;
+          $ecce_homo_fresco = new $class_name();
+
+          if ($ecce_homo_fresco->can_use(($this->url['scheme'] == 'https')) === true) {
+            $this->driver = $ecce_homo_fresco;
+          } else {
+            trigger_error('httpClient() cannot use manually set "' . $driver . '"');
+          }
+        } else {
+          trigger_error('httpClient() manually set "' . $driver . '" driver does not exist');
+        }
+      }
     }
 
-/**
- * Disconnect
- * close the connection to the  server
- **/
-    function Disconnect() {
-      if ($this->socket) fclose($this->socket);
-    }
-
-/**
- * head
- * issue a HEAD request
- * @param uri string URI of the document
- * @return string response status code (200 if ok)
- * @seeAlso getHeaders()
- **/
-    function Head($uri) {
-      $this->responseHeaders = $this->responseBody = '';
+    function get($url) {
+      if (!isset($this->driver)) {
+        $this->setDriver();
+      }
 
-      $uri = $this->makeUri($uri);
+      $uri = $this->makeUri($url);
 
-      if ($this->sendCommand('HEAD ' . $uri . ' HTTP/' . $this->protocolVersion)) {
-        $this->processReply();
+      $this->params['server'] = $this->url;
+      $this->params['method'] = 'get';
+      $this->params['header'] = array();
+      $this->params['version'] = $this->protocolVersion;
+
+      if (isset($this->proxyHost)) {
+        $this->params['proxy'] = $this->proxyHost . (!empty($this->proxyPort) ? ':' . $this->proxyPort : '');
       }
 
-      return $this->reply;
-    }
+      if (isset($this->requestHeaders) && is_array($this->requestHeaders)) {
+        foreach ($this->requestHeaders as $k => $v) {
+          $this->params['header'][] = $k . ': ' . $v;
+        }
+      }
 
-/**
- * get
- * issue a GET http request
- * @param uri URI (path on server) or full URL of the document
- * @return string response status code (200 if ok)
- * @seeAlso getHeaders(), getBody()
- **/
-    function Get($url) {
       $this->responseHeaders = $this->responseBody = '';
 
-      $uri = $this->makeUri($url);
+      $this->response = $this->driver->execute($this->params);
 
-      if ($this->sendCommand('GET ' . $uri . ' HTTP/' . $this->protocolVersion)) {
+      if (is_array($this->response) && isset($this->response['code'])) {
         $this->processReply();
       }
 
       return $this->reply;
     }
 
-/**
- * Post
- * issue a POST http request
- * @param uri string URI of the document
- * @param query_params array parameters to send in the form "parameter name" => value
- * @return string response status code (200 if ok)
- * @example 
- * $params = array( "login" => "tiger", "password" => "secret" );
- * $http->post( "/login.php", $params );
- **/
-    function Post($uri, $query_params = '') {
+    function post($uri, $query_params = null) {
+      if (!isset($this->driver)) {
+        $this->setDriver();
+      }
+
       $uri = $this->makeUri($uri);
 
-      if (is_array($query_params)) {
-        $postArray = array();
-        reset($query_params);
-        while (list($k, $v) = each($query_params)) {
-          $postArray[] = urlencode($k) . '=' . urlencode($v);
+      if (isset($query_params)) {
+        if (is_array($query_params)) {
+          $postArray = array();
+          foreach ($query_params as $k => $v) {
+            $postArray[] = urlencode($k) . '=' . urlencode($v);
+          }
+
+          $this->requestBody = implode('&', $postArray);
+        } else {
+          $this->requestBody = $query_params;
         }
+      }
 
-        $this->requestBody = implode('&', $postArray);
+      $this->params['server'] = $this->url;
+      $this->params['method'] = 'post';
+      $this->params['header'] = array();
+      $this->params['version'] = $this->protocolVersion;
+      $this->params['parameters'] = '';
+
+      if (isset($this->proxyHost)) {
+        $this->params['proxy'] = $this->proxyHost . (!empty($this->proxyPort) ? ':' . $this->proxyPort : '');
       }
 
-// set the content type for post parameters
-      $this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
+      if (!empty($this->requestBody)) {
+        $this->params['parameters'] = $this->requestBody;
+      }
 
-      if ($this->sendCommand('POST ' . $uri . ' HTTP/' . $this->protocolVersion)) {
-        $this->processReply();
+      if (isset($this->requestHeaders) && is_array($this->requestHeaders)) {
+        foreach ($this->requestHeaders as $k => $v) {
+          $this->params['header'][] = $k . ': ' . $v;
+        }
       }
 
-      $this->removeHeader('Content-Type');
-      $this->removeHeader('Content-Length');
-      $this->requestBody = '';
+      $this->responseHeaders = $this->responseBody = '';
+
+      $this->response = $this->driver->execute($this->params);
+
+      if (is_array($this->response) && isset($this->response['code'])) {
+        $this->processReply();
+      }
 
       return $this->reply;
     }
 
-/**
- * Put
- * Send a PUT request
- * PUT is the method to sending a file on the server. it is *not* widely supported
- * @param uri the location of the file on the server. dont forget the heading "/"
- * @param filecontent the content of the file. binary content accepted
- * @return string response status code 201 (Created) if ok
- * @see RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV"
- **/
-    function Put($uri, $filecontent) {
-      $uri = $this->makeUri($uri);
-      $this->requestBody = $filecontent;
+    function head($uri) {
+      return $this->get($uri);
+    }
 
-      if ($this->sendCommand('PUT ' . $uri . ' HTTP/' . $this->protocolVersion)) {
-        $this->processReply();
+    function processHeader() {
+      $headers = array();
+
+      foreach (explode("\n", $this->response['headers']) as $h) {
+        list($hdr, $value) = explode(': ', $h, 2);
+// nasty workaround broken multiple same headers (eg. Set-Cookie headers)
+        if (isset($headers[$hdr])) {
+          $headers[$hdr] .= '; ' . trim($value);
+        } else {
+          $headers[$hdr] = trim($value);
+        }
       }
 
-      return $this->reply;
+      return $headers;
+    }
+
+    function processBody() {
+      return trim($this->response['body']);
     }
 
-/**
- * getHeaders
- * return the response headers
- * to be called after a Get() or Head() call
- * @return array headers received from server in the form headername => value
- * @seeAlso get, head
- **/
     function getHeaders() {
       return $this->responseHeaders;
     }
 
-/**
- * getHeader
- * return the response header "headername"
- * @param headername the name of the header
- * @return header value or NULL if no such header is defined
- **/
     function getHeader($headername) {
       return $this->responseHeaders[$headername];
     }
 
-/**
- * getBody
- * return the response body
- * invoke it after a Get() call for instance, to retrieve the response
- * @return string body content
- * @seeAlso get, head
- **/
     function getBody() {
       return $this->responseBody;
     }
 
-/**
- * getStatus return the server response's status code
- * @return string a status code
- * code are divided in classes (where x is a digit)
- *  - 20x : request processed OK
- *  - 30x : document moved
- *  - 40x : client error ( bad url, document not found, etc...)
- *  - 50x : server error 
- * @see RFC2616 "Hypertext Transfer Protocol -- HTTP/1.1"
- **/
     function getStatus() {
       return $this->reply;
     }
 
-/** 
- * getStatusMessage return the full response status, of the form "CODE Message"
- * eg. "404 Document not found"
- * @return string the message 
- **/
     function getStatusMessage() {
       return $this->replyString;
     }
 
-/**
- * @scope only protected or private methods below
- **/
-
-/** 
- * send a request
- * data sent are in order
- * a) the command
- * b) the request headers if they are defined
- * c) the request body if defined
- * @return string the server repsonse status code
- **/
-    function sendCommand($command) {
-      $this->responseHeaders = array();
-      $this->responseBody = '';
-
-// connect if necessary
-      if ( ($this->socket == false) || (feof($this->socket)) ) {
-        if ($this->useProxy) {
-          $host = $this->proxyHost;
-          $port = $this->proxyPort;
-        } else {
-          $host = $this->url['host'];
-          $port = $this->url['port'];
-        }
-
-        if (!tep_not_null($port)) $port = 80;
-
-        if (!$this->socket = fsockopen($host, $port, $this->reply, $this->replyString)) {
-          return false;
-        }
-
-        if (tep_not_null($this->requestBody)) {
-          $this->addHeader('Content-Length', strlen($this->requestBody));
-        }
+    function setCredentials($username, $password) {
+      $this->addHeader('Authorization', 'Basic ' . base64_encode($username . ':' . $password));
+    }
 
-        $this->request = $command;
-        $cmd = $command . "\r\n";
-        if (is_array($this->requestHeaders)) {
-          reset($this->requestHeaders);
-          while (list($k, $v) = each($this->requestHeaders)) {
-            $cmd .= $k . ': ' . $v . "\r\n";
-          }
+    function setHeaders($headers) {
+      if (is_array($headers)) {
+        foreach ($headers as $name => $value) {
+          $this->requestHeaders[$name] = $value;
         }
+      }
+    }
 
-        if (tep_not_null($this->requestBody)) {
-          $cmd .= "\r\n" . $this->requestBody;
-        }
+    function addHeader($headerName, $headerValue) {
+      $this->requestHeaders[$headerName] = $headerValue;
+    }
 
-// unset body (in case of successive requests)
-        $this->requestBody = '';
+    function removeHeader($headerName) {
+      if (isset($this->requestHeaders[$headerName])) {
+        unset($this->requestHeaders[$headerName]);
+      }
+    }
 
-        fputs($this->socket, $cmd . "\r\n");
+    function setProtocolVersion($version) {
+      $this->protocolVersion = $version;
+    }
 
-        return true;
+    function put($uri, $filecontent) {
+      if (!isset($this->driver)) {
+        $this->setDriver();
       }
-    }
 
-    function processReply() {
-      $this->replyString = trim(fgets($this->socket, 1024));
+      $uri = $this->makeUri($uri);
 
-      if (preg_match('|^HTTP/\S+ (\d+) |i', $this->replyString, $a )) {
-        $this->reply = $a[1];
-      } else {
-        $this->reply = 'Bad Response';
+      $this->params['server'] = $this->url;
+      $this->params['method'] = 'put';
+      $this->params['header'] = array();
+      $this->params['version'] = $this->protocolVersion;
+      $this->params['parameters'] = $filecontent;
+
+      if (isset($this->proxyHost)) {
+        $this->params['proxy'] = $this->proxyHost . (!empty($this->proxyPort) ? ':' . $this->proxyPort : '');
       }
 
-//get response headers and body
-      $this->responseHeaders = $this->processHeader();
-      $this->responseBody = $this->processBody();
+      if (isset($this->requestHeaders) && is_array($this->requestHeaders)) {
+        foreach ($this->requestHeaders as $k => $v) {
+          $this->params['header'][] = $k . ': ' . $v;
+        }
+      }
 
-      return $this->reply;
-    }
+      $this->responseHeaders = $this->responseBody = '';
 
-/**
- * processHeader() reads header lines from socket until the line equals $lastLine
- * @scope protected
- * @return array of headers with header names as keys and header content as values
- **/
-    function processHeader($lastLine = "\r\n") {
-      $headers = array();
-      $finished = false;
+      $this->response = $this->driver->execute($this->params);
 
-      while ( (!$finished) && (!feof($this->socket)) ) {
-        $str = fgets($this->socket, 1024);
-        $finished = ($str == $lastLine);
-        if (!$finished) {
-          list($hdr, $value) = explode(': ', $str, 2);
-// nasty workaround broken multiple same headers (eg. Set-Cookie headers) @FIXME 
-          if (isset($headers[$hdr])) {
-            $headers[$hdr] .= '; ' . trim($value);
-          } else {
-            $headers[$hdr] = trim($value);
-          }
-        }
+      if (is_array($this->response) && isset($this->response['code'])) {
+        $this->processReply();
       }
 
-      return $headers;
+      return $this->reply;
     }
 
-/**
- * processBody() reads the body from the socket
- * the body is the "real" content of the reply
- * @return string body content 
- * @scope private
- **/
-    function processBody() {
-      $data = '';
-      $counter = 0;
+    function addParameter($key, $value) {
+      $this->params[$key] = $value;
+    }
 
-      do {
-        $status = socket_get_status($this->socket);
-        if ($status['eof'] == 1) {
-          break;
+    function savePublicCertificate($server = null, $port = null) {
+      if ((PHP_VERSION >= 5) && extension_loaded('openssl') && is_writable(DIR_FS_CACHE)) {
+        if (!isset($server)) {
+          $server = $this->url['host'];
         }
 
-        if ($status['unread_bytes'] > 0) {
-          $buffer = fread($this->socket, $status['unread_bytes']);
-          $counter = 0;
-        } else {
-          $buffer = fread($this->socket, 128);
-          $counter++;
-          usleep(2);
+        if (!isset($port)) {
+          $port = $this->url['port'];
         }
 
-        $data .= $buffer;
-      } while ( ($status['unread_bytes'] > 0) || ($counter++ < 10) );
+        $public_cert = null;
 
-      return $data;
-    }
+        $context = stream_context_create(array('ssl' => array('capture_peer_cert' => true)));
 
-/**
- * Calculate and return the URI to be sent ( proxy purpose )
- * @param the local URI
- * @return URI to be used in the HTTP request
- * @scope private
- **/
-    function makeUri($uri) {
-      $a = parse_url($uri);
+        $socket = stream_socket_client('ssl://' . $server . ':' . $port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
 
-      if ( (isset($a['scheme'])) && (isset($a['host'])) ) {
-        $this->url = $a;
-      } else {
-        unset($this->url['query']);
-        unset($this->url['fragment']);
-        $this->url = array_merge($this->url, $a);
-      }
+        $options = stream_context_get_options($socket);
 
-      if ($this->useProxy) {
-        $requesturi = 'http://' . $this->url['host'] . (empty($this->url['port']) ? '' : ':' . $this->url['port']) . $this->url['path'] . (empty($this->url['query']) ? '' : '?' . $this->url['query']);
-      } else {
-        $requesturi = $this->url['path'] . (empty($this->url['query']) ? '' : '?' . $this->url['query']);
+        openssl_x509_export($options['ssl']['peer_certificate'], $public_cert);
+
+        if (!empty($public_cert)) {
+          return file_put_contents(DIR_FS_CACHE . $server . '.crt', $public_cert);
+        }
       }
 
-      return $requesturi;
+      return false;
     }
+
+// Deprecated
+    function sendCommand($command) {
+      trigger_error('httpClient::sendCommand is deprecated.');
+    }
+
+// Deprecated
+    function disconnect() { }
   }
-?>
\ No newline at end of file
+?>
diff -x .svn -aruN 2.3.3.src/includes/languages/english/modules/payment/paypal_standard.php 2.3.3.cp1.src/includes/languages/english/modules/payment/paypal_standard.php
--- 2.3.3.src/includes/languages/english/modules/payment/paypal_standard.php	2012-09-24 14:33:44.000000000 -0500
+++ 2.3.3.cp1.src/includes/languages/english/modules/payment/paypal_standard.php	2013-04-02 16:01:50.000000000 -0500
@@ -13,4 +13,6 @@
   define('MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_TITLE', 'PayPal Website Payments Standard');
   define('MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_PUBLIC_TITLE', 'PayPal (including Credit and Debit Cards)');
   define('MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_DESCRIPTION', '<img src="images/icon_popup.gif" border="0">&nbsp;<a href="https://www.paypal.com/mrb/pal=PS2X9Q773CKG4" target="_blank" style="text-decoration: underline; font-weight: bold;">Visit PayPal Website</a>&nbsp;<a href="javascript:toggleDivBlock(\'paypalStdInfo\');">(info)</a><span id="paypalStdInfo" style="display: none;"><br /><i>Using the above link to signup at PayPal grants osCommerce a small financial bonus for referring a customer.</i></span>');
+  define('MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_PAYPAL_RETURN_BUTTON', 'Back to ' . STORE_NAME); // Maximum length 60 characters, otherwise it is ignored.
+  define('MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_INVALID_TRANSACTION', 'Could not verify the PayPal transaction. Please try again.');
 ?>
diff -x .svn -aruN 2.3.3.src/includes/modules/payment/paypal_standard.php 2.3.3.cp1.src/includes/modules/payment/paypal_standard.php
--- 2.3.3.src/includes/modules/payment/paypal_standard.php	2012-09-24 14:33:44.000000000 -0500
+++ 2.3.3.cp1.src/includes/modules/payment/paypal_standard.php	2013-04-02 16:01:50.000000000 -0500
@@ -5,7 +5,7 @@
   osCommerce, Open Source E-Commerce Solutions
   http://www.oscommerce.com
 
-  Copyright (c) 2008 osCommerce
+  Copyright (c) 2012 osCommerce
 
   Released under the GNU General Public License
 */
@@ -17,7 +17,7 @@
     function paypal_standard() {
       global $order;
 
-      $this->signature = 'paypal|paypal_standard|1.0|2.2';
+      $this->signature = 'paypal|paypal_standard|1.1|2.2';
 
       $this->code = 'paypal_standard';
       $this->title = MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_TITLE;
@@ -135,8 +135,7 @@
         if ($insert_order == true) {
           $order_totals = array();
           if (is_array($order_total_modules->modules)) {
-            reset($order_total_modules->modules);
-            while (list(, $value) = each($order_total_modules->modules)) {
+            foreach ($order_total_modules->modules as $value) {
               $class = substr($value, 0, strrpos($value, '.'));
               if ($GLOBALS[$class]->enabled) {
                 for ($i=0, $n=sizeof($GLOBALS[$class]->output); $i<$n; $i++) {
@@ -288,11 +287,16 @@
                           'custom' => $customer_id,
                           'no_note' => '1',
                           'notify_url' => tep_href_link('ext/modules/payment/paypal/standard_ipn.php', '', 'SSL', false, false),
+                          'rm' => '2',
                           'return' => tep_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL'),
                           'cancel_return' => tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL'),
                           'bn' => 'osCommerce22_Default_ST',
                           'paymentaction' => ((MODULE_PAYMENT_PAYPAL_STANDARD_TRANSACTION_METHOD == 'Sale') ? 'sale' : 'authorization'));
 
+      if (defined('MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_PAYPAL_RETURN_BUTTON') && tep_not_null(MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_PAYPAL_RETURN_BUTTON) && (strlen(MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_PAYPAL_RETURN_BUTTON) <= 60)) {
+        $parameters['cbt'] = MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_PAYPAL_RETURN_BUTTON;
+      }
+
       if (is_numeric($sendto) && ($sendto > 0)) {
         $parameters['address_override'] = '1';
         $parameters['first_name'] = $order->delivery['firstname'];
@@ -323,8 +327,7 @@
         $random_string = rand(100000, 999999) . '-' . $customer_id . '-';
 
         $data = '';
-        reset($parameters);
-        while (list($key, $value) = each($parameters)) {
+        foreach ($parameters as $key => $value) {
           $data .= $key . '=' . $value . "\n";
         }
 
@@ -379,8 +382,7 @@
 
         unset($data);
       } else {
-        reset($parameters);
-        while (list($key, $value) = each($parameters)) {
+        foreach ($parameters as $key => $value) {
           $process_button_string .= tep_draw_hidden_field($key, $value);
         }
       }
@@ -389,30 +391,105 @@
     }
 
     function before_process() {
-      global $customer_id, $order, $order_totals, $sendto, $billto, $languages_id, $payment, $currencies, $cart, $cart_PayPal_Standard_ID;
-      global $$payment;
+      global $customer_id, $order, $order_totals, $sendto, $billto, $languages_id, $payment, $currencies, $cart, $cart_PayPal_Standard_ID, $$payment, $HTTP_GET_VARS, $HTTP_POST_VARS, $messageStack;
+
+      if (!class_exists('httpClient')) {
+        include('includes/classes/http_client.php');
+      }
+
+      $result = false;
+
+      if ( ($HTTP_POST_VARS['receiver_email'] == MODULE_PAYMENT_PAYPAL_STANDARD_ID) || (defined('MODULE_PAYMENT_PAYPAL_STANDARD_PRIMARY_ID') && tep_not_null(MODULE_PAYMENT_PAYPAL_STANDARD_PRIMARY_ID) && ($HTTP_POST_VARS['receiver_email'] == MODULE_PAYMENT_PAYPAL_STANDARD_PRIMARY_ID)) ) {
+        if (MODULE_PAYMENT_PAYPAL_STANDARD_GATEWAY_SERVER == 'Live') {
+          $server = 'www.paypal.com';
+        } else {
+          $server = 'www.sandbox.paypal.com';
+        }
+
+        $parameters = 'cmd=_notify-validate';
+
+        foreach ($HTTP_POST_VARS as $key => $value) {
+          $parameters .= '&' . $key . '=' . urlencode(stripslashes($value));
+        }
+
+        $http = new httpClient($server, 443);
+
+        if (defined('MODULE_PAYMENT_PAYPAL_STANDARD_PROXY') && tep_not_null(MODULE_PAYMENT_PAYPAL_STANDARD_PROXY)) {
+          $proxy_server = MODULE_PAYMENT_PAYPAL_STANDARD_PROXY;
+          $proxy_port = null;
+
+          if (strpos(MODULE_PAYMENT_PAYPAL_STANDARD_PROXY, ':') !== false) {
+            list($proxy_server, $proxy_port) = explode(':', MODULE_PAYMENT_PAYPAL_STANDARD_PROXY, 2);
+          }
+
+          $http->setProxy($proxy_server, $proxy_port);
+        }
+
+        if (file_exists(DIR_FS_CACHE . $server . '.crt')) {
+          $http->addParameter('cafile', DIR_FS_CACHE . $server . '.crt');
+        }
+
+        if ($http->post('/cgi-bin/webscr', $parameters) == 200) {
+          $result = $http->getBody();
+        }
+      }
+
+      if ($result != 'VERIFIED') {
+        if (defined('MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_INVALID_TRANSACTION')) {
+          $messageStack->add_session('header', MODULE_PAYMENT_PAYPAL_STANDARD_TEXT_INVALID_TRANSACTION);
+        }
+
+        if (tep_not_null(MODULE_PAYMENT_PAYPAL_STANDARD_DEBUG_EMAIL)) {
+          $email_body = '$HTTP_POST_VARS:' . "\n\n";
+
+          foreach ($HTTP_POST_VARS as $key => $value) {
+            $email_body .= $key . '=' . $value . "\n";
+          }
+
+          $email_body .= "\n" . '$HTTP_GET_VARS:' . "\n\n";
+
+          foreach ($HTTP_GET_VARS as $key => $value) {
+            $email_body .= $key . '=' . $value . "\n";
+          }
+
+          tep_mail('', MODULE_PAYMENT_PAYPAL_STANDARD_DEBUG_EMAIL, 'PayPal Invalid Transaction', $email_body, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
+        }
+
+        tep_redirect(tep_href_link(FILENAME_SHOPPING_CART));
+      }
 
       $order_id = substr($cart_PayPal_Standard_ID, strpos($cart_PayPal_Standard_ID, '-')+1);
 
       $check_query = tep_db_query("select orders_status from " . TABLE_ORDERS . " where orders_id = '" . (int)$order_id . "'");
-      if (tep_db_num_rows($check_query)) {
-        $check = tep_db_fetch_array($check_query);
 
-        if ($check['orders_status'] == MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID) {
-          $sql_data_array = array('orders_id' => $order_id,
-                                  'orders_status_id' => MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID,
-                                  'date_added' => 'now()',
-                                  'customer_notified' => '0',
-                                  'comments' => '');
+      if (!tep_db_num_rows($check_query)) {
+        tep_redirect(tep_href_link(FILENAME_SHOPPING_CART));
+      }
+
+      $check = tep_db_fetch_array($check_query);
 
-          tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
-        }
+      $new_order_status = DEFAULT_ORDERS_STATUS_ID;
+
+      if ($check['orders_status'] == MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID) {
+        $sql_data_array = array('orders_id' => $order_id,
+                                'orders_status_id' => MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID,
+                                'date_added' => 'now()',
+                                'customer_notified' => '0',
+                                'comments' => '');
+
+        tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
+      } else {
+        $new_order_status = $check['orders_status'];
       }
 
-      tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . (MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID > 0 ? (int)MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID : (int)DEFAULT_ORDERS_STATUS_ID) . "', last_modified = now() where orders_id = '" . (int)$order_id . "'");
+      if ( (MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID > 0) && ($check['orders_status'] == MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID) ) {
+        $new_order_status = MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID;
+      }
+
+      tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . (int)$new_order_status . "', last_modified = now() where orders_id = '" . (int)$order_id . "'");
 
       $sql_data_array = array('orders_id' => $order_id,
-                              'orders_status_id' => (MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID > 0 ? (int)MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID : (int)DEFAULT_ORDERS_STATUS_ID),
+                              'orders_status_id' => (int)$new_order_status,
                               'date_added' => 'now()',
                               'customer_notified' => (SEND_EMAILS == 'true') ? '1' : '0',
                               'comments' => $order->info['comments']);
@@ -576,48 +653,36 @@
       return $this->_check;
     }
 
-    function install() {
-      $check_query = tep_db_query("select orders_status_id from " . TABLE_ORDERS_STATUS . " where orders_status_name = 'Preparing [PayPal Standard]' limit 1");
+    function install($parameter = null) {
+      $params = $this->getParams();
 
-      if (tep_db_num_rows($check_query) < 1) {
-        $status_query = tep_db_query("select max(orders_status_id) as status_id from " . TABLE_ORDERS_STATUS);
-        $status = tep_db_fetch_array($status_query);
-
-        $status_id = $status['status_id']+1;
+      if (isset($parameter)) {
+        if (isset($params[$parameter])) {
+          $params = array($parameter => $params[$parameter]);
+        } else {
+          $params = array();
+        }
+      }
 
-        $languages = tep_get_languages();
+      foreach ($params as $key => $data) {
+        $sql_data_array = array('configuration_title' => $data['title'],
+                                'configuration_key' => $key,
+                                'configuration_value' => (isset($data['value']) ? $data['value'] : ''),
+                                'configuration_description' => $data['desc'],
+                                'configuration_group_id' => '6',
+                                'sort_order' => '0',
+                                'date_added' => 'now()');
 
-        foreach ($languages as $lang) {
-          tep_db_query("insert into " . TABLE_ORDERS_STATUS . " (orders_status_id, language_id, orders_status_name) values ('" . $status_id . "', '" . $lang['id'] . "', 'Preparing [PayPal Standard]')");
+        if (isset($data['set_func'])) {
+          $sql_data_array['set_function'] = $data['set_func'];
         }
 
-        $flags_query = tep_db_query("describe " . TABLE_ORDERS_STATUS . " public_flag");
-        if (tep_db_num_rows($flags_query) == 1) {
-          tep_db_query("update " . TABLE_ORDERS_STATUS . " set public_flag = 0 and downloads_flag = 0 where orders_status_id = '" . $status_id . "'");
+        if (isset($data['use_func'])) {
+          $sql_data_array['use_function'] = $data['use_func'];
         }
-      } else {
-        $check = tep_db_fetch_array($check_query);
 
-        $status_id = $check['orders_status_id'];
+        tep_db_perform(TABLE_CONFIGURATION, $sql_data_array);
       }
-
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable PayPal Website Payments Standard', 'MODULE_PAYMENT_PAYPAL_STANDARD_STATUS', 'False', 'Do you want to accept PayPal Website Payments Standard payments?', '6', '3', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('E-Mail Address', 'MODULE_PAYMENT_PAYPAL_STANDARD_ID', '', 'The PayPal seller e-mail address to accept payments for', '6', '4', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort order of display.', 'MODULE_PAYMENT_PAYPAL_STANDARD_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '0', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Payment Zone', 'MODULE_PAYMENT_PAYPAL_STANDARD_ZONE', '0', 'If a zone is selected, only enable this payment method for that zone.', '6', '2', 'tep_get_zone_class_title', 'tep_cfg_pull_down_zone_classes(', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set Preparing Order Status', 'MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID', '" . $status_id . "', 'Set the status of prepared orders made with this payment module to this value', '6', '0', 'tep_cfg_pull_down_order_statuses(', 'tep_get_order_status_name', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set PayPal Acknowledged Order Status', 'MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID', '0', 'Set the status of orders made with this payment module to this value', '6', '0', 'tep_cfg_pull_down_order_statuses(', 'tep_get_order_status_name', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Gateway Server', 'MODULE_PAYMENT_PAYPAL_STANDARD_GATEWAY_SERVER', 'Live', 'Use the testing (sandbox) or live gateway server for transactions?', '6', '6', 'tep_cfg_select_option(array(\'Live\', \'Sandbox\'), ', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Transaction Method', 'MODULE_PAYMENT_PAYPAL_STANDARD_TRANSACTION_METHOD', 'Sale', 'The processing method to use for each transaction.', '6', '0', 'tep_cfg_select_option(array(\'Authorization\', \'Sale\'), ', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Page Style', 'MODULE_PAYMENT_PAYPAL_STANDARD_PAGE_STYLE', '', 'The page style to use for the transaction procedure (defined at your PayPal Profile page)', '6', '4', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Debug E-Mail Address', 'MODULE_PAYMENT_PAYPAL_STANDARD_DEBUG_EMAIL', '', 'All parameters of an Invalid IPN notification will be sent to this email address if one is entered.', '6', '4', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable Encrypted Web Payments', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_STATUS', 'False', 'Do you want to enable Encrypted Web Payments?', '6', '3', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Your Private Key', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PRIVATE_KEY', '', 'The location of your Private Key to use for signing the data. (*.pem)', '6', '4', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Your Public Certificate', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PUBLIC_KEY', '', 'The location of your Public Certificate to use for signing the data. (*.pem)', '6', '4', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('PayPals Public Certificate', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PAYPAL_KEY', '', 'The location of the PayPal Public Certificate for encrypting the data.', '6', '4', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Your PayPal Public Certificate ID', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_CERT_ID', '', 'The Certificate ID to use from your PayPal Encrypted Payment Settings Profile.', '6', '4', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Working Directory', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_WORKING_DIRECTORY', '', 'The working directory to use for temporary files. (trailing slash needed)', '6', '4', now())");
-      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('OpenSSL Location', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_OPENSSL', '/usr/bin/openssl', 'The location of the openssl binary file.', '6', '4', now())");
     }
 
     function remove() {
@@ -625,7 +690,107 @@
     }
 
     function keys() {
-      return array('MODULE_PAYMENT_PAYPAL_STANDARD_STATUS', 'MODULE_PAYMENT_PAYPAL_STANDARD_ID', 'MODULE_PAYMENT_PAYPAL_STANDARD_ZONE', 'MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID', 'MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID', 'MODULE_PAYMENT_PAYPAL_STANDARD_GATEWAY_SERVER', 'MODULE_PAYMENT_PAYPAL_STANDARD_TRANSACTION_METHOD', 'MODULE_PAYMENT_PAYPAL_STANDARD_PAGE_STYLE', 'MODULE_PAYMENT_PAYPAL_STANDARD_DEBUG_EMAIL', 'MODULE_PAYMENT_PAYPAL_STANDARD_SORT_ORDER', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_STATUS', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PRIVATE_KEY', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PUBLIC_KEY', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PAYPAL_KEY', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_CERT_ID', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_WORKING_DIRECTORY', 'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_OPENSSL');
+      $keys = array_keys($this->getParams());
+
+      if ($this->check()) {
+        foreach ($keys as $key) {
+          if (!defined($key)) {
+            $this->install($key);
+          }
+        }
+      }
+
+      return $keys;
+    }
+
+    function getParams() {
+      if (!defined('MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID')) {
+        $check_query = tep_db_query("select orders_status_id from " . TABLE_ORDERS_STATUS . " where orders_status_name = 'Preparing [PayPal Standard]' limit 1");
+
+        if (tep_db_num_rows($check_query) < 1) {
+          $status_query = tep_db_query("select max(orders_status_id) as status_id from " . TABLE_ORDERS_STATUS);
+          $status = tep_db_fetch_array($status_query);
+
+          $status_id = $status['status_id']+1;
+
+          $languages = tep_get_languages();
+
+          foreach ($languages as $lang) {
+            tep_db_query("insert into " . TABLE_ORDERS_STATUS . " (orders_status_id, language_id, orders_status_name) values ('" . $status_id . "', '" . $lang['id'] . "', 'Preparing [PayPal Standard]')");
+          }
+
+          $flags_query = tep_db_query("describe " . TABLE_ORDERS_STATUS . " public_flag");
+          if (tep_db_num_rows($flags_query) == 1) {
+            tep_db_query("update " . TABLE_ORDERS_STATUS . " set public_flag = 0 and downloads_flag = 0 where orders_status_id = '" . $status_id . "'");
+          }
+        } else {
+          $check = tep_db_fetch_array($check_query);
+
+          $status_id = $check['orders_status_id'];
+        }
+      } else {
+        $status_id = MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID;
+      }
+
+      $params = array('MODULE_PAYMENT_PAYPAL_STANDARD_STATUS' => array('title' => 'Enable PayPal Website Payments Standard',
+                                                                       'desc' => 'Do you want to accept PayPal Website Payments Standard payments?',
+                                                                       'value' => 'False',
+                                                                       'set_func' => 'tep_cfg_select_option(array(\'True\', \'False\'), '),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_ID' => array('title' => 'Seller E-Mail Address',
+                                                                   'desc' => 'The PayPal seller e-mail address to accept payments for'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_PRIMARY_ID' => array('title' => 'Primary E-Mail Address',
+                                                                           'desc' => 'The primary PayPal seller e-mail address to validate IPN with (leave empty if it is the same as the Seller E-Mail Address)'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_ZONE' => array('title' => 'Payment Zone',
+                                                                     'desc' => 'If a zone is selected, only enable this payment method for that zone.',
+                                                                     'value' => '0',
+                                                                     'use_func' => 'tep_get_zone_class_title',
+                                                                     'set_func' => 'tep_cfg_pull_down_zone_classes('),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_PREPARE_ORDER_STATUS_ID' => array('title' => 'Set Preparing Order Status',
+                                                                                        'desc' => 'Set the status of prepared orders made with this payment module to this value',
+                                                                                        'value' => $status_id,
+                                                                                        'set_func' => 'tep_cfg_pull_down_order_statuses(',
+                                                                                        'use_func' => 'tep_get_order_status_name'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_ORDER_STATUS_ID' => array('title' => 'Set PayPal Acknowledged Order Status',
+                                                                                'desc' => 'Set the status of orders made with this payment module to this value',
+                                                                                'value' => '0',
+                                                                                'set_func' => 'tep_cfg_pull_down_order_statuses(',
+                                                                                'use_func' => 'tep_get_order_status_name'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_GATEWAY_SERVER' => array('title' => 'Gateway Server',
+                                                                               'desc' => 'Use the testing (sandbox) or live gateway server for transactions?',
+                                                                               'value' => 'Live',
+                                                                               'set_func' => 'tep_cfg_select_option(array(\'Live\', \'Sandbox\'), '),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_TRANSACTION_METHOD' => array('title' => 'Transaction Method',
+                                                                                   'desc' => 'The processing method to use for each transaction.',
+                                                                                   'value' => 'Sale',
+                                                                                   'set_func' => 'tep_cfg_select_option(array(\'Authorization\', \'Sale\'), '),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_PROXY' => array('title' => 'Proxy Server',
+                                                                      'desc' => 'Send API requests through this proxy server. (host:port, eg: 123.45.67.89:8080 or proxy.example.com:8080)'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_PAGE_STYLE' => array('title' => 'Page Style',
+                                                                           'desc' => 'The page style to use for the transaction procedure (defined at your PayPal Profile page)'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_DEBUG_EMAIL' => array('title' => 'Debug E-Mail Address',
+                                                                            'desc' => 'All parameters of an Invalid IPN notification will be sent to this email address if one is entered.'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_STATUS' => array('title' => 'Enable Encrypted Web Payments',
+                                                                           'desc' => 'Do you want to enable Encrypted Web Payments?',
+                                                                           'value' => 'False',
+                                                                           'set_func' => 'tep_cfg_select_option(array(\'True\', \'False\'), '),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PRIVATE_KEY' => array('title' => 'Your Private Key',
+                                                                                'desc' => 'The location of your Private Key to use for signing the data. (*.pem)'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PUBLIC_KEY' => array('title' => 'Your Public Certificate',
+                                                                               'desc' => 'The location of your Public Certificate to use for signing the data. (*.pem)'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_PAYPAL_KEY' => array('title' => 'PayPals Public Certificate',
+                                                                               'desc' => 'The location of the PayPal Public Certificate for encrypting the data.'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_CERT_ID' => array('title' => 'Your PayPal Public Certificate ID',
+                                                                            'desc' => 'The Certificate ID to use from your PayPal Encrypted Payment Settings Profile.'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_WORKING_DIRECTORY' => array('title' => 'Working Directory',
+                                                                                      'desc' => 'The working directory to use for temporary files. (trailing slash needed)'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_EWP_OPENSSL' => array('title' => 'OpenSSL Location',
+                                                                            'desc' => 'The location of the openssl binary file.',
+                                                                            'value' => '/usr/bin/openssl'),
+                      'MODULE_PAYMENT_PAYPAL_STANDARD_SORT_ORDER' => array('title' => 'Sort order of display.',
+                                                                           'desc' => 'Sort order of display. Lowest is displayed first.',
+                                                                           'value' => '0'));
+
+      return $params;
     }
 
 // format prices without currency formatting
