Jump to content

Archived

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

Chemo

A Store Speed Optimization in Progress

Recommended Posts

Just wanted to chime in here. I've had a long running site up (over 2 years now), and I thought I had optimized it about as far as I could.

 

The only thing *new* to me in this thread thus far was the 'page cache'. I gotta admit, I'm impressed. My site went form loading in about 38 seconds on a 56k (graphics heavy) to loading in about 19 seconds.

 

That's a pretty hefty imporvement, and I like how you can control how long the case page last for. Terrific improvements. Thanks for the heads up.


-------------------------------------------------------------------------------------------------------------------------

NOTE: As of Oct 2006, I'm not as active in this forum as I used to be, but I still work with osC quite a bit.

If you have a question about any of my posts here, your best bet is to contact me though either Email or PM in my profile, and I'll be happy to help.

Share this post


Link to post
Share on other sites
Hello, I also want to install this nice Contribution.

However, have a problem with Install?

 

STEP 3 (catalog,includes,funktions, general.php)

 

I found the Code not in my File.

 function tep_db_query($query, $link = 'db_link') {
< SNIP >

 

Can you help me with the Installation?

 

LG

That function is actually located in includes/functions/database.php around line37 or so.

 

I apologize and will correct the install file now.

 

Download the latest query debug here: Debug Query Output

 

Just wanted to chime in here. I've had a long running site up (over 2 years now), and I thought I had optimized it about as far as I could.

 

The only thing *new* to me in this thread thus far was the 'page cache'. I gotta admit, I'm impressed.  My site went form loading in about 38 seconds on a 56k (graphics heavy) to loading in about 19 seconds.

 

That's a pretty hefty imporvement, and I like how you can control how long the case page last for. Terrific improvements. Thanks for the heads up.

You've been around the block so know there is always a downside to everything. The page cache also keep the traditionally dynamic portions cached (like specials, featured products, best sellers, etc.). The only thing left to generate on each page request is the customer or guests cart. Also, once they register or log in the cache system turns itself off (for safety). It's only active for guests not logged in.

 

I figure if they log in they should get the full work of the server :)

 

Excellent - thanks a lot  :D

 

I'm looking forward to this thread developing to the same high standard.

(I'm very new to osC so can't contribute much.)

 

Dave.

Stay tuned...there's more to come. The next steps are:

1. Add popular contributions (discount coupons, featured, specials, etc)

2. Optimize again

3. Search Engine Optmization ala Chemo style

 

As a side note to #3: it's going to be like the "archive" feature of vBulletin discussion forum software. It will go beyond all_products and take SEO / sitemaps to another level for osCommerce. Enough of me blowing my own horn...back to coding :)

Share this post


Link to post
Share on other sites
Excellent - thanks a lot  :D

 

I'm looking forward to this thread developing to the same high standard.

(I'm very new to osC so can't contribute much.)

 

Dave.

Almost forgot...you can also define a longer period on a per page basis from the admin control panel setting.

 

For instance, the default code at the top of each page looks like this:

require(DIR_WS_CLASSES . 'page_cache.php');
$page_cache = new page_cache($cart_cache);
$page_cache->cache_this_page();

 

Change it to something like this:

require(DIR_WS_CLASSES . 'page_cache.php');
$page_cache = new page_cache($cart_cache, 1440, false);
$page_cache->cache_this_page();

 

Here's the function and arguments

cache_this_page($cart_info, $cachelifetime=5, $debugmode=false)

 

So, for pages like all_products, printable_catalog, etc. where there is not much traffic other than search engine spiders I can set the cache lifetime much higher (or, lower).

 

I try to make the code as versatile as I can :)

Share this post


Link to post
Share on other sites
Almost forgot...you can also define a longer period on a per page basis from the admin control panel setting.

 

For instance,  the default code at the top of each page looks like this:

require(DIR_WS_CLASSES . 'page_cache.php');
$page_cache = new page_cache($cart_cache);
$page_cache->cache_this_page();

 

Change it to something like this:

require(DIR_WS_CLASSES . 'page_cache.php');
$page_cache = new page_cache($cart_cache, 1440, false);
$page_cache->cache_this_page();

 

Here's the function and arguments

cache_this_page($cart_info, $cachelifetime=5, $debugmode=false)

 

So, for pages like all_products, printable_catalog, etc. where there is not much traffic other than search engine spiders I can set the cache lifetime much higher (or, lower).

 

I try to make the code as versatile as I can :)

 

 

Hey Chemo,

 

I am installing the m3 tax class for ms2 contribution, but hit a snag. in step3 second part is says replace tep_get_tax_description() with this code, but I don't have a function for teg_get_tax_description. I am using 2.2 ms 2 (latest download from oscommerce site)..any ideas?

 

Thanks!

RW


A man who works with his hands is a laborer

A man who works with his hands and his brain is a craftsman

But a man who works with his hands and his brain and his heart is an artist. - Charles Dickens

Share this post


Link to post
Share on other sites
Hey Chemo,

 

I am installing the m3 tax class for ms2 contribution, but hit a snag. in step3 second part is says replace tep_get_tax_description() with this code, but I don't have a function for teg_get_tax_description.  I am using 2.2 ms 2 (latest download from oscommerce site)..any ideas?

 

Thanks!

RW

The method tep_get_tax_rate() is located in includes/functions/general.php and was a typo. I've corrected it in the latest install (I think).

 

Check on my dev server for lastest files and pre-releases: osCommerce contritutions on my server

 

Also, you can go right to the install file here: MS3 Tax Class for MS2

Share this post


Link to post
Share on other sites

Before you move on, I'd like to ask a quick question about the page cashe.

 

If you have this enabled, won't all of your guests have the same exact session ID? That seems to be the case.


-------------------------------------------------------------------------------------------------------------------------

NOTE: As of Oct 2006, I'm not as active in this forum as I used to be, but I still work with osC quite a bit.

If you have a question about any of my posts here, your best bet is to contact me though either Email or PM in my profile, and I'll be happy to help.

Share this post


Link to post
Share on other sites

That may be the case if your store has the session id's appended to each URL. However, most do not and only use them in the URL when going from / to SSL / NONSSL.

 

It hasn't been problem on my sites but that is something to report and should be easily fixed.

Share this post


Link to post
Share on other sites

Not sure what you mean.

 

The sid will be attached to the URL if cookies are not enabled in the customer's browser, and 'force cookie' use is not set to true.

 

Since IE is now being distributed with cookies NOT enabled, I would think that this would actually represent the majority of users very soon.

 

And the session is not only used when going form SSL to nonSSL, but also what you have in your cart. Not to mention that if one person purchases using that session, and enters their details to create an account, and then another person comes along and uses that session, they will have access to all of the first person's account details.

 

That could be a very serious issue.


-------------------------------------------------------------------------------------------------------------------------

NOTE: As of Oct 2006, I'm not as active in this forum as I used to be, but I still work with osC quite a bit.

If you have a question about any of my posts here, your best bet is to contact me though either Email or PM in my profile, and I'll be happy to help.

Share this post


Link to post
Share on other sites

Another point recently brought to my attention is that if a search engine parses that cashed page, they will also get that very same session id. And the last thing you want to do is have search engine links with session ids in them.


-------------------------------------------------------------------------------------------------------------------------

NOTE: As of Oct 2006, I'm not as active in this forum as I used to be, but I still work with osC quite a bit.

If you have a question about any of my posts here, your best bet is to contact me though either Email or PM in my profile, and I'll be happy to help.

Share this post


Link to post
Share on other sites
The method tep_get_tax_rate() is located in includes/functions/general.php and was a typo.  I've corrected it in the latest install (I think).

 

Check on my dev server for lastest files and pre-releases: osCommerce contritutions on my server

 

Also, you can go right to the install file here: MS3 Tax Class for MS2

 

 

Heya, thanks for the quick reply.

I went to your server and dl the v1.1 for the m3 tax class for oscommerce.. however in the install instructions it still says:

STEP 3 - Edit includes/functions/general.php

REPLACE tep_get_tax_rate() it with this code:

function tep_get_tax_rate($class_id, $country_id = -1, $zone_id = -1) {

global $customer_zone_id, $customer_country_id, $osC_Tax;

return $osC_Tax->getTaxRate($class_id, $country_id, $zone_id);

}

 

REPLACE tep_get_tax_description() it with this code:

function tep_get_tax_description($class_id, $country_id, $zone_id) {

global $osC_Tax;

return $osC_Tax->getTaxRateDescription($class_id, $country_id, $zone_id);

}

 

I have done the 1st one (tep_get_tax_rate), but I don't have tep_get_tax_description in my general.php file in the catalog/includes/functions folder.. any ideas? below is a copy of my general.php file:

 

<?php

/*

$Id: general.php,v 1.160 2003/07/12 08:32:47 hpdl Exp $

++++ modified for USPS Methods 2.5 08/02/03 by Brad Waite and Fritz Clapp ++++

osCommerce, Open Source E-Commerce Solutions

http://www.oscommerce.com

 

Copyright © 2003 osCommerce

 

Released under the GNU General Public License

*/

 

 

////

// Redirect to another page or site

function tep_redirect($url) {

global $logger;

 

header('Location: ' . $url);

 

if (STORE_PAGE_PARSE_TIME == 'true') {

if (!is_object($logger)) $logger = new logger;

$logger->timer_stop();

}

 

exit;

}

 

////

// Parse the data used in the html tags to ensure the tags will not break

function tep_parse_input_field_data($data, $parse) {

return strtr(trim($data), $parse);

}

 

function tep_output_string($string, $translate = false, $protected = false) {

if ($protected == true) {

return htmlspecialchars($string);

} else {

if ($translate == false) {

return tep_parse_input_field_data($string, array('"' => '"'));

} else {

return tep_parse_input_field_data($string, $translate);

}

}

}

 

function tep_output_string_protected($string) {

return tep_output_string($string, false, true);

}

 

function tep_sanitize_string($string) {

$string = ereg_replace(' +', ' ', $string);

 

return preg_replace("/[<>]/", '_', $string);

}

 

function tep_customers_name($customers_id) {

$customers = tep_db_query("select customers_firstname, customers_lastname from " . TABLE_CUSTOMERS . " where customers_id = '" . (int)$customers_id . "'");

$customers_values = tep_db_fetch_array($customers);

 

return $customers_values['customers_firstname'] . ' ' . $customers_values['customers_lastname'];

}

 

function tep_get_path($current_category_id = '') {

global $cPath_array;

 

if ($current_category_id == '') {

$cPath_new = implode('_', $cPath_array);

} else {

if (sizeof($cPath_array) == 0) {

$cPath_new = $current_category_id;

} else {

$cPath_new = '';

$last_category_query = tep_db_query("select parent_id from " . TABLE_CATEGORIES . " where categories_id = '" . (int)$cPath_array[(sizeof($cPath_array)-1)] . "'");

$last_category = tep_db_fetch_array($last_category_query);

 

$current_category_query = tep_db_query("select parent_id from " . TABLE_CATEGORIES . " where categories_id = '" . (int)$current_category_id . "'");

$current_category = tep_db_fetch_array($current_category_query);

 

if ($last_category['parent_id'] == $current_category['parent_id']) {

for ($i = 0, $n = sizeof($cPath_array) - 1; $i < $n; $i++) {

$cPath_new .= '_' . $cPath_array[$i];

}

} else {

for ($i = 0, $n = sizeof($cPath_array); $i < $n; $i++) {

$cPath_new .= '_' . $cPath_array[$i];

}

}

 

$cPath_new .= '_' . $current_category_id;

 

if (substr($cPath_new, 0, 1) == '_') {

$cPath_new = substr($cPath_new, 1);

}

}

}

 

return 'cPath=' . $cPath_new;

}

 

function tep_get_all_get_params($exclude_array = '') {

global $HTTP_GET_VARS;

 

if ($exclude_array == '') $exclude_array = array();

 

$get_url = '';

 

reset($HTTP_GET_VARS);

while (list($key, $value) = each($HTTP_GET_VARS)) {

if (($key != tep_session_name()) && ($key != 'error') && (!in_array($key, $exclude_array))) $get_url .= $key . '=' . $value . '&';

}

 

return $get_url;

}

 

function tep_date_long($raw_date) {

if ( ($raw_date == '0000-00-00 00:00:00') || ($raw_date == '') ) return false;

 

$year = (int)substr($raw_date, 0, 4);

$month = (int)substr($raw_date, 5, 2);

$day = (int)substr($raw_date, 8, 2);

$hour = (int)substr($raw_date, 11, 2);

$minute = (int)substr($raw_date, 14, 2);

$second = (int)substr($raw_date, 17, 2);

 

return strftime(DATE_FORMAT_LONG, mktime($hour, $minute, $second, $month, $day, $year));

}

 

////

// Output a raw date string in the selected locale date format

// $raw_date needs to be in this format: YYYY-MM-DD HH:MM:SS

// NOTE: Includes a workaround for dates before 01/01/1970 that fail on windows servers

function tep_date_short($raw_date) {

if ( ($raw_date == '0000-00-00 00:00:00') || ($raw_date == '') ) return false;

 

$year = substr($raw_date, 0, 4);

$month = (int)substr($raw_date, 5, 2);

$day = (int)substr($raw_date, 8, 2);

$hour = (int)substr($raw_date, 11, 2);

$minute = (int)substr($raw_date, 14, 2);

$second = (int)substr($raw_date, 17, 2);

 

if (@date('Y', mktime($hour, $minute, $second, $month, $day, $year)) == $year) {

return date(DATE_FORMAT, mktime($hour, $minute, $second, $month, $day, $year));

} else {

return ereg_replace('2037' . '$', $year, date(DATE_FORMAT, mktime($hour, $minute, $second, $month, $day, 2037)));

}

 

}

 

function tep_datetime_short($raw_datetime) {

if ( ($raw_datetime == '0000-00-00 00:00:00') || ($raw_datetime == '') ) return false;

 

$year = (int)substr($raw_datetime, 0, 4);

$month = (int)substr($raw_datetime, 5, 2);

$day = (int)substr($raw_datetime, 8, 2);

$hour = (int)substr($raw_datetime, 11, 2);

$minute = (int)substr($raw_datetime, 14, 2);

$second = (int)substr($raw_datetime, 17, 2);

 

return strftime(DATE_TIME_FORMAT, mktime($hour, $minute, $second, $month, $day, $year));

}

 

function tep_get_category_tree($parent_id = '0', $spacing = '', $exclude = '', $category_tree_array = '', $include_itself = false) {

global $languages_id;

 

if (!is_array($category_tree_array)) $category_tree_array = array();

if ( (sizeof($category_tree_array) < 1) && ($exclude != '0') ) $category_tree_array[] = array('id' => '0', 'text' => TEXT_TOP);

 

if ($include_itself) {

$category_query = tep_db_query("select cd.categories_name from " . TABLE_CATEGORIES_DESCRIPTION . " cd where cd.language_id = '" . (int)$languages_id . "' and cd.categories_id = '" . (int)$parent_id . "'");

$category = tep_db_fetch_array($category_query);

$category_tree_array[] = array('id' => $parent_id, 'text' => $category['categories_name']);

}

 

$categories_query = tep_db_query("select c.categories_id, cd.categories_name, c.parent_id from " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where c.categories_id = cd.categories_id and cd.language_id = '" . (int)$languages_id . "' and c.parent_id = '" . (int)$parent_id . "' order by c.sort_order, cd.categories_name");

while ($categories = tep_db_fetch_array($categories_query)) {

if ($exclude != $categories['categories_id']) $category_tree_array[] = array('id' => $categories['categories_id'], 'text' => $spacing . $categories['categories_name']);

$category_tree_array = tep_get_category_tree($categories['categories_id'], $spacing . '   ', $exclude, $category_tree_array);

}

 

return $category_tree_array;

}

 

function tep_draw_products_pull_down($name, $parameters = '', $exclude = '') {

global $currencies, $languages_id;

 

if ($exclude == '') {

$exclude = array();

}

 

$select_string = '<select name="' . $name . '"';

 

if ($parameters) {

$select_string .= ' ' . $parameters;

}

 

$select_string .= '>';

 

$products_query = tep_db_query("select p.products_id, pd.products_name, p.products_price from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_DESCRIPTION . " pd where p.products_id = pd.products_id and pd.language_id = '" . (int)$languages_id . "' order by products_name");

while ($products = tep_db_fetch_array($products_query)) {

if (!in_array($products['products_id'], $exclude)) {

$select_string .= '<option value="' . $products['products_id'] . '">' . $products['products_name'] . ' (' . $currencies->format($products['products_price']) . ')</option>';

}

}

 

$select_string .= '</select>';

 

return $select_string;

}

 

function tep_options_name($options_id) {

global $languages_id;

 

$options = tep_db_query("select products_options_name from " . TABLE_PRODUCTS_OPTIONS . " where products_options_id = '" . (int)$options_id . "' and language_id = '" . (int)$languages_id . "'");

$options_values = tep_db_fetch_array($options);

 

return $options_values['products_options_name'];

}

 

function tep_values_name($values_id) {

global $languages_id;

 

$values = tep_db_query("select products_options_values_name from " . TABLE_PRODUCTS_OPTIONS_VALUES . " where products_options_values_id = '" . (int)$values_id . "' and language_id = '" . (int)$languages_id . "'");

$values_values = tep_db_fetch_array($values);

 

return $values_values['products_options_values_name'];

}

 

function tep_info_image($image, $alt, $width = '', $height = '') {

if (tep_not_null($image) && (file_exists(DIR_FS_CATALOG_IMAGES . $image)) ) {

$image = tep_image(DIR_WS_CATALOG_IMAGES . $image, $alt, $width, $height);

} else {

$image = TEXT_IMAGE_NONEXISTENT;

}

 

return $image;

}

 

function tep_break_string($string, $len, $break_char = '-') {

$l = 0;

$output = '';

for ($i=0, $n=strlen($string); $i<$n; $i++) {

$char = substr($string, $i, 1);

if ($char != ' ') {

$l++;

} else {

$l = 0;

}

if ($l > $len) {

$l = 1;

$output .= $break_char;

}

$output .= $char;

}

 

return $output;

}

 

function tep_get_country_name($country_id) {

$country_query = tep_db_query("select countries_name from " . TABLE_COUNTRIES . " where countries_id = '" . (int)$country_id . "'");

 

if (!tep_db_num_rows($country_query)) {

return $country_id;

} else {

$country = tep_db_fetch_array($country_query);

return $country['countries_name'];

}

}

 

function tep_get_zone_name($country_id, $zone_id, $default_zone) {

$zone_query = tep_db_query("select zone_name from " . TABLE_ZONES . " where zone_country_id = '" . (int)$country_id . "' and zone_id = '" . (int)$zone_id . "'");

if (tep_db_num_rows($zone_query)) {

$zone = tep_db_fetch_array($zone_query);

return $zone['zone_name'];

} else {

return $default_zone;

}

}

 

function tep_not_null($value) {

if (is_array($value)) {

if (sizeof($value) > 0) {

return true;

} else {

return false;

}

} else {

if ( (is_string($value) || is_int($value)) && ($value != '') && ($value != 'NULL') && (strlen(trim($value)) > 0)) {

return true;

} else {

return false;

}

}

}

 

function tep_browser_detect($component) {

global $HTTP_USER_AGENT;

 

return stristr($HTTP_USER_AGENT, $component);

}

 

function tep_tax_classes_pull_down($parameters, $selected = '') {

$select_string = '<select ' . $parameters . '>';

$classes_query = tep_db_query("select tax_class_id, tax_class_title from " . TABLE_TAX_CLASS . " order by tax_class_title");

while ($classes = tep_db_fetch_array($classes_query)) {

$select_string .= '<option value="' . $classes['tax_class_id'] . '"';

if ($selected == $classes['tax_class_id']) $select_string .= ' SELECTED';

$select_string .= '>' . $classes['tax_class_title'] . '</option>';

}

$select_string .= '</select>';

 

return $select_string;

}

 

function tep_geo_zones_pull_down($parameters, $selected = '') {

$select_string = '<select ' . $parameters . '>';

$zones_query = tep_db_query("select geo_zone_id, geo_zone_name from " . TABLE_GEO_ZONES . " order by geo_zone_name");

while ($zones = tep_db_fetch_array($zones_query)) {

$select_string .= '<option value="' . $zones['geo_zone_id'] . '"';

if ($selected == $zones['geo_zone_id']) $select_string .= ' SELECTED';

$select_string .= '>' . $zones['geo_zone_name'] . '</option>';

}

$select_string .= '</select>';

 

return $select_string;

}

 

function tep_get_geo_zone_name($geo_zone_id) {

$zones_query = tep_db_query("select geo_zone_name from " . TABLE_GEO_ZONES . " where geo_zone_id = '" . (int)$geo_zone_id . "'");

 

if (!tep_db_num_rows($zones_query)) {

$geo_zone_name = $geo_zone_id;

} else {

$zones = tep_db_fetch_array($zones_query);

$geo_zone_name = $zones['geo_zone_name'];

}

 

return $geo_zone_name;

}

 

function tep_address_format($address_format_id, $address, $html, $boln, $eoln) {

$address_format_query = tep_db_query("select address_format as format from " . TABLE_ADDRESS_FORMAT . " where address_format_id = '" . (int)$address_format_id . "'");

$address_format = tep_db_fetch_array($address_format_query);

 

$company = tep_output_string_protected($address['company']);

if (isset($address['firstname']) && tep_not_null($address['firstname'])) {

$firstname = tep_output_string_protected($address['firstname']);

$lastname = tep_output_string_protected($address['lastname']);

} elseif (isset($address['name']) && tep_not_null($address['name'])) {

$firstname = tep_output_string_protected($address['name']);

$lastname = '';

} else {

$firstname = '';

$lastname = '';

}

$street = tep_output_string_protected($address['street_address']);

$suburb = tep_output_string_protected($address['suburb']);

$city = tep_output_string_protected($address['city']);

$state = tep_output_string_protected($address['state']);

if (isset($address['country_id']) && tep_not_null($address['country_id'])) {

$country = tep_get_country_name($address['country_id']);

 

if (isset($address['zone_id']) && tep_not_null($address['zone_id'])) {

$state = tep_get_zone_code($address['country_id'], $address['zone_id'], $state);

}

} elseif (isset($address['country']) && tep_not_null($address['country'])) {

$country = tep_output_string_protected($address['country']);

} else {

$country = '';

}

$postcode = tep_output_string_protected($address['postcode']);

$zip = $postcode;

 

if ($html) {

// HTML Mode

$HR = '<hr>';

$hr = '<hr>';

if ( ($boln == '') && ($eoln == "\n") ) { // Values not specified, use rational defaults

$CR = '<br>';

$cr = '<br>';

$eoln = $cr;

} else { // Use values supplied

$CR = $eoln . $boln;

$cr = $CR;

}

} else {

// Text Mode

$CR = $eoln;

$cr = $CR;

$HR = '----------------------------------------';

$hr = '----------------------------------------';

}

 

$statecomma = '';

$streets = $street;

if ($suburb != '') $streets = $street . $cr . $suburb;

if ($country == '') $country = tep_output_string_protected($address['country']);

if ($state != '') $statecomma = $state . ', ';

 

$fmt = $address_format['format'];

eval("\$address = \"$fmt\";");

 

if ( (ACCOUNT_COMPANY == 'true') && (tep_not_null($company)) ) {

$address = $company . $cr . $address;

}

 

return $address;

}

 

////////////////////////////////////////////////////////////////////////////////////////////////

//

// Function : tep_get_zone_code

//

// Arguments : country country code string

// zone state/province zone_id

// def_state default string if zone==0

//

// Return : state_prov_code state/province code

//

// Description : Function to retrieve the state/province code (as in FL for Florida etc)

//

////////////////////////////////////////////////////////////////////////////////////////////////

function tep_get_zone_code($country, $zone, $def_state) {

 

$state_prov_query = tep_db_query("select zone_code from " . TABLE_ZONES . " where zone_country_id = '" . (int)$country . "' and zone_id = '" . (int)$zone . "'");

 

if (!tep_db_num_rows($state_prov_query)) {

$state_prov_code = $def_state;

}

else {

$state_prov_values = tep_db_fetch_array($state_prov_query);

$state_prov_code = $state_prov_values['zone_code'];

}

 

return $state_prov_code;

}

 

function tep_get_uprid($prid, $params) {

$uprid = $prid;

if ( (is_array($params)) && (!strstr($prid, '{')) ) {

while (list($option, $value) = each($params)) {

$uprid = $uprid . '{' . $option . '}' . $value;

}

}

 

return $uprid;

}

 

function tep_get_prid($uprid) {

$pieces = explode('{', $uprid);

 

return $pieces[0];

}

 

function tep_get_languages() {

$languages_query = tep_db_query("select languages_id, name, code, image, directory from " . TABLE_LANGUAGES . " order by sort_order");

while ($languages = tep_db_fetch_array($languages_query)) {

$languages_array[] = array('id' => $languages['languages_id'],

'name' => $languages['name'],

'code' => $languages['code'],

'image' => $languages['image'],

'directory' => $languages['directory']);

}

 

return $languages_array;

}

 

function tep_get_category_name($category_id, $language_id) {

$category_query = tep_db_query("select categories_name from " . TABLE_CATEGORIES_DESCRIPTION . " where categories_id = '" . (int)$category_id . "' and language_id = '" . (int)$language_id . "'");

$category = tep_db_fetch_array($category_query);

 

return $category['categories_name'];

}

 

function tep_get_orders_status_name($orders_status_id, $language_id = '') {

global $languages_id;

 

if (!$language_id) $language_id = $languages_id;

$orders_status_query = tep_db_query("select orders_status_name from " . TABLE_ORDERS_STATUS . " where orders_status_id = '" . (int)$orders_status_id . "' and language_id = '" . (int)$language_id . "'");

$orders_status = tep_db_fetch_array($orders_status_query);

 

return $orders_status['orders_status_name'];

}

 

function tep_get_orders_status() {

global $languages_id;

 

$orders_status_array = array();

$orders_status_query = tep_db_query("select orders_status_id, orders_status_name from " . TABLE_ORDERS_STATUS . " where language_id = '" . (int)$languages_id . "' order by orders_status_id");

while ($orders_status = tep_db_fetch_array($orders_status_query)) {

$orders_status_array[] = array('id' => $orders_status['orders_status_id'],

'text' => $orders_status['orders_status_name']);

}

 

return $orders_status_array;

}

 

function tep_get_products_name($product_id, $language_id = 0) {

global $languages_id;

 

if ($language_id == 0) $language_id = $languages_id;

$product_query = tep_db_query("select products_name from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$product_id . "' and language_id = '" . (int)$language_id . "'");

$product = tep_db_fetch_array($product_query);

 

return $product['products_name'];

}

 

function tep_get_products_description($product_id, $language_id) {

$product_query = tep_db_query("select products_description from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$product_id . "' and language_id = '" . (int)$language_id . "'");

$product = tep_db_fetch_array($product_query);

 

return $product['products_description'];

}

 

// BoF Header Tag Controller

function tep_get_products_head_title_tag($product_id, $language_id) {

$product_query = tep_db_query("select products_head_title_tag from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$product_id . "' and language_id = '" . (int)$language_id . "'");

$product = tep_db_fetch_array($product_query);

 

return $product['products_head_title_tag'];

}

 

function tep_get_products_head_desc_tag($product_id, $language_id) {

$product_query = tep_db_query("select products_head_desc_tag from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$product_id . "' and language_id = '" . (int)$language_id . "'");

$product = tep_db_fetch_array($product_query);

 

return $product['products_head_desc_tag'];

}

 

function tep_get_products_head_keywords_tag($product_id, $language_id) {

$product_query = tep_db_query("select products_head_keywords_tag from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$product_id . "' and language_id = '" . (int)$language_id . "'");

$product = tep_db_fetch_array($product_query);

 

return $product['products_head_keywords_tag'];

}

// EoF Header Tag Controller

 

 

function tep_get_products_url($product_id, $language_id) {

$product_query = tep_db_query("select products_url from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$product_id . "' and language_id = '" . (int)$language_id . "'");

$product = tep_db_fetch_array($product_query);

 

return $product['products_url'];

}

 

////

// Return the manufacturers URL in the needed language

// TABLES: manufacturers_info

function tep_get_manufacturer_url($manufacturer_id, $language_id) {

$manufacturer_query = tep_db_query("select manufacturers_url from " . TABLE_MANUFACTURERS_INFO . " where manufacturers_id = '" . (int)$manufacturer_id . "' and languages_id = '" . (int)$language_id . "'");

$manufacturer = tep_db_fetch_array($manufacturer_query);

 

return $manufacturer['manufacturers_url'];

}

 

////

// Wrapper for class_exists() function

// This function is not available in all PHP versions so we test it before using it.

function tep_class_exists($class_name) {

if (function_exists('class_exists')) {

return class_exists($class_name);

} else {

return true;

}

}

 

////

// Count how many products exist in a category

// TABLES: products, products_to_categories, categories

function tep_products_in_category_count($categories_id, $include_deactivated = false) {

$products_count = 0;

 

if ($include_deactivated) {

$products_query = tep_db_query("select count(*) as total from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c where p.products_id = p2c.products_id and p2c.categories_id = '" . (int)$categories_id . "'");

} else {

$products_query = tep_db_query("select count(*) as total from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c where p.products_id = p2c.products_id and p.products_status = '1' and p2c.categories_id = '" . (int)$categories_id . "'");

}

 

$products = tep_db_fetch_array($products_query);

 

$products_count += $products['total'];

 

$childs_query = tep_db_query("select categories_id from " . TABLE_CATEGORIES . " where parent_id = '" . (int)$categories_id . "'");

if (tep_db_num_rows($childs_query)) {

while ($childs = tep_db_fetch_array($childs_query)) {

$products_count += tep_products_in_category_count($childs['categories_id'], $include_deactivated);

}

}

 

return $products_count;

}

 

////

// Count how many subcategories exist in a category

// TABLES: categories

function tep_childs_in_category_count($categories_id) {

$categories_count = 0;

 

$categories_query = tep_db_query("select categories_id from " . TABLE_CATEGORIES . " where parent_id = '" . (int)$categories_id . "'");

while ($categories = tep_db_fetch_array($categories_query)) {

$categories_count++;

$categories_count += tep_childs_in_category_count($categories['categories_id']);

}

 

return $categories_count;

}

 

////

// Returns an array with countries

// TABLES: countries

function tep_get_countries($default = '') {

$countries_array = array();

if ($default) {

$countries_array[] = array('id' => '',

'text' => $default);

}

$countries_query = tep_db_query("select countries_id, countries_name from " . TABLE_COUNTRIES . " order by countries_name");

while ($countries = tep_db_fetch_array($countries_query)) {

$countries_array[] = array('id' => $countries['countries_id'],

'text' => $countries['countries_name']);

}

 

return $countries_array;

}

 

////

// return an array with country zones

function tep_get_country_zones($country_id) {

$zones_array = array();

$zones_query = tep_db_query("select zone_id, zone_name from " . TABLE_ZONES . " where zone_country_id = '" . (int)$country_id . "' order by zone_name");

while ($zones = tep_db_fetch_array($zones_query)) {

$zones_array[] = array('id' => $zones['zone_id'],

'text' => $zones['zone_name']);

}

 

return $zones_array;

}

 

function tep_prepare_country_zones_pull_down($country_id = '') {

// preset the width of the drop-down for Netscape

$pre = '';

if ( (!tep_browser_detect('MSIE')) && (tep_browser_detect('Mozilla/4')) ) {

for ($i=0; $i<45; $i++) $pre .= ' ';

}

 

$zones = tep_get_country_zones($country_id);

 

if (sizeof($zones) > 0) {

$zones_select = array(array('id' => '', 'text' => PLEASE_SELECT));

$zones = array_merge($zones_select, $zones);

} else {

$zones = array(array('id' => '', 'text' => TYPE_BELOW));

// create dummy options for Netscape to preset the height of the drop-down

if ( (!tep_browser_detect('MSIE')) && (tep_browser_detect('Mozilla/4')) ) {

for ($i=0; $i<9; $i++) {

$zones[] = array('id' => '', 'text' => $pre);

}

}

}

 

return $zones;

}

 

////

// Get list of address_format_id's

function tep_get_address_formats() {

$address_format_query = tep_db_query("select address_format_id from " . TABLE_ADDRESS_FORMAT . " order by address_format_id");

$address_format_array = array();

while ($address_format_values = tep_db_fetch_array($address_format_query)) {

$address_format_array[] = array('id' => $address_format_values['address_format_id'],

'text' => $address_format_values['address_format_id']);

}

return $address_format_array;

}

 

////

// Alias function for Store configuration values in the Administration Tool

function tep_cfg_pull_down_country_list($country_id) {

return tep_draw_pull_down_menu('configuration_value', tep_get_countries(), $country_id);

}

 

function tep_cfg_pull_down_zone_list($zone_id) {

return tep_draw_pull_down_menu('configuration_value', tep_get_country_zones(STORE_COUNTRY), $zone_id);

}

 

function tep_cfg_pull_down_tax_classes($tax_class_id, $key = '') {

$name = (($key) ? 'configuration[' . $key . ']' : 'configuration_value');

 

$tax_class_array = array(array('id' => '0', 'text' => TEXT_NONE));

$tax_class_query = tep_db_query("select tax_class_id, tax_class_title from " . TABLE_TAX_CLASS . " order by tax_class_title");

while ($tax_class = tep_db_fetch_array($tax_class_query)) {

$tax_class_array[] = array('id' => $tax_class['tax_class_id'],

'text' => $tax_class['tax_class_title']);

}

 

return tep_draw_pull_down_menu($name, $tax_class_array, $tax_class_id);

}

 

////

// Function to read in text area in admin

function tep_cfg_textarea($text) {

return tep_draw_textarea_field('configuration_value', false, 35, 5, $text);

}

 

function tep_cfg_get_zone_name($zone_id) {

$zone_query = tep_db_query("select zone_name from " . TABLE_ZONES . " where zone_id = '" . (int)$zone_id . "'");

 

if (!tep_db_num_rows($zone_query)) {

return $zone_id;

} else {

$zone = tep_db_fetch_array($zone_query);

return $zone['zone_name'];

}

}

 

////

// Sets the status of a banner

function tep_set_banner_status($banners_id, $status) {

if ($status == '1') {

return tep_db_query("update " . TABLE_BANNERS . " set status = '1', expires_impressions = NULL, expires_date = NULL, date_status_change = NULL where banners_id = '" . $banners_id . "'");

} elseif ($status == '0') {

return tep_db_query("update " . TABLE_BANNERS . " set status = '0', date_status_change = now() where banners_id = '" . $banners_id . "'");

} else {

return -1;

}

}

 

////

// Sets the sort order of a product

function tep_set_product_sort_order($products_id, $sort_order) {

return tep_db_query("update " . TABLE_PRODUCTS . " set products_sort_order = '" . $sort_order . "', products_last_modified = now() where products_id = '" . (int)$products_id . "'");

}

 

 

////

// Sets the status of a product

function tep_set_product_status($products_id, $status) {

if ($status == '1') {

return tep_db_query("update " . TABLE_PRODUCTS . " set products_status = '1', products_last_modified = now() where products_id = '" . (int)$products_id . "'");

} elseif ($status == '0') {

return tep_db_query("update " . TABLE_PRODUCTS . " set products_status = '0', products_last_modified = now() where products_id = '" . (int)$products_id . "'");

} else {

return -1;

}

}

 

////

// Sets the status of a product on special

function tep_set_specials_status($specials_id, $status) {

if ($status == '1') {

return tep_db_query("update " . TABLE_SPECIALS . " set status = '1', expires_date = NULL, date_status_change = NULL where specials_id = '" . (int)$specials_id . "'");

} elseif ($status == '0') {

return tep_db_query("update " . TABLE_SPECIALS . " set status = '0', date_status_change = now() where specials_id = '" . (int)$specials_id . "'");

} else {

return -1;

}

}

 

////

// Sets timeout for the current script.

// Cant be used in safe mode.

function tep_set_time_limit($limit) {

if (!get_cfg_var('safe_mode')) {

set_time_limit($limit);

}

}

 

////

// Alias function for Store configuration values in the Administration Tool

function tep_cfg_select_option($select_array, $key_value, $key = '') {

$string = '';

 

for ($i=0, $n=sizeof($select_array); $i<$n; $i++) {

$name = ((tep_not_null($key)) ? 'configuration[' . $key . ']' : 'configuration_value');

 

$string .= '<br><input type="radio" name="' . $name . '" value="' . $select_array[$i] . '"';

 

if ($key_value == $select_array[$i]) $string .= ' CHECKED';

 

$string .= '> ' . $select_array[$i];

}

 

return $string;

}

 

////

// Alias function for module configuration keys

function tep_mod_select_option($select_array, $key_name, $key_value) {

reset($select_array);

while (list($key, $value) = each($select_array)) {

if (is_int($key)) $key = $value;

$string .= '<br><input type="radio" name="configuration[' . $key_name . ']" value="' . $key . '"';

if ($key_value == $key) $string .= ' CHECKED';

$string .= '> ' . $value;

}

 

return $string;

}

// USPS Methods 2.5

// Alias function for Store configuration values in the Administration Tool

function tep_cfg_select_multioption($select_array, $key_value, $key = '') {

for ($i=0; $i<sizeof($select_array); $i++) {

$name = (($key) ? 'configuration[' . $key . '][]' : 'configuration_value');

$string .= '<br><input type="checkbox" name="' . $name . '" value="' . $select_array[$i] . '"';

$key_values = explode( ", ", $key_value);

if ( in_array($select_array[$i], $key_values) ) $string .= ' CHECKED';

$string .= '> ' . $select_array[$i];

}

$string .= '<input type="hidden" name="' . $name . '" value="--none--">';

return $string;

}

////

// Retreive server information

function tep_get_system_information() {

global $HTTP_SERVER_VARS;

 

$db_query = tep_db_query("select now() as datetime");

$db = tep_db_fetch_array($db_query);

 

list($system, $host, $kernel) = preg_split('/[\s,]+/', @exec('uname -a'), 5);

 

return array('date' => tep_datetime_short(date('Y-m-d H:i:s')),

'system' => $system,

'kernel' => $kernel,

'host' => $host,

'ip' => gethostbyname($host),

'uptime' => @exec('uptime'),

'http_server' => $HTTP_SERVER_VARS['SERVER_SOFTWARE'],

'php' => PHP_VERSION,

'zend' => (function_exists('zend_version') ? zend_version() : ''),

'db_server' => DB_SERVER,

'db_ip' => gethostbyname(DB_SERVER),

'db_version' => 'MySQL ' . (function_exists('mysql_get_server_info') ? mysql_get_server_info() : ''),

'db_date' => tep_datetime_short($db['datetime']));

}

 

function tep_generate_category_path($id, $from = 'category', $categories_array = '', $index = 0) {

global $languages_id;

 

if (!is_array($categories_array)) $categories_array = array();

 

if ($from == 'product') {

$categories_query = tep_db_query("select categories_id from " . TABLE_PRODUCTS_TO_CATEGORIES . " where products_id = '" . (int)$id . "'");

while ($categories = tep_db_fetch_array($categories_query)) {

if ($categories['categories_id'] == '0') {

$categories_array[$index][] = array('id' => '0', 'text' => TEXT_TOP);

} else {

$category_query = tep_db_query("select cd.categories_name, c.parent_id from " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where c.categories_id = '" . (int)$categories['categories_id'] . "' and c.categories_id = cd.categories_id and cd.language_id = '" . (int)$languages_id . "'");

$category = tep_db_fetch_array($category_query);

$categories_array[$index][] = array('id' => $categories['categories_id'], 'text' => $category['categories_name']);

if ( (tep_not_null($category['parent_id'])) && ($category['parent_id'] != '0') ) $categories_array = tep_generate_category_path($category['parent_id'], 'category', $categories_array, $index);

$categories_array[$index] = array_reverse($categories_array[$index]);

}

$index++;

}

} elseif ($from == 'category') {

$category_query = tep_db_query("select cd.categories_name, c.parent_id from " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where c.categories_id = '" . (int)$id . "' and c.categories_id = cd.categories_id and cd.language_id = '" . (int)$languages_id . "'");

$category = tep_db_fetch_array($category_query);

$categories_array[$index][] = array('id' => $id, 'text' => $category['categories_name']);

if ( (tep_not_null($category['parent_id'])) && ($category['parent_id'] != '0') ) $categories_array = tep_generate_category_path($category['parent_id'], 'category', $categories_array, $index);

}

 

return $categories_array;

}

 

function tep_output_generated_category_path($id, $from = 'category') {

$calculated_category_path_string = '';

$calculated_category_path = tep_generate_category_path($id, $from);

for ($i=0, $n=sizeof($calculated_category_path); $i<$n; $i++) {

for ($j=0, $k=sizeof($calculated_category_path[$i]); $j<$k; $j++) {

$calculated_category_path_string .= $calculated_category_path[$i][$j]['text'] . ' > ';

}

$calculated_category_path_string = substr($calculated_category_path_string, 0, -16) . '<br>';

}

$calculated_category_path_string = substr($calculated_category_path_string, 0, -4);

 

if (strlen($calculated_category_path_string) < 1) $calculated_category_path_string = TEXT_TOP;

 

return $calculated_category_path_string;

}

 

function tep_get_generated_category_path_ids($id, $from = 'category') {

$calculated_category_path_string = '';

$calculated_category_path = tep_generate_category_path($id, $from);

for ($i=0, $n=sizeof($calculated_category_path); $i<$n; $i++) {

for ($j=0, $k=sizeof($calculated_category_path[$i]); $j<$k; $j++) {

$calculated_category_path_string .= $calculated_category_path[$i][$j]['id'] . '_';

}

$calculated_category_path_string = substr($calculated_category_path_string, 0, -1) . '<br>';

}

$calculated_category_path_string = substr($calculated_category_path_string, 0, -4);

 

if (strlen($calculated_category_path_string) < 1) $calculated_category_path_string = TEXT_TOP;

 

return $calculated_category_path_string;

}

 

function tep_remove_category($category_id) {

$category_image_query = tep_db_query("select categories_image from " . TABLE_CATEGORIES . " where categories_id = '" . (int)$category_id . "'");

$category_image = tep_db_fetch_array($category_image_query);

 

$duplicate_image_query = tep_db_query("select count(*) as total from " . TABLE_CATEGORIES . " where categories_image = '" . tep_db_input($category_image['categories_image']) . "'");

$duplicate_image = tep_db_fetch_array($duplicate_image_query);

 

if ($duplicate_image['total'] < 2) {

if (file_exists(DIR_FS_CATALOG_IMAGES . $category_image['categories_image'])) {

@unlink(DIR_FS_CATALOG_IMAGES . $category_image['categories_image']);

}

}

 

tep_db_query("delete from " . TABLE_CATEGORIES . " where categories_id = '" . (int)$category_id . "'");

tep_db_query("delete from " . TABLE_CATEGORIES_DESCRIPTION . " where categories_id = '" . (int)$category_id . "'");

tep_db_query("delete from " . TABLE_PRODUCTS_TO_CATEGORIES . " where categories_id = '" . (int)$category_id . "'");

 

if (USE_CACHE == 'true') {

tep_reset_cache_block('categories');

tep_reset_cache_block('also_purchased');

}

}

 

function tep_remove_product($product_id) {

$product_image_query = tep_db_query("select products_image from " . TABLE_PRODUCTS . " where products_id = '" . (int)$product_id . "'");

$product_image = tep_db_fetch_array($product_image_query);

 

$duplicate_image_query = tep_db_query("select count(*) as total from " . TABLE_PRODUCTS . " where products_image = '" . tep_db_input($product_image['products_image']) . "'");

$duplicate_image = tep_db_fetch_array($duplicate_image_query);

 

if ($duplicate_image['total'] < 2) {

if (file_exists(DIR_FS_CATALOG_IMAGES . $product_image['products_image'])) {

@unlink(DIR_FS_CATALOG_IMAGES . $product_image['products_image']);

}

}

 

tep_db_query("delete from " . TABLE_SPECIALS . " where products_id = '" . (int)$product_id . "'");

tep_db_query("delete from " . TABLE_PRODUCTS . " where products_id = '" . (int)$product_id . "'");

tep_db_query("delete from " . TABLE_PRODUCTS_TO_CATEGORIES . " where products_id = '" . (int)$product_id . "'");

tep_db_query("delete from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$product_id . "'");

tep_db_query("delete from " . TABLE_PRODUCTS_ATTRIBUTES . " where products_id = '" . (int)$product_id . "'");

tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where products_id = '" . (int)$product_id . "'");

tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where products_id = '" . (int)$product_id . "'");

 

$product_reviews_query = tep_db_query("select reviews_id from " . TABLE_REVIEWS . " where products_id = '" . (int)$product_id . "'");

while ($product_reviews = tep_db_fetch_array($product_reviews_query)) {

tep_db_query("delete from " . TABLE_REVIEWS_DESCRIPTION . " where reviews_id = '" . (int)$product_reviews['reviews_id'] . "'");

}

tep_db_query("delete from " . TABLE_REVIEWS . " where products_id = '" . (int)$product_id . "'");

 

if (USE_CACHE == 'true') {

tep_reset_cache_block('categories');

tep_reset_cache_block('also_purchased');

}

}

 

function tep_remove_order($order_id, $restock = false) {

if ($restock == 'on') {

$order_query = tep_db_query("select products_id, products_quantity from " . TABLE_ORDERS_PRODUCTS . " where orders_id = '" . (int)$order_id . "'");

while ($order = tep_db_fetch_array($order_query)) {

tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = products_quantity + " . $order['products_quantity'] . ", products_ordered = products_ordered - " . $order['products_quantity'] . " where products_id = '" . (int)$order['products_id'] . "'");

}

}

 

tep_db_query("delete from " . TABLE_ORDERS . " where orders_id = '" . (int)$order_id . "'");

tep_db_query("delete from " . TABLE_ORDERS_PRODUCTS . " where orders_id = '" . (int)$order_id . "'");

tep_db_query("delete from " . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . " where orders_id = '" . (int)$order_id . "'");

tep_db_query("delete from " . TABLE_ORDERS_STATUS_HISTORY . " where orders_id = '" . (int)$order_id . "'");

tep_db_query("delete from " . TABLE_ORDERS_TOTAL . " where orders_id = '" . (int)$order_id . "'");

}

 

function tep_reset_cache_block($cache_block) {

global $cache_blocks;

 

for ($i=0, $n=sizeof($cache_blocks); $i<$n; $i++) {

if ($cache_blocks[$i]['code'] == $cache_block) {

if ($cache_blocks[$i]['multiple']) {

if ($dir = @opendir(DIR_FS_CACHE)) {

while ($cache_file = readdir($dir)) {

$cached_file = $cache_blocks[$i]['file'];

$languages = tep_get_languages();

for ($j=0, $k=sizeof($languages); $j<$k; $j++) {

$cached_file_unlink = ereg_replace('-language', '-' . $languages[$j]['directory'], $cached_file);

if (ereg('^' . $cached_file_unlink, $cache_file)) {

@unlink(DIR_FS_CACHE . $cache_file);

}

}

}

closedir($dir);

}

} else {

$cached_file = $cache_blocks[$i]['file'];

$languages = tep_get_languages();

for ($i=0, $n=sizeof($languages); $i<$n; $i++) {

$cached_file = ereg_replace('-language', '-' . $languages[$i]['directory'], $cached_file);

@unlink(DIR_FS_CACHE . $cached_file);

}

}

break;

}

}

}

 

function tep_get_file_permissions($mode) {

// determine type

if ( ($mode & 0xC000) == 0xC000) { // unix domain socket

$type = 's';

} elseif ( ($mode & 0x4000) == 0x4000) { // directory

$type = 'd';

} elseif ( ($mode & 0xA000) == 0xA000) { // symbolic link

$type = 'l';

} elseif ( ($mode & 0x8000) == 0x8000) { // regular file

$type = '-';

} elseif ( ($mode & 0x6000) == 0x6000) { //bBlock special file

$type = 'b';

} elseif ( ($mode & 0x2000) == 0x2000) { // character special file

$type = 'c';

} elseif ( ($mode & 0x1000) == 0x1000) { // named pipe

$type = 'p';

} else { // unknown

$type = '?';

}

 

// determine permissions

$owner['read'] = ($mode & 00400) ? 'r' : '-';

$owner['write'] = ($mode & 00200) ? 'w' : '-';

$owner['execute'] = ($mode & 00100) ? 'x' : '-';

$group['read'] = ($mode & 00040) ? 'r' : '-';

$group['write'] = ($mode & 00020) ? 'w' : '-';

$group['execute'] = ($mode & 00010) ? 'x' : '-';

$world['read'] = ($mode & 00004) ? 'r' : '-';

$world['write'] = ($mode & 00002) ? 'w' : '-';

$world['execute'] = ($mode & 00001) ? 'x' : '-';

 

// adjust for SUID, SGID and sticky bit

if ($mode & 0x800 ) $owner['execute'] = ($owner['execute'] == 'x') ? 's' : 'S';

if ($mode & 0x400 ) $group['execute'] = ($group['execute'] == 'x') ? 's' : 'S';

if ($mode & 0x200 ) $world['execute'] = ($world['execute'] == 'x') ? 't' : 'T';

 

return $type .

$owner['read'] . $owner['write'] . $owner['execute'] .

$group['read'] . $group['write'] . $group['execute'] .

$world['read'] . $world['write'] . $world['execute'];

}

 

function tep_remove($source) {

global $messageStack, $tep_remove_error;

 

if (isset($tep_remove_error)) $tep_remove_error = false;

 

if (is_dir($source)) {

$dir = dir($source);

while ($file = $dir->read()) {

if ( ($file != '.') && ($file != '..') ) {

if (is_writeable($source . '/' . $file)) {

tep_remove($source . '/' . $file);

} else {

$messageStack->add(sprintf(ERROR_FILE_NOT_REMOVEABLE, $source . '/' . $file), 'error');

$tep_remove_error = true;

}

}

}

$dir->close();

 

if (is_writeable($source)) {

rmdir($source);

} else {

$messageStack->add(sprintf(ERROR_DIRECTORY_NOT_REMOVEABLE, $source), 'error');

$tep_remove_error = true;

}

} else {

if (is_writeable($source)) {

unlink($source);

} else {

$messageStack->add(sprintf(ERROR_FILE_NOT_REMOVEABLE, $source), 'error');

$tep_remove_error = true;

}

}

}

 

////

// Output the tax percentage with optional padded decimals

function tep_display_tax_value($value, $padding = TAX_DECIMAL_PLACES) {

if (strpos($value, '.')) {

$loop = true;

while ($loop) {

if (substr($value, -1) == '0') {

$value = substr($value, 0, -1);

} else {

$loop = false;

if (substr($value, -1) == '.') {

$value = substr($value, 0, -1);

}

}

}

}

 

if ($padding > 0) {

if ($decimal_pos = strpos($value, '.')) {

$decimals = strlen(substr($value, ($decimal_pos+1)));

for ($i=$decimals; $i<$padding; $i++) {

$value .= '0';

}

} else {


A man who works with his hands is a laborer

A man who works with his hands and his brain is a craftsman

But a man who works with his hands and his brain and his heart is an artist. - Charles Dickens

Share this post


Link to post
Share on other sites
Not sure what you mean.

 

The sid will be attached to the URL if cookies are not enabled in the customer's browser, and 'force cookie' use is not set to true.

 

Since IE is now being distributed with cookies NOT enabled, I would think that this would actually represent the majority of users very soon.

 

And the session is not only used when going form SSL to nonSSL, but also what you have in your cart. Not to mention that if one person purchases using that session, and enters their details to create an account, and then another person comes along and uses that session, they will have access to all of the first person's account details.

 

That could be a very serious issue.

YOur site is cacheing the osCid....not good.

 

Another point recently brought to my attention is that if a search engine parses that cashed page, they will also get that very same session id. And the last thing you want to do is have search engine links with session ids in them.

You are correct...we're going to have to find a way to strip the session id's

 

Heya, thanks for the quick reply.

I went to your server and dl the v1.1 for the m3 tax class for oscommerce.. however in the install instructions it still says:

STEP 3 - Edit includes/functions/general.php

REPLACE tep_get_tax_rate() it with this code:

function tep_get_tax_rate($class_id, $country_id = -1, $zone_id = -1) {

global $customer_zone_id, $customer_country_id, $osC_Tax;

return $osC_Tax->getTaxRate($class_id, $country_id, $zone_id);

}

 

REPLACE tep_get_tax_description() it with this code:

function tep_get_tax_description($class_id, $country_id, $zone_id) {

global $osC_Tax;

return $osC_Tax->getTaxRateDescription($class_id, $country_id, $zone_id);

}

 

I have done the 1st one (tep_get_tax_rate), but I don't have tep_get_tax_description in my general.php file in the catalog/includes/functions folder.. any ideas?  below is a copy of my general.php file:

< SNIP >

I don't even see the tep_get_tax_rate() method...are you sure you're modifying *catalog*/includes/functions/general.php?? It should NOT be the one in the admin folder...

Share this post


Link to post
Share on other sites
Stay tuned...there's more to come.  The next steps are:

1. Add popular contributions (discount coupons, featured, specials, etc)

2. Optimize again

3. Search Engine Optmization ala Chemo style

 

As a side note to #3: it's going to be like the "archive" feature of vBulletin discussion forum software.  It will go beyond all_products and take SEO / sitemaps to another level for osCommerce.  Enough of me blowing my own horn...back to coding :)

 

SEO is very high on my wannadoo lists so I'm certainly hooked now :thumbsup:

 

I've dabbled with some of the SEO advice/contributions here but without any joy, for example I've tried turning on SEO URLs option but for whatever reason that just screws up my sites display - dunno if thats due to some contribution additions I've made but hey ho - it's not been a success so far!

 

Anyway don't want to jump the gun here, I will await the developments as you get round to them.

 

Dave.

Share this post


Link to post
Share on other sites
Not sure what you mean.

 

The sid will be attached to the URL if cookies are not enabled in the customer's browser, and 'force cookie' use is not set to true.

 

Since IE is now being distributed with cookies NOT enabled, I would think that this would actually represent the majority of users very soon.

 

And the session is not only used when going form SSL to nonSSL, but also what you have in your cart. Not to mention that if one person purchases using that session, and enters their details to create an account, and then another person comes along and uses that session, they will have access to all of the first person's account details.

 

That could be a very serious issue.

Here are the options:

1. Disable default appending session_id's to URL's setting in tep_href_link()

2. Create code to strip the session id's from the cache code

 

Here is what my tep_href_link() looks like:

  function tep_href_link($page = '', $parameters = '', $connection = 'NONSSL', $add_session_id = false, $search_engine_safe = true) {

Now, even if the session_id's are not appended to the URL they will still be created for guests uniquely. Once they log in they get another or resume a previous. Once they put something in their cart the session_id is recorded in session and that is good for the life of their visit. If they log in they will get a more permanent session_id.

Share this post


Link to post
Share on other sites
YOur site is cacheing the osCid....not good.

You are correct...we're going to have to find a way to strip the session id's

I don't even see the tep_get_tax_rate() method...are you sure you're modifying *catalog*/includes/functions/general.php??  It should NOT be the one in the admin folder...

 

 

ok I feel really dumb, sorry...LOL I HAVE got to learn the difference between admin and catalog LOL!!!

:blush:

THANKS!!!

RW


A man who works with his hands is a laborer

A man who works with his hands and his brain is a craftsman

But a man who works with his hands and his brain and his heart is an artist. - Charles Dickens

Share this post


Link to post
Share on other sites
Here is what my tep_href_link() looks like:

 

Where do i find this code?

 

Thanks

Share this post


Link to post
Share on other sites

Hey all,

 

In reading this topic I also saw someone refer to the config cache contribution. I am trying to install this on my local testing machine (I have easyphp1-7 installed)

 

I think I have it all good, but the cache file is not being generated (I don't recieve any errors though) The instructions say to put in the "absolute" path to where the cache file is located. I think I may have this wrong and was wondering if any of you have an idea I how I can set it correctly.

 

The path to the folder is:

 

C:/EasyPHP1-7/www/config_cache

 

I have tried every combo of this I can think of and nothing works..does anyone have suggestions?

 

Sorry if this is misplaced, but I though to ask the gurus of optimization, and ya'll seem to be here :)

 

RW


A man who works with his hands is a laborer

A man who works with his hands and his brain is a craftsman

But a man who works with his hands and his brain and his heart is an artist. - Charles Dickens

Share this post


Link to post
Share on other sites

Oh one more request for the night :-"

 

Can someone post info in the Join command? where to use it, what it does, etc..

 

THANKS!

RW


A man who works with his hands is a laborer

A man who works with his hands and his brain is a craftsman

But a man who works with his hands and his brain and his heart is an artist. - Charles Dickens

Share this post


Link to post
Share on other sites

Very nice work Bobby ! After having played around with the configuration settings, I also has a look at all those index.php queries that are HUGE! As you said, OSC is way to generic for all Live shops and a lot of stuff can be dropped if not needed (banners, taxes, etc).

 

I think that it's especial very useful in iterations where the same query is repeated over and over again (product listings, etc.)

 

My other optimisations done so far :

 

- gzip compression (level 7)

- configuration flat file (cache)

- tep_get_tax_rate() is exited at beginning if my variable USE_OF_TAX = 0

- drop of banner code

- merge of query for "specials" and products price query.

 

For me it's more as a "background" task when I'm tired after having added another nifty contribution (hehe).

 

I do not display my new products so I cannot help you with the extra JOIN.

 

Bye,

 

Didier.

Share this post


Link to post
Share on other sites
Here is what my tep_href_link() looks like:

CODE

 

function tep_href_link($page = '', $parameters = '', $connection = 'NONSSL', $add_session_id = false, $search_engine_safe = true) {

 

Now, even if the session_id's are not appended to the URL they will still be created for guests uniquely. Once they log in they get another or resume a previous. Once they put something in their cart the session_id is recorded in session and that is good for the life of their visit. If they log in they will get a more permanent session_id.

 

This isn't really a valid solution. Essentially, all this is doing is setting the 'Force Cookie Use' to true. Customers that have browsers that do not allow cookies will not be able to purchase.

 

I think that it would be worth letting everyone know that the 'Page Cache' contribution doesn't work unless you force cookie use.


-------------------------------------------------------------------------------------------------------------------------

NOTE: As of Oct 2006, I'm not as active in this forum as I used to be, but I still work with osC quite a bit.

If you have a question about any of my posts here, your best bet is to contact me though either Email or PM in my profile, and I'll be happy to help.

Share this post


Link to post
Share on other sites

Or, to be more accurate, if you use page case without having 'force cookie usage' set to true, then you have a very serious security risk.


-------------------------------------------------------------------------------------------------------------------------

NOTE: As of Oct 2006, I'm not as active in this forum as I used to be, but I still work with osC quite a bit.

If you have a question about any of my posts here, your best bet is to contact me though either Email or PM in my profile, and I'll be happy to help.

Share this post


Link to post
Share on other sites

Chemo great work, im starting to optimise my site, got this result on index.php it has a modified modules/new_products.php box on it which as you can see loops through to retreive data, any clues on where to start to reduce this down(other than a LIMIT:

 

Current Parse Time: 1.225 s with 73 queries
Array
(
   [QUERIES] => Array
       (
           [0] => select configuration_key as cfgKey, configuration_value as cfgValue from configuration
           [1] => select value from sessions where sesskey = '01a0e28161b759a9d2d59ebe7220f6ed' and expiry > '1099436796'
           [2] => select code, title, symbol_left, symbol_right, decimal_point, thousands_point, decimal_places, value from currencies
           [3] => delete from whos_online where time_last_click < '1099435896'
           [4] => select count(*) as count from whos_online where session_id = '01a0e28161b759a9d2d59ebe7220f6ed'
           [5] => update whos_online set customer_id = '0', full_name = 'Guest', ip_address = '62.254.0.34', time_last_click = '1099436796', last_page_url = '' where session_id = '01a0e28161b759a9d2d59ebe7220f6ed'
           [6] => select specials_id from specials where status = '1' and now() >= expires_date and expires_date > 0
           [7] => select count(p.products_id) as total  from products p left join specials s on p.products_id = s.products_id where products_status = '1'
           [8] => select p.products_id, p.products_image, p.products_tax_class_id, if(s.status, s.specials_new_products_price, p.products_price) as products_price from products p left join specials s on p.products_id = s.products_id where products_status = '1' order by p.products_date_added desc limit 0, 20
           [9] => select categories_id from products_to_categories where products_id = '72'
           [10] => select parent_id from categories where categories_id = '28'
           [11] => select products_name from products_description where products_id = '72'
           [12] => select categories_id from products_to_categories where products_id = '71'
           [13] => select parent_id from categories where categories_id = '28'
           [14] => select products_name from products_description where products_id = '71'
           [15] => select categories_id from products_to_categories where products_id = '70'
           [16] => select parent_id from categories where categories_id = '28'
           [17] => select products_name from products_description where products_id = '70'
           [18] => select categories_id from products_to_categories where products_id = '69'
           [19] => select parent_id from categories where categories_id = '28'
           [20] => select products_name from products_description where products_id = '69'
           [21] => select categories_id from products_to_categories where products_id = '68'
           [22] => select parent_id from categories where categories_id = '28'
           [23] => select products_name from products_description where products_id = '68'
           [24] => select categories_id from products_to_categories where products_id = '67'
           [25] => select parent_id from categories where categories_id = '28'
           [26] => select products_name from products_description where products_id = '67'
           [27] => select categories_id from products_to_categories where products_id = '66'
           [28] => select parent_id from categories where categories_id = '28'
           [29] => select products_name from products_description where products_id = '66'
           [30] => select categories_id from products_to_categories where products_id = '65'
           [31] => select parent_id from categories where categories_id = '28'
           [32] => select products_name from products_description where products_id = '65'
           [33] => select categories_id from products_to_categories where products_id = '64'
           [34] => select parent_id from categories where categories_id = '28'
           [35] => select products_name from products_description where products_id = '64'
           [36] => select categories_id from products_to_categories where products_id = '63'
           [37] => select parent_id from categories where categories_id = '28'
           [38] => select products_name from products_description where products_id = '63'
           [39] => select categories_id from products_to_categories where products_id = '59'
           [40] => select parent_id from categories where categories_id = '27'
           [41] => select products_name from products_description where products_id = '59'
           [42] => select categories_id from products_to_categories where products_id = '58'
           [43] => select parent_id from categories where categories_id = '27'
           [44] => select products_name from products_description where products_id = '58'
           [45] => select categories_id from products_to_categories where products_id = '57'
           [46] => select parent_id from categories where categories_id = '27'
           [47] => select products_name from products_description where products_id = '57'
           [48] => select categories_id from products_to_categories where products_id = '56'
           [49] => select parent_id from categories where categories_id = '27'
           [50] => select products_name from products_description where products_id = '56'
           [51] => select categories_id from products_to_categories where products_id = '55'
           [52] => select parent_id from categories where categories_id = '27'
           [53] => select products_name from products_description where products_id = '55'
           [54] => select categories_id from products_to_categories where products_id = '54'
           [55] => select parent_id from categories where categories_id = '27'
           [56] => select products_name from products_description where products_id = '54'
           [57] => select categories_id from products_to_categories where products_id = '53'
           [58] => select parent_id from categories where categories_id = '27'
           [59] => select products_name from products_description where products_id = '53'
           [60] => select categories_id from products_to_categories where products_id = '52'
           [61] => select parent_id from categories where categories_id = '30'
           [62] => select products_name from products_description where products_id = '52'
           [63] => select categories_id from products_to_categories where products_id = '51'
           [64] => select parent_id from categories where categories_id = '30'
           [65] => select products_name from products_description where products_id = '51'
           [66] => select categories_id from products_to_categories where products_id = '49'
           [67] => select parent_id from categories where categories_id = '27'
           [68] => select products_name from products_description where products_id = '49'
           [69] => select startdate, counter from counter
           [70] => update counter set counter = '558'
           [71] => select count(*) as total from sessions where sesskey = '01a0e28161b759a9d2d59ebe7220f6ed'
           [72] => update sessions set expiry = '1099438237', value = 'cart|O:12:\"shoppingcart\":5:{s:8:\"contents\";a:0:{}s:5:\"total\";i:0;s:6:\"weight\";i:0;s:6:\"cartID\";N;s:12:\"content_type\";b:0;}language|s:7:\"english\";languages_id|s:1:\"1\";currency|s:3:\"GBP\";navigation|O:17:\"navigationhistory\":2:{s:4:\"path\";a:2:{i:0;a:4:{s:4:\"page\";s:16:\"product_info.php\";s:4:\"mode\";s:6:\"NONSSL\";s:3:\"get\";a:2:{s:5:\"cPath\";s:2:\"22\";s:11:\"products_id\";s:2:\"29\";}s:4:\"post\";a:0:{}}i:1;a:4:{s:4:\"page\";s:9:\"index.php\";s:4:\"mode\";s:6:\"NONSSL\";s:3:\"get\";a:2:{s:6:\"output\";s:1:\"1\";s:6:\"osCsid\";s:32:\"01a0e28161b759a9d2d59ebe7220f6ed\";}s:4:\"post\";a:0:{}}}s:8:\"snapshot\";a:0:{}}' where sesskey = '01a0e28161b759a9d2d59ebe7220f6ed'
       )

)

Share this post


Link to post
Share on other sites

Chemo, first I would like to say thanks for all your help with the optimization process. I was wondering if you tried the Page Cache + Config Cache mods with Simple Template System installed. I managed to get the config cache working but when I turn on Page Cache I get this error:

 

Fatal error: Call to a member function on a non-object in /home/perfumeo/public_html/shop/includes/sts_display_output.php on line 200

Share this post


Link to post
Share on other sites
ok I feel really dumb, sorry...LOL I HAVE got to learn the difference between admin and catalog LOL!!!

:blush:

THANKS!!!

RW

No problem...

 

Where do i find this code?

 

Thanks

It is located in *catalog*/includes/functions/html_output.php

 

Oh one more request for the night  :-"

 

Can someone post info in the Join command?  where to use it, what it does, etc..

 

THANKS!

RW

The JOIN is different for each module so can't give specifics unless you give me a specific file (i.e. - new_products.php)

 

Or, to be more accurate, if you use page case without having 'force cookie usage' set to true, then you have a very serious security risk.

Let's do this...take a look at the code and see if there is a quick way to remove the session_id's from the URL's and cache file name.

 

In the case of my client who I developed it for he uses SEF URL's so this is to be expected on live shops installing (of course, I didn't see it or would have done something about it before releasing).

 

At any rate, I'll take a look and see what can be done. It might be as simple as a str_replace() to get it out.

Chemo great work, im starting to optimise my site, got this result on index.php it has a modified modules/new_products.php box on it which as you can see loops through to retreive data, any clues on where to start to reduce this down(other than a LIMIT:

 

Current Parse Time: 1.225 s with 73 queries
< SNIP Lots of data >

Send me your modified file and I'll send one back with a few JOINS to get those queries down.

Chemo, first I would like to say thanks for all your help with the optimization process.  I was wondering if you tried the Page Cache + Config Cache mods with Simple Template System installed.  I managed to get the config cache working but when I turn on Page Cache I get this error:

 

Fatal error: Call to a member function on a non-object in /home/perfumeo/public_html/shop/includes/sts_display_output.php on line 200

I have not looked at the template systems available but this is the second report of non-compatibilitiy with page cache. I need to put that disclaimer in there somewhere until we can get them working together!

Share this post


Link to post
Share on other sites

It won't matter if the store owner has SEF enabled or not. If they do not have 'Force Cookie Usage' set to true, then the session will always be hardcoded into the cashe page, thereby allowing the session to be 'hi-jacked'.

 

The session might be able to be removed with a search and replace function, or we might be able to pass the section of the html_output file an indicator NOT to assign a SID, like we do for spiders. Abviously, we wouldn't be able to use the USER AGENT, but I bet we could come up wit hsome other sort of indicator that this is something that should not be assigned an SID.


-------------------------------------------------------------------------------------------------------------------------

NOTE: As of Oct 2006, I'm not as active in this forum as I used to be, but I still work with osC quite a bit.

If you have a question about any of my posts here, your best bet is to contact me though either Email or PM in my profile, and I'll be happy to help.

Share this post


Link to post
Share on other sites

×