Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Fixes for osCommerce on IIS with ISAPI-PHP


Talegen

Recommended Posts

I was asked to look into fixing a specific SSL problem for osCommerce running on a win2k3 with ISAPI php, and in researching it discovered that there are several other problems with the osCommerce code (specifically the use of getenv) and ISAPI PHP.

 

I have gone ahead and made changes to the code (which should run on any platform) and suggest that these changes be taken forward into the next revision of osCommerce. Basically, eliminate the use of getenv(). Some lines I did not change because they are for environment variables that are mod_ssl specific and wouldn't make a difference on IIS anyway, but here is the modifications that do need to be made:

 

[admin\index.php]

 

on or about line 179

 

Replace:

 ?if (getenv('HTTPS') == 'on') {
? ?$size = ((getenv('SSL_CIPHER_ALGKEYSIZE')) ? getenv('SSL_CIPHER_ALGKEYSIZE') . '-bit' : '<i>' . BOX_CONNECTION_UNKNOWN . '</i>');

With:

 ?if ($SERVER_PORT == 443) {
? ?$size = (($HTTP_ENV_VARS['SSL_CIPHER_ALGKEYSIZE']) ? $HTTP_ENV_VARS['SSL_CIPHER_ALGKEYSIZE'] . '-bit' : '<i>' . BOX_CONNECTION_UNKNOWN . '</i>');

 

NOTE: SSL_CIPHER_ALGKEYSIZE is an environment variable that only works with mod_ssl (not IIS)

 

 

[admin\includes\classes\language.php]

 

on or about line 82

 

Replace:

 ? ? $this->browser_languages = explode(',', getenv('HTTP_ACCEPT_LANGUAGE'));

With:

 ? ? ?$this->browser_languages = explode(',', $HTTP_ACCEPT_LANGUAGE);

 

 

[admin\includes\classes\logger.php]

 

on or about line 37

 

Replace:

 ? ? ?$this->write(getenv('REQUEST_URI'), $this->timer_total . 's');

With:

 ? ? ?$this->write($REQUEST_URI, $this->timer_total . 's');

 

 

[includes\application_bottom.php]

 

on or about line 20

 

Replace:

 ? ?error_log(strftime(STORE_PARSE_DATE_TIME_FORMAT) . ' - ' . getenv('REQUEST_URI') . ' (' . $parse_time . 's)' . "\n", 3, STORE_PAGE_PARSE_TIME_LOG);

With:

 ? ?error_log(strftime(STORE_PARSE_DATE_TIME_FORMAT) . ' - ' . $REQUEST_URI . ' (' . $parse_time . 's)' . "\n", 3, STORE_PAGE_PARSE_TIME_LOG);

 

[includes\application_top.php]

 

on or about line 90

 

NOTE: ehhhh don't bother, PATH_INFO is apache stuff

 

on or about line 174

 

Replace:

 ? ?$user_agent = strtolower(getenv('HTTP_USER_AGENT'));

With:

 ? ?$user_agent = strtolower($HTTP_USER_AGENT);

 

on or about line 204

 

NOTE: don't bother, mod_ssl only variable >:(

 

on or about line 218

 

Replace:

 ? ?$http_user_agent = getenv('HTTP_USER_AGENT');

With:

 ? ?$http_user_agent = $HTTP_USER_AGENT;

 

 

[includes\classes\language.php]

 

on or about line 82

 

Replace:

 ? ? ?$this->browser_languages = explode(',', getenv('HTTP_ACCEPT_LANGUAGE'));

With:

 ? ? ?$this->browser_languages = explode(',', $HTTP_ACCEPT_LANGUAGE);

 

 

[includes\functions\general.php]

 

on or about line 23

 

Replace:

 ? ?if ( (ENABLE_SSL == true) && (getenv('HTTPS') == 'on') ) { // We are loading an SSL page

With:

 ? ?if ( (ENABLE_SSL == true) && ($SERVER_PORT == 443) ) { // We are loading an SSL page

 

on or about line 1187

 

Replace:

 ? ? ?if (getenv('HTTP_X_FORWARDED_FOR')) {
? ? ? ?$ip = getenv('HTTP_X_FORWARDED_FOR');
? ? ?} elseif (getenv('HTTP_CLIENT_IP')) {
? ? ? ?$ip = getenv('HTTP_CLIENT_IP');
? ? ?} else {
? ? ? ?$ip = getenv('REMOTE_ADDR');
? ? ?}

With:

 ? ? ?if ($HTTP_X_FORWARDED_FOR) {
? ? ? ?$ip = $HTTP_X_FORWARDED_FOR;
? ? ?} elseif ($HTTP_CLIENT_IP) {
? ? ? ?$ip = $HTTP_CLIENT_IP;
? ? ?} else {
? ? ? ?$ip = $REMOTE_ADDR;
? ? ?}

 

[includes\functions\whos_online.php]

 

on or about line 29

 

Replace:

 ? ?$wo_ip_address = getenv('REMOTE_ADDR');
? ?$wo_last_page_url = getenv('REQUEST_URI');

With:

 ? ?$wo_ip_address = $REMOTE_ADDR;
? ?$wo_last_page_url = $REQUEST_URI;

 

[includes\modules\payment\secpay.php]

 

on or about line 132

 

Replace:

 ? ? ? ?if ($remote_host = getenv('REMOTE_HOST')) {

With:

 ? ? ? ?if ($remote_host = $REMOTE_HOST) {

 

 

Hope this helps. Let me know if I missed something or if you have additions or changes to make.

 

Thanks,

 

Rob

Link to comment
Share on other sites

here is the modifications that do need to be made:

That would be much nicer of you to use some utilty like unix "diff"

if you want to show changes in code.

In that way you (1) give people the chance to "patch" their source

(2) make your changes easier to look at.

Link to comment
Share on other sites

Forgot to add this to the mods list as well...

 

[includes/application_top.php]

 

on or about line 42

 

Replace:

$request_type = (getenv('HTTPS') == 'on') ? 'SSL' : 'NONSSL';

With:

$request_type = ($SERVER_PORT == 443) ? 'SSL' : 'NONSSL';

Link to comment
Share on other sites

Thank you for your input.

 

Can you provide some details about the problem with getenv()? Is the function unavailable? Is there a problem with the returned values?

 

It seems your modifications will only run with register_globals=on. Future versions of osCommerce will run with register_globals=off, and your code is not useable as is.

Christian Lescuyer

Link to comment
Share on other sites

It seems your modifications will only run with register_globals=on. Future versions of osCommerce will run with register_globals=off, and your code is not useable as is.
I had that thought as well...perhaps replacing with $_SERVER variables (I don't think that those work in PHP3, so that would be an MS3 thing)? That should pick up HTTP_USER_AGENT, HTTP_ACCEPT_LANGUAGE, REMOTE_ADDR, REMOTE_HOST, REQUEST_URI, and SERVER_PORT (although, SERVER_PORT is not a good way to check if something is SSL as 443 is a standard not a requirement). Misses HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR (perhaps these are in $_ENV, like SSL_CIPHER_ALGKEYSIZE). Or maybe it needs to be a fail over; try getenv but fail over to alternatives if necessary (perhaps IIS needs register_globals to operate properly).

 

It's also worth pointing out that it is probably better to run osCommerce on a Linux box running Apache, as PHP was written for Linux/Apache and has only been ported to MS Windows/IIS.

 

Cheers,

Matt

Link to comment
Share on other sites

The problem with getenv() is that it according to the PHP docs it doesn't work with the ISAPI module on IIS/win32. Hmmm, thank's for your input regarding register_globals, I forgot I have that set on for phpBB. You're correct in regards to checking the port number, but there's really no other way (that I know of) to determine if we're in a HTTPS session or not. If you know of another way, please let me know. Thanks for your input! :)

 

-Rob-

Link to comment
Share on other sites

http://www.php.net/variables.predefined has a revised method of getting the IP that is ISAPI compliant (it's in the comments section; search page for ISAPI).

The problem with getenv() is that it according to the PHP docs it doesn't work with the ISAPI module on IIS/win32.
Rob, could you try the following code (save it as its own page on your server and browse to it) and let us know what happens?
<?php
 if (!function_exists('getenv')) {
   echo 'Function getenv does not exist!';
 } else {
   echo 'Function getenv('HTTPS') returns:  (' . getenv('HTTPS') . ')';
 }
?>

Note: a possible result would be an error on line 5: if so, please post the error. If it prints that getenv does not exist, then Christian could add a new compatibility function to the core code in includes/functions/compatibility.php. Something like

  if (!function_exists('getenv')) {
   function getenv($variable) {
     if (!tep_not_null($variable) return false;
     elseif (isset($_SERVER[$index])) return $_SERVER[$index];
     elseif (isset($_ENV[$index])) return $_ENV[$index];
     else return false;
   }
 }

php_sapi_name() will return "isapi" when PHP is running on IIS in ISAPI mode, in case anyone needed this info.

 

According to www.php.net/manual/en/reserved.variables.php, you can use $_SERVER['HTTPS'] to get the connection type. If this doesn't work for you, perhaps a check to see if this is set then check the server port.

 

Hth,

Matt

Link to comment
Share on other sites

$_SERVER['HTTPS'] would work on your server (instead of the getenv). Checking if the function is defined obviously won't work. However, replacing all getenv references with tep_getenv and adding the following function to includes/functions/compatibility.php might work:

    function tep_getenv($index) {
    if (!tep_not_null($index) return false;
    elseif (isset($_SERVER[$index])) return $_SERVER[$index];
    elseif (isset($_ENV[$index])) return $_ENV[$index];
    elseif (tep_not_null(getenv($index))) return $_ENV[$index];
    else return false;
  }

If you get a chance to test this, I would be interested in knowing if it works.

 

Thanks,

Matt

Link to comment
Share on other sites

It is not working for me. :unsure:

 

I added these lines to my compatiblity.php file. After that, I went in and replace all getenv references with tep_getenv. My main page would blank out after that. However, as soon as I put the getenv back, the page would show up normal. I am using PHP. 4.3.4 if that makes any differences.

 

Thanks

-Tuan

 

   function tep_getenv($index) {
   if (!tep_not_null($index) return false;
   elseif (isset($_SERVER[$index])) return $_SERVER[$index];
   elseif (isset($_ENV[$index])) return $_ENV[$index];
   elseif (tep_not_null(getenv($index))) return $_ENV[$index];
   else return false;
 }

 

 

 

 

And this is what it looks like.

<?php
/*
 $Id: compatibility.php,v 1.19 2003/04/09 16:12:54 project3000 Exp $

 osCommerce, Open Source E-Commerce Solutions
 http://www.oscommerce.com

 Copyright (c) 2003 osCommerce

 Released under the GNU General Public License

 Modified by Marco Canini, <[email protected]>
 - Fixed a bug with arrays in $HTTP_xxx_VARS
*/

////
// Recursively handle magic_quotes_gpc turned off.
// This is due to the possibility of have an array in
// $HTTP_xxx_VARS
// Ie, products attributes
 function do_magic_quotes_gpc(&$ar) {
   if (!is_array($ar)) return false;

   while (list($key, $value) = each($ar)) {
     if (is_array($value)) {
       do_magic_quotes_gpc($value);
     } else {
       $ar[$key] = addslashes($value);
     }
   }
 }

// $HTTP_xxx_VARS are always set on php4
 if (!is_array($HTTP_GET_VARS)) $HTTP_GET_VARS = array();
 if (!is_array($HTTP_POST_VARS)) $HTTP_POST_VARS = array();
 if (!is_array($HTTP_COOKIE_VARS)) $HTTP_COOKIE_VARS = array();

// handle magic_quotes_gpc turned off.
 if (!get_magic_quotes_gpc()) {
   do_magic_quotes_gpc($HTTP_GET_VARS);
   do_magic_quotes_gpc($HTTP_POST_VARS);
   do_magic_quotes_gpc($HTTP_COOKIE_VARS);
 }

 if (!function_exists('array_splice')) {
   function array_splice(&$array, $maximum) {
     if (sizeof($array) >= $maximum) {
       for ($i=0; $i<$maximum; $i++) {
         $new_array[$i] = $array[$i];
       }
       $array = $new_array;
     }
   }
 }

 if (!function_exists('in_array')) {
   function in_array($lookup_value, $lookup_array) {
     reset($lookup_array);
     while (list($key, $value) = each($lookup_array)) {
       if ($value == $lookup_value) return true;
     }

     return false;
   }
 }

 if (!function_exists('array_reverse')) {
   function array_reverse($array) {
     for ($i=0, $n=sizeof($array); $i<$n; $i++) $array_reversed[$i] = $array[($n-$i-1)];

     return $array_reversed;
   }
 }

 if (!function_exists('constant')) {
   function constant($constant) {
     eval("\$temp=$constant;");

     return $temp;
   }
 }

 if (!function_exists('is_null')) {
   function is_null($value) {
     if (is_array($value)) {
       if (sizeof($value) > 0) {
         return false;
       } else {
         return true;
       }
     } else {
       if (($value != '') && ($value != 'NULL') && (strlen(trim($value)) > 0)) {
         return false;
       } else {
         return true;
       }
     }
   }
 }

 if (!function_exists('array_merge')) {
   function array_merge($array1, $array2, $array3 = '') {
     if (empty($array3) && !is_array($array3)) $array3 = array();
     while (list($key, $val) = each($array1)) $array_merged[$key] = $val;
     while (list($key, $val) = each($array2)) $array_merged[$key] = $val;
     if (sizeof($array3) > 0) while (list($key, $val) = each($array3)) $array_merged[$key] = $val;

     return (array) $array_merged;
   }
 }

 if (!function_exists('is_numeric')) {
   function is_numeric($param) {
     return ereg('^[0-9]{1,50}.?[0-9]{0,50}$', $param);
   }
 }

 if (!function_exists('array_slice')) {
   function array_slice($array, $offset, $length = 0) {
     if ($offset < 0 ) {
       $offset = sizeof($array) + $offset;
     }
     $length = ((!$length) ? sizeof($array) : (($length < 0) ? sizeof($array) - $length : $length + $offset));
     for ($i = $offset; $i<$length; $i++) {
       $tmp[] = $array[$i];
     }

     return $tmp;
   }
 }

 if (!function_exists('array_map')) {
   function array_map($callback, $array) {
     if (is_array($array)) {
       $_new_array = array();
       reset($array);
       while (list($key, $value) = each($array)) {
         $_new_array[$key] = array_map($callback, $array[$key]);
       }
       return $_new_array;
     } else {
       return $callback($array);
     }
   }
 }

 if (!function_exists('str_repeat')) {
   function str_repeat($string, $number) {
     $repeat = '';

     for ($i=0; $i<$number; $i++) {
       $repeat .= $string;
     }

     return $repeat;
   }
 }

function tep_getenv($index) {
if (!tep_not_null($index) return false;
elseif (isset($_SERVER[$index])) return $_SERVER[$index];
elseif (isset($_ENV[$index])) return $_ENV[$index];
elseif (tep_not_null(getenv($index))) return $_ENV[$index];
else return false;
}


 if (!function_exists('checkdnsrr')) {
   function checkdnsrr($host, $type) {
     if(tep_not_null($host) && tep_not_null($type)) {
       @exec("nslookup -type=$type $host", $output);
       while(list($k, $line) = each($output)) {
         if(eregi("^$host", $line)) {
           return true;
         }
       }
     }
     return false;
   }
 }
?>

Link to comment
Share on other sites

One more question......Is there any good tool out there that you can do a text "Search & Replace" on the entire directory instead of opening up each file manually?

 

I had to do it manually to the files below.

 

[admin\index.php]

[admin\includes\classes\language.php]

[admin\includes\classes\logger.php]

[includes\application_bottom.php]

[includes\application_top.php]

[includes\classes\language.php]

[includes\functions\general.php]

[includes\functions\whos_online.php]

[includes\modules\payment\secpay.php]

 

Did I miss a file that's why it didn't work? :unsure: :unsure: :unsure:

 

Thanks again

-Tuan

Link to comment
Share on other sites

I wrote it wrong, the function should be

 function tep_getenv($index) {
  if (!tep_not_null($index) return false;
  elseif (isset($_SERVER[$index])) return $_SERVER[$index];
  elseif (isset($_ENV[$index])) return $_ENV[$index];
  elseif (tep_not_null(getenv($index))) return getenv($index);
  else return false;
}

or maybe

 function tep_getenv($index) {
  if (!tep_not_null($index) return false;
  elseif (tep_not_null(getenv($index))) return getenv($index);
  elseif (isset($_SERVER[$index])) return $_SERVER[$index];
  elseif (isset($_ENV[$index])) return $_ENV[$index];
  else return false;
}

At the very least, the second function should mostly have the same behavior as getenv (i.e. if getenv set, return that value).

 

Hth,

Matt

Link to comment
Share on other sites

  • 2 years later...

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...