Quick Search:

View

Revision:

Diff

Diff from 716 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/osCommerce/oscommerce2/trunk/update-20060817.txt

Annotated File View

hpdl
711
1 osCommerce 2.2 Milestone 2 Update 060817
2 Update Package 17th August 2006
3
4 ------------------------------------------------------------------------------
5 Table of Contents
6 ------------------------------------------------------------------------------
7
8 ## Update 060817 (17th August 2006)
9
10 Magic Quotes Compatibility Layer Fix
11 Parse GET Variables In Cache Functions
12 PHP 3 Session ID XSS Issue
13 Product Attributes SQL Injection
14 Resize Images To Round Numbers
hpdl
714
15 Use The Correct Country Name Value When Formatting Addresses
hpdl
716
16 Prevent The Session ID Being Passed In Tell-A-Friend E-Mails
hpdl
711
17
18 ## Update 051113 (13th November 2005)
19
20 customer_country_id in addressbook
21
22 ## Update 051112 (12th November 2005)
23
24 Cannot re-assign $this
25 limit -20, 20
26 Database Input Enhancement
27 Adding Non-Existing Products To Cart
28 Session ID XSS Issue
29 Validate Session ID
30 File Manager Problem
31 HTTP Header Injection
32 E-Mail Header Injection
33 Contact Us Form XSS Issue
34 Open Redirector
35 Extra Slashes In New Products
36 Order Status Filtering
37 MySQL 5.0 Compatibility
38
39 ###########################
40 ###### Update 060817 ######
41 ###########################
42
43 ------------------------------------------------------------------------------
44 Magic Quotes Compatibility Layer Fix
45 http://www.oscommerce.com/community/bugs,1435
46 http://svn.oscommerce.com/trac/changeset/706
47 ------------------------------------------------------------------------------
48
49 Problem:
50
51 The Magic Quotes compatibility layer does not parse arrays within the GET/POST/COOKIE scope that can be used to inject SQL into database queries.
52
53 Solution:
54
55 The following lines must be replaced in catalog/includes/functions/compatibility.php:
56
57 Lines 22-23, from:
58
59 if (is_array($value)) {
60   do_magic_quotes_gpc($value);
61
62 to:
63
64 if (is_array($ar[$key])) {
65   do_magic_quotes_gpc($ar[$key]);
66
67 The following lines must be replaced in catalog/admin/includes/functions/compatibility.php:
68
69 Lines 22-23, from:
70
71 if (is_array($value)) {
72   do_magic_quotes_gpc($value);
73
74 to:
75
76 if (is_array($ar[$key])) {
77   do_magic_quotes_gpc($ar[$key]);
78
79 ------------------------------------------------------------------------------
80 Parse GET Variables In Cache Functions
81 http://svn.oscommerce.com/trac/changeset/708
82 ------------------------------------------------------------------------------
83
84 Problem:
85
86 The GET variables used in caching functions are not parsed.
87
88 Solution:
89
90 The following lines must be replaced in catalog/includes/functions/cache.php:
91
92 Line 121, from:
93
94 if (isset($HTTP_GET_VARS['manufactuers_id']) && tep_not_null($HTTP_GET_VARS['manufacturers_id'])) {
95
96 to:
97
98 if (isset($HTTP_GET_VARS['manufactuers_id']) && is_numeric($HTTP_GET_VARS['manufacturers_id'])) {
99
100 Lines 142-148, from:
101
102 if (($refresh == true) || !read_cache($cache_output, 'also_purchased-' . $language . '.cache' . $HTTP_GET_VARS['products_id'], $auto_expire)) {
103   ob_start();
104   include(DIR_WS_MODULES . FILENAME_ALSO_PURCHASED_PRODUCTS);
105   $cache_output = ob_get_contents();
106   ob_end_clean();
107   write_cache($cache_output, 'also_purchased-' . $language . '.cache' . $HTTP_GET_VARS['products_id']);
108 }
109
110 to:
111
112 $cache_output = '';
113
114 if (isset($HTTP_GET_VARS['products_id']) && is_numeric($HTTP_GET_VARS['products_id'])) {
115   if (($refresh == true) || !read_cache($cache_output, 'also_purchased-' . $language . '.cache' . $HTTP_GET_VARS['products_id'], $auto_expire)) {
116     ob_start();
117     include(DIR_WS_MODULES . FILENAME_ALSO_PURCHASED_PRODUCTS);
118     $cache_output = ob_get_contents();
119     ob_end_clean();
120     write_cache($cache_output, 'also_purchased-' . $language . '.cache' . $HTTP_GET_VARS['products_id']);
121   }
122 }
123
124 ------------------------------------------------------------------------------
125 PHP 3 Session ID XSS Issue
126 http://svn.oscommerce.com/trac/changeset/709
127 ------------------------------------------------------------------------------
128
129 Problem:
130
131 The session ID in the PHP 3 compatibility layer is not being parsed.
132
133 Solution:
134
135 The following lines must be added in catalog/includes/classes/sessions.php:
136
137 Line 380:
138
139 if (!empty($session->id)) {
140   if (preg_match('/^[a-zA-Z0-9]+$/', $session->id) == false) {
141     unset($session->id);
142   }
143 }
144
145 ------------------------------------------------------------------------------
146 Product Attributes SQL Injection
147 http://svn.oscommerce.com/trac/changeset/703
148 ------------------------------------------------------------------------------
149
150 Problem:
151
152 With the failure of arrays not being parsed by the magic_quotes_gpc compatibility layer, it is possible to inject SQL into database queries.
153
154 Solution:
155
156 The following lines must be replaced in catalog/includes/classes/shopping_cart.php:
157
158 Line 84, from:
159
160 if (is_numeric($products_id) && is_numeric($qty)) {
161
162 to:
163
164 $attributes_pass_check = true;
165
166 if (is_array($attributes)) {
167   reset($attributes);
168   while (list($option, $value) = each($attributes)) {
169     if (!is_numeric($option) || !is_numeric($value)) {
170       $attributes_pass_check = false;
171       break;
172     }
173   }
174 }
175
176 if (is_numeric($products_id) && is_numeric($qty) && ($attributes_pass_check == true)) {
177
178 Line 125, from:
179
180 if (is_numeric($products_id) && isset($this->contents[$products_id_string]) && is_numeric($quantity)) {
181
182 to:
183
184 $attributes_pass_check = true;
185
186 if (is_array($attributes)) {
187   reset($attributes);
188   while (list($option, $value) = each($attributes)) {
189     if (!is_numeric($option) || !is_numeric($value)) {
190       $attributes_pass_check = false;
191       break;
192     }
193   }
194 }
195
196 if (is_numeric($products_id) && isset($this->contents[$products_id_string]) && is_numeric($quantity) && ($attributes_pass_check == true)) {
197
198 The following lines must be replaced in catalog/shopping_cart.php:
199
200 Lines 84-85, from:
201
202 where pa.products_id = '" . $products[$i]['id'] . "'
203 and pa.options_id = '" . $option . "'
204
205 to:
206
207 where pa.products_id = '" . (int)$products[$i]['id'] . "'
208 and pa.options_id = '" . (int)$option . "'
209
210 Line 87, from:
211
212 and pa.options_values_id = '" . $value . "'
213
214 to:
215
216 and pa.options_values_id = '" . (int)$value . "'
217
218 Lines 89-90, from:
219
220 and popt.language_id = '" . $languages_id . "'
221 and poval.language_id = '" . $languages_id . "'");
222
223 to:
224
225 and popt.language_id = '" . (int)$languages_id . "'
226 and poval.language_id = '" . (int)$languages_id . "'");
227
228 ------------------------------------------------------------------------------
229 Resize Images To Round Numbers
230 http://www.oscommerce.com/community/bugs,1371
231 http://svn.oscommerce.com/trac/changeset/707
232 ------------------------------------------------------------------------------
233
234 Problem:
235
236 The image resizing logic may result in decimal numbers which the HTML specification does not allow.
237
238 Solution:
239
240 The following lines must be replaced in catalog/includes/functions/html_output.php:
241
242 Line 91, from:
243
244 $width = $image_size[0] * $ratio;
245
246 to:
247
248 $width = intval($image_size[0] * $ratio);
249
250 Line 94, from:
251
252 $height = $image_size[1] * $ratio;
253
254 to:
255
256 $height = intval($image_size[1] * $ratio);
257
hpdl
714
258 ------------------------------------------------------------------------------
259 Use The Correct Country Name Value When Formatting Addresses
260 http://www.oscommerce.com/community/bugs,1291
261 http://svn.oscommerce.com/trac/changeset/713
262 ------------------------------------------------------------------------------
263
264 Problem:
265
266 Depending on the values passed to tep_address_format(), an array value could be used as the country name instead of a string value.
267
268 Solution:
269
270 The following line must be replaced in catalog/includes/functions/general.php:
271
272 Line 453, from:
273
274 $country = tep_output_string_protected($address['country']);
275
276 to:
277
278 $country = tep_output_string_protected($address['country']['title']);
279
280 The following line must be removed:
281
282 Line 483:
283
284 if ($country == '') $country = tep_output_string_protected($address['country']);
285
hpdl
716
286 ------------------------------------------------------------------------------
287 Prevent The Session ID Being Passed In Tell-A-Friend E-Mails
288 http://www.oscommerce.com/community/bugs,3986
289 http://svn.oscommerce.com/trac/changeset/715
290 ------------------------------------------------------------------------------
291
292 Problem:
293
294 If the customer has cookies disabled their session ID may exist in the store URL used in tell-a-friend emails.
295
296 Solution:
297
298 The following line must be replaced in catalog/tell_a_friend.php:
299
300 Line 77, from:
301
302 $email_body .= sprintf(TEXT_EMAIL_LINK, tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $HTTP_GET_VARS['products_id'])) . "\n\n" .
303
304 to:
305
306 $email_body .= sprintf(TEXT_EMAIL_LINK, tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $HTTP_GET_VARS['products_id'], 'NONSSL', false)) . "\n\n" .
307
hpdl
711
308 ###########################
309 ###### Update 051113 ######
310 ###########################
311
312 ------------------------------------------------------------------------------
313 customer_country_id in addressbook
314 http://www.oscommerce.com/community/bugs,1662
315 ------------------------------------------------------------------------------
316
317 Problem:
318
319 When the customer updates their address in the My Account page, their country value is being stored in an incorrect variable that can cause an incorrect tax rate value being used in product prices.
320
321 Solution:
322
323 The following lines must be replaced in catalog/address_book_process.php:
324
325 Line 150, from:
326
327 $customer_country_id = $country_id;
328
329 to:
330
331 $customer_country_id = $country;
332
333 Line 171, from:
334
335 $customer_country_id = $country_id;
336
337 to:
338
339 $customer_country_id = $country;
340
341 ###########################
342 ###### Update 051112 ######
343 ###########################
344
345 ------------------------------------------------------------------------------
346 Cannot re-assign $this
347 http://www.oscommerce.com/community/bugs,1650
348 ------------------------------------------------------------------------------
349
350 Problem:
351
352 Fatal error: Cannot re-assign $this in /path/to/catalog/admin/includes/classes/upload.php on line 31
353
354 Solution:
355
356 Lines 27-34 in catalog/admin/includes/classes/upload.php must be changed from:
357
358 if ( ($this->parse() == true) && ($this->save() == true) ) {
359   return true;
360 } else {
361 // self destruct
362   $this = null;
363
364   return false;
365 }
366
367 to:
368
369 if ( ($this->parse() == true) && ($this->save() == true) ) {
370   return true;
371 } else {
372   return false;
373 }
374
375 ------------------------------------------------------------------------------
376 limit -20, 20
377 http://www.oscommerce.com/community/bugs,1605
378 ------------------------------------------------------------------------------
379
380 Problem:
381
382 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-20, 20' at line 1
383
384 Solution:
385
386 Line 67 in catalog/includes/classes/split_page_results.php must be changed from:
387
388 $this->sql_query .= " limit " . $offset . ", " . $this->number_of_rows_per_page;
389
390 to:
391
392 $this->sql_query .= " limit " . max($offset, 0) . ", " . $this->number_of_rows_per_page;
393
394 Line 38 in catalog/admin/includes/classes/split_page_results.php must be changed from:
395
396 $sql_query .= " limit " . $offset . ", " . $max_rows_per_page;
397
398 to:
399
400 $sql_query .= " limit " . max($offset, 0) . ", " . $max_rows_per_page;
401
402 ------------------------------------------------------------------------------
403 Database Input Enhancement
404 ------------------------------------------------------------------------------
405
406 Problem:
407
408 Native MySQL functions should be used in preference to the addslashes() function, to properly protect the SQL queries being executed on the database server.
409
410 Solution:
411
412 The following function must be replaced in catalog/includes/functions/database.php.
413
414 Lines 126-128, from:
415
416 function tep_db_input($string) {
417   return addslashes($string);
418 }
419
420 to:
421
422 function tep_db_input($string, $link = 'db_link') {
423   global $$link;
424
425   if (function_exists('mysql_real_escape_string')) {
426     return mysql_real_escape_string($string, $$link);
427   } elseif (function_exists('mysql_escape_string')) {
428     return mysql_escape_string($string);
429   }
430
431   return addslashes($string);
432 }
433
434 The following function must be replaced in catalog/admin/includes/functions/database.php.
435
436 Lines 130-132, from:
437
438 function tep_db_input($string) {
439   return addslashes($string);
440 }
441
442 to:
443
444 function tep_db_input($string, $link = 'db_link') {
445   global $$link;
446
447   if (function_exists('mysql_real_escape_string')) {
448     return mysql_real_escape_string($string, $$link);
449   } elseif (function_exists('mysql_escape_string')) {
450     return mysql_escape_string($string);
451   }
452
453   return addslashes($string);
454 }
455
456 ------------------------------------------------------------------------------
457 Adding Non-Existing Products To Cart
458 http://www.oscommerce.com/community/bugs,1617
459 ------------------------------------------------------------------------------
460
461 Problem:
462
463 It is possible to add non-existing products into the shopping cart which may prevent customers from removing the products from their cart.
464
465 Solution:
466
467 The following functions must be replaced in catalog/includes/functions/general.php.
468
469 Lines 912-921, from:
470
471 function tep_get_uprid($prid, $params) {
472   $uprid = $prid;
473   if ( (is_array($params)) && (!strstr($prid, '{')) ) {
474     while (list($option, $value) = each($params)) {
475       $uprid = $uprid . '{' . $option . '}' . $value;
476     }
477   }
478
479   return $uprid;
480 }
481
482 to:
483
484 function tep_get_uprid($prid, $params) {
485   if (is_numeric($prid)) {
486     $uprid = $prid;
487
488     if (is_array($params) && (sizeof($params) > 0)) {
489       $attributes_check = true;
490       $attributes_ids = '';
491
492       reset($params);
493       while (list($option, $value) = each($params)) {
494         if (is_numeric($option) && is_numeric($value)) {
495           $attributes_ids .= '{' . (int)$option . '}' . (int)$value;
496         } else {
497           $attributes_check = false;
498           break;
499         }
500       }
501
502       if ($attributes_check == true) {
503         $uprid .= $attributes_ids;
504       }
505     }
506   } else {
507     $uprid = tep_get_prid($prid);
508
509     if (is_numeric($uprid)) {
510       if (strpos($prid, '{') !== false) {
511         $attributes_check = true;
512         $attributes_ids = '';
513
514 // strpos()+1 to remove up to and including the first { which would create an empty array element in explode()
515         $attributes = explode('{', substr($prid, strpos($prid, '{')+1));
516
517         for ($i=0, $n=sizeof($attributes); $i<$n; $i++) {
518           $pair = explode('}', $attributes[$i]);
519
520           if (is_numeric($pair[0]) && is_numeric($pair[1])) {
521             $attributes_ids .= '{' . (int)$pair[0] . '}' . (int)$pair[1];
522           } else {
523             $attributes_check = false;
524             break;
525           }
526         }
527
528         if ($attributes_check == true) {
529           $uprid .= $attributes_ids;
530         }
531       }
532     } else {
533       return false;
534     }
535   }
536
537   return $uprid;
538 }
539
540 Lines 925-929, from:
541
542 function tep_get_prid($uprid) {
543   $pieces = explode('{', $uprid);
544
545   return $pieces[0];
546 }
547
548 to:
549
550 function tep_get_prid($uprid) {
551   $pieces = explode('{', $uprid);
552
553   if (is_numeric($pieces[0])) {
554     return $pieces[0];
555   } else {
556     return false;
557   }
558 }
559
560 The following functions must be replaced in catalog/includes/classes/shopping_cart.php.
561
562 Lines 78-108, from:
563
564 function add_cart($products_id, $qty = '1', $attributes = '', $notify = true) {
565   global $new_products_id_in_cart, $customer_id;
566
567   $products_id = tep_get_uprid($products_id, $attributes);
568   if ($notify == true) {
569     $new_products_id_in_cart = $products_id;
570     tep_session_register('new_products_id_in_cart');
571   }
572
573   if ($this->in_cart($products_id)) {
574     $this->update_quantity($products_id, $qty, $attributes);
575   } else {
576     $this->contents[] = array($products_id);
577     $this->contents[$products_id] = array('qty' => $qty);
578 // insert into database
579     if (tep_session_is_registered('customer_id')) tep_db_query("insert into " . TABLE_CUSTOMERS_BASKET . " (customers_id, products_id, customers_basket_quantity, customers_basket_date_added) values ('" . (int)$customer_id . "', '" . tep_db_input($products_id) . "', '" . $qty . "', '" . date('Ymd') . "')");
580
581     if (is_array($attributes)) {
582       reset($attributes);
583       while (list($option, $value) = each($attributes)) {
584         $this->contents[$products_id]['attributes'][$option] = $value;
585 // insert into database
586         if (tep_session_is_registered('customer_id')) tep_db_query("insert into " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " (customers_id, products_id, products_options_id, products_options_value_id) values ('" . (int)$customer_id . "', '" . tep_db_input($products_id) . "', '" . (int)$option . "', '" . (int)$value . "')");
587       }
588     }
589   }
590   $this->cleanup();
591
592 // assign a temporary unique ID to the order contents to prevent hack attempts during the checkout procedure
593   $this->cartID = $this->generate_cart_id();
594 }
595
596 to:
597
598 function add_cart($products_id, $qty = '1', $attributes = '', $notify = true) {
599   global $new_products_id_in_cart, $customer_id;
600
601   $products_id_string = tep_get_uprid($products_id, $attributes);
602   $products_id = tep_get_prid($products_id_string);
603
604   if (is_numeric($products_id) && is_numeric($qty)) {
605     $check_product_query = tep_db_query("select products_status from " . TABLE_PRODUCTS . " where products_id = '" . (int)$products_id . "'");
606     $check_product = tep_db_fetch_array($check_product_query);
607
608     if (($check_product !== false) && ($check_product['products_status'] == '1')) {
609       if ($notify == true) {
610         $new_products_id_in_cart = $products_id;
611         tep_session_register('new_products_id_in_cart');
612       }
613
614       if ($this->in_cart($products_id_string)) {
615         $this->update_quantity($products_id_string, $qty, $attributes);
616       } else {
617         $this->contents[$products_id_string] = array('qty' => $qty);
618 // insert into database
619         if (tep_session_is_registered('customer_id')) tep_db_query("insert into " . TABLE_CUSTOMERS_BASKET . " (customers_id, products_id, customers_basket_quantity, customers_basket_date_added) values ('" . (int)$customer_id . "', '" . tep_db_input($products_id_string) . "', '" . (int)$qty . "', '" . date('Ymd') . "')");
620
621         if (is_array($attributes)) {
622           reset($attributes);
623           while (list($option, $value) = each($attributes)) {
624             $this->contents[$products_id_string]['attributes'][$option] = $value;
625 // insert into database
626             if (tep_session_is_registered('customer_id')) tep_db_query("insert into " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " (customers_id, products_id, products_options_id, products_options_value_id) values ('" . (int)$customer_id . "', '" . tep_db_input($products_id_string) . "', '" . (int)$option . "', '" . (int)$value . "')");
627           }
628         }
629       }
630
631       $this->cleanup();
632
633 // assign a temporary unique ID to the order contents to prevent hack attempts during the checkout procedure
634       $this->cartID = $this->generate_cart_id();
635     }
636   }
637 }
638
639 Lines 110-127, from:
640
641 function update_quantity($products_id, $quantity = '', $attributes = '') {
642   global $customer_id;
643
644   if (empty($quantity)) return true; // nothing needs to be updated if theres no quantity, so we return true..
645
646   $this->contents[$products_id] = array('qty' => $quantity);
647 // update database
648   if (tep_session_is_registered('customer_id')) tep_db_query("update " . TABLE_CUSTOMERS_BASKET . " set customers_basket_quantity = '" . $quantity . "' where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id) . "'");
649
650   if (is_array($attributes)) {
651     reset($attributes);
652     while (list($option, $value) = each($attributes)) {
653       $this->contents[$products_id]['attributes'][$option] = $value;
654 // update database
655       if (tep_session_is_registered('customer_id')) tep_db_query("update " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " set products_options_value_id = '" . (int)$value . "' where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id) . "' and products_options_id = '" . (int)$option . "'");
656     }
657   }
658 }
659
660 to:
661
662 function update_quantity($products_id, $quantity = '', $attributes = '') {
663   global $customer_id;
664
665   $products_id_string = tep_get_uprid($products_id, $attributes);
666   $products_id = tep_get_prid($products_id_string);
667
668   if (is_numeric($products_id) && isset($this->contents[$products_id_string]) && is_numeric($quantity)) {
669     $this->contents[$products_id_string] = array('qty' => $quantity);
670 // update database
671     if (tep_session_is_registered('customer_id')) tep_db_query("update " . TABLE_CUSTOMERS_BASKET . " set customers_basket_quantity = '" . (int)$quantity . "' where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id_string) . "'");
672
673     if (is_array($attributes)) {
674       reset($attributes);
675       while (list($option, $value) = each($attributes)) {
676         $this->contents[$products_id_string]['attributes'][$option] = $value;
677 // update database
678         if (tep_session_is_registered('customer_id')) tep_db_query("update " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " set products_options_value_id = '" . (int)$value . "' where customers_id = '" . (int)$customer_id . "' and products_id = '" . tep_db_input($products_id_string) . "' and products_options_id = '" . (int)$option . "'");
679       }
680     }
681   }
682 }
683
684 ------------------------------------------------------------------------------
685 Session ID XSS Issue
686 http://www.oscommerce.com/community/bugs,1546
687 ------------------------------------------------------------------------------
688
689 Problem:
690
691 A cross site scripting issue exists with malformed session IDs being used in the tep_href_link() function.
692
693 Solution:
694
695 Line 66 in catalog/includes/functions/html_output.php must be changed from:
696
697 $link .= $separator . $_sid;
698
699 to:
700
701 $link .= $separator . tep_output_string($_sid);
702
703 ------------------------------------------------------------------------------
704 Validate Session ID
705 ------------------------------------------------------------------------------
706
707 Problem:
708
709 Validate the session ID and redirect to the front page when an invalid session ID is requested.
710
711 Solution:
712
713 The following function must be replaced in catalog/includes/functions/sessions.php.
714
715 Lines 66-68, from:
716
717 function tep_session_start() {
718   return session_start();
719 }
720
721 to:
722
723 function tep_session_start() {
724   global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS;
725
726   $sane_session_id = true;
727
728   if (isset($HTTP_GET_VARS[tep_session_name()])) {
729     if (preg_match('/^[a-zA-Z0-9]+$/', $HTTP_GET_VARS[tep_session_name()]) == false) {
730       unset($HTTP_GET_VARS[tep_session_name()]);
731
732       $sane_session_id = false;
733     }
734   } elseif (isset($HTTP_POST_VARS[tep_session_name()])) {
735     if (preg_match('/^[a-zA-Z0-9]+$/', $HTTP_POST_VARS[tep_session_name()]) == false) {
736       unset($HTTP_POST_VARS[tep_session_name()]);
737
738       $sane_session_id = false;
739     }
740   } elseif (isset($HTTP_COOKIE_VARS[tep_session_name()])) {
741     if (preg_match('/^[a-zA-Z0-9]+$/', $HTTP_COOKIE_VARS[tep_session_name()]) == false) {
742       $session_data = session_get_cookie_params();
743
744       setcookie(tep_session_name(), '', time()-42000, $session_data['path'], $session_data['domain']);
745
746       $sane_session_id = false;
747     }
748   }
749
750   if ($sane_session_id == false) {
751     tep_redirect(tep_href_link(FILENAME_DEFAULT, '', 'NONSSL', false));
752   }
753
754   return session_start();
755 }
756
757 ------------------------------------------------------------------------------
758 File Manager Problem
759 http://www.oscommerce.com/community/bugs,1391
760 ------------------------------------------------------------------------------
761
762 Problem:
763
764 Parsing errors occur when saving edited files through the File Manager.
765
766 Solution:
767
768 Line 148 in catalog/admin/file_manager.php must be changed from:
769
770 $file_contents = htmlspecialchars(implode('', $file_array));
771
772 to:
773
774 $file_contents = addslashes(implode('', $file_array));
775
776 Note: This update also requires the Contact Us Form XSS Issue update in order to function correctly.
777
778 ------------------------------------------------------------------------------
779 HTTP Header Injection
780 ------------------------------------------------------------------------------
781
782 Problem:
783
784 By using malicious data it is possible to inject headers into HTTP requests. 
785 Solution:
786
787 The following function must be replaced in catalog/includes/functions/general.php.
788
789 Lines 22-32, from:
790
791 function tep_redirect($url) {
792   if ( (ENABLE_SSL == true) && (getenv('HTTPS') == 'on') ) { // We are loading an SSL page
793     if (substr($url, 0, strlen(HTTP_SERVER)) == HTTP_SERVER) { // NONSSL url
794       $url = HTTPS_SERVER . substr($url, strlen(HTTP_SERVER)); // Change it to SSL
795     }
796   }
797
798   header('Location: ' . $url);
799
800   tep_exit();
801 }
802
803 to:
804
805 function tep_redirect($url) {
806   if ( (strstr($url, "\n") != false) || (strstr($url, "\r") != false) ) {
807     tep_redirect(tep_href_link(FILENAME_DEFAULT, '', 'NONSSL', false));
808   }
809
810   if ( (ENABLE_SSL == true) && (getenv('HTTPS') == 'on') ) { // We are loading an SSL page
811     if (substr($url, 0, strlen(HTTP_SERVER)) == HTTP_SERVER) { // NONSSL url
812       $url = HTTPS_SERVER . substr($url, strlen(HTTP_SERVER)); // Change it to SSL
813     }
814   }
815
816   header('Location: ' . $url);
817
818   tep_exit();
819 }
820
821 The following function must be replaced in catalog/admin/includes/functions/general.php.
822
823 Lines 15-26, from:
824
825 function tep_redirect($url) {
826   global $logger;
827
828   header('Location: ' . $url);
829
830   if (STORE_PAGE_PARSE_TIME == 'true') {
831     if (!is_object($logger)) $logger = new logger;
832     $logger->timer_stop();
833   }
834
835   exit;
836 }
837
838 to:
839
840 function tep_redirect($url) {
841   global $logger;
842
843   if ( (strstr($url, "\n") != false) || (strstr($url, "\r") != false) ) {
844     tep_redirect(tep_href_link(FILENAME_DEFAULT, '', 'NONSSL', false));
845   }
846
847   header('Location: ' . $url);
848
849   if (STORE_PAGE_PARSE_TIME == 'true') {
850     if (!is_object($logger)) $logger = new logger;
851     $logger->timer_stop();
852   }
853
854   exit;
855 }
856
857 ------------------------------------------------------------------------------
858 E-Mail Header Injection
859 http://www.oscommerce.com/community/bugs,2488
860 ------------------------------------------------------------------------------
861
862 Problem:
863
864 By using malicious data it is possible to inject headers into emails the online store sends. 
865
866 Solution:
867
868 The following function must be replaced in catalog/includes/classes/email.php and catalog/admin/includes/classes/email.php.
869
870 Lines 473-504, from:
871
872 function send($to_name, $to_addr, $from_name, $from_addr, $subject = '', $headers = '') {
873   $to = (($to_name != '') ? '"' . $to_name . '" <' . $to_addr . '>' : $to_addr);
874   $from = (($from_name != '') ? '"' . $from_name . '" <' . $from_addr . '>' : $from_addr);
875
876   if (is_string($headers)) {
877     $headers = explode($this->lf, trim($headers));
878   }
879
880   for ($i=0; $i<count($headers); $i++) {
881     if (is_array($headers[$i])) {
882       for ($j=0; $j<count($headers[$i]); $j++) {
883         if ($headers[$i][$j] != '') {
884           $xtra_headers[] = $headers[$i][$j];
885         }
886       }
887     }
888
889     if ($headers[$i] != '') {
890       $xtra_headers[] = $headers[$i];
891     }
892   }
893
894   if (!isset($xtra_headers)) {
895     $xtra_headers = array();
896   }
897
898   if (EMAIL_TRANSPORT == 'smtp') {
899     return mail($to_addr, $subject, $this->output, 'From: ' . $from . $this->lf . 'To: ' . $to . $this->lf . implode($this->lf, $this->headers) . $this->lf . implode($this->lf, $xtra_headers));
900   } else {
901     return mail($to, $subject, $this->output, 'From: '.$from.$this->lf.implode($this->lf, $this->headers).$this->lf.implode($this->lf, $xtra_headers));
902   }
903 }
904
905 to:
906
907 function send($to_name, $to_addr, $from_name, $from_addr, $subject = '', $headers = '') {
908   if ((strstr($to_name, "\n") != false) || (strstr($to_name, "\r") != false)) {
909     return false;
910   }
911
912   if ((strstr($to_addr, "\n") != false) || (strstr($to_addr, "\r") != false)) {
913     return false;
914   }
915
916   if ((strstr($subject, "\n") != false) || (strstr($subject, "\r") != false)) {
917     return false;
918   }
919
920   if ((strstr($from_name, "\n") != false) || (strstr($from_name, "\r") != false)) {
921     return false;
922   }
923
924   if ((strstr($from_addr, "\n") != false) || (strstr($from_addr, "\r") != false)) {
925     return false;
926   }
927
928   $to = (($to_name != '') ? '"' . $to_name . '" <' . $to_addr . '>' : $to_addr);
929   $from = (($from_name != '') ? '"' . $from_name . '" <' . $from_addr . '>' : $from_addr);
930
931   if (is_string($headers)) {
932     $headers = explode($this->lf, trim($headers));
933   }
934
935   for ($i=0; $i<count($headers); $i++) {
936     if (is_array($headers[$i])) {
937       for ($j=0; $j<count($headers[$i]); $j++) {
938         if ($headers[$i][$j] != '') {
939           $xtra_headers[] = $headers[$i][$j];
940         }
941       }
942     }
943
944     if ($headers[$i] != '') {
945       $xtra_headers[] = $headers[$i];
946     }
947   }
948
949   if (!isset($xtra_headers)) {
950     $xtra_headers = array();
951   }
952
953   if (EMAIL_TRANSPORT == 'smtp') {
954     return mail($to_addr, $subject, $this->output, 'From: ' . $from . $this->lf . 'To: ' . $to . $this->lf . implode($this->lf, $this->headers) . $this->lf . implode($this->lf, $xtra_headers));
955   } else {
956     return mail($to, $subject, $this->output, 'From: '.$from.$this->lf.implode($this->lf, $this->headers).$this->lf.implode($this->lf, $xtra_headers));
957   }
958 }
959
960 ------------------------------------------------------------------------------
961 Contact Us Form XSS Issue
962 http://www.oscommerce.com/community/bugs,2422
963 ------------------------------------------------------------------------------
964
965 Problem:
966
967 By using malicious data it is possible to inject HTML into the page. 
968
969 Solution:
970
971 Lines 221-225 in catalog/includes/functions/html_output.php must be changed from:
972
973 if ( (isset($GLOBALS[$name])) && ($reinsert_value == true) ) {
974   $field .= stripslashes($GLOBALS[$name]);
975 } elseif (tep_not_null($text)) {
976   $field .= $text;
977 }
978
979 to:
980
981 if ( (isset($GLOBALS[$name])) && ($reinsert_value == true) ) {
982   $field .= tep_output_string_protected(stripslashes($GLOBALS[$name]));
983 } elseif (tep_not_null($text)) {
984   $field .= tep_output_string_protected($text);
985 }
986
987 Lines 244-248 in catalog/admin/includes/functions/html_output.php must be changed from:
988
989 if ( (isset($GLOBALS[$name])) && ($reinsert_value == true) ) {
990   $field .= stripslashes($GLOBALS[$name]);
991 } elseif (tep_not_null($text)) {
992   $field .= $text;
993 }
994
995 to:
996
997 if ( (isset($GLOBALS[$name])) && ($reinsert_value == true) ) {
998   $field .= tep_output_string_protected(stripslashes($GLOBALS[$name]));
999 } elseif (tep_not_null($text)) {
1000   $field .= tep_output_string_protected($text);
1001 }
1002
1003 ------------------------------------------------------------------------------
1004 Open Redirector
1005 http://www.oscommerce.com/community/bugs,2970
1006 ------------------------------------------------------------------------------
1007
1008 Problem:
1009
1010 There is no URL checking being performed on the redirection page, and allows external sources to use the page as an open redirect relay.
1011
1012 Solution:
1013
1014 Lines 27-29 in catalog/redirect.php must be changed from:
1015
1016 if (isset($HTTP_GET_VARS['goto']) && tep_not_null($HTTP_GET_VARS['goto'])) {
1017   tep_redirect('http://' . $HTTP_GET_VARS['goto']);
1018 }
1019
1020 to:
1021
1022 if (isset($HTTP_GET_VARS['goto']) && tep_not_null($HTTP_GET_VARS['goto'])) {
1023   $check_query = tep_db_query("select products_url from " . TABLE_PRODUCTS_DESCRIPTION . " where products_url = '" . tep_db_input($HTTP_GET_VARS['goto']) . "' limit 1");
1024   if (tep_db_num_rows($check_query)) {
1025     tep_redirect('http://' . $HTTP_GET_VARS['goto']);
1026   }
1027 }
1028
1029 ------------------------------------------------------------------------------
1030 Extra Slashes In New Products
1031 ------------------------------------------------------------------------------
1032
1033 Problem:
1034
1035 When new products are entered and previewed, hitting the back button to edit the product data again adds extra slashes to apostrophes in the products name and description.
1036
1037 Solution:
1038
1039 The following lines must be replaced in catalog/admin/categories.php:
1040
1041 Line 504, from:
1042
1043 <td class="main"><?php echo tep_image(DIR_WS_CATALOG_LANGUAGES . $languages[$i]['directory'] . '/images/' . $languages[$i]['image'], $languages[$i]['name']) . '&nbsp;' . tep_draw_input_field('products_name[' . $languages[$i]['id'] . ']', (isset($products_name[$languages[$i]['id']]) ? $products_name[$languages[$i]['id']] : tep_get_products_name($pInfo->products_id, $languages[$i]['id']))); ?></td>
1044
1045 to:
1046
1047 <td class="main"><?php echo tep_image(DIR_WS_CATALOG_LANGUAGES . $languages[$i]['directory'] . '/images/' . $languages[$i]['image'], $languages[$i]['name']) . '&nbsp;' . tep_draw_input_field('products_name[' . $languages[$i]['id'] . ']', (isset($products_name[$languages[$i]['id']]) ? stripslashes($products_name[$languages[$i]['id']]) : tep_get_products_name($pInfo->products_id, $languages[$i]['id']))); ?></td>
1048
1049 Line 538, from:
1050
1051 <td class="main"><?php echo tep_draw_textarea_field('products_description[' . $languages[$i]['id'] . ']', 'soft', '70', '15', (isset($products_description[$languages[$i]['id']]) ? $products_description[$languages[$i]['id']] : tep_get_products_description($pInfo->products_id, $languages[$i]['id']))); ?></td>
1052
1053 to:
1054
1055 <td class="main"><?php echo tep_draw_textarea_field('products_description[' . $languages[$i]['id'] . ']', 'soft', '70', '15', (isset($products_description[$languages[$i]['id']]) ? stripslashes($products_description[$languages[$i]['id']]) : tep_get_products_description($pInfo->products_id, $languages[$i]['id']))); ?></td>
1056
1057 Line 574, from:
1058
1059 <td class="main"><?php echo tep_image(DIR_WS_CATALOG_LANGUAGES . $languages[$i]['directory'] . '/images/' . $languages[$i]['image'], $languages[$i]['name']) . '&nbsp;' . tep_draw_input_field('products_url[' . $languages[$i]['id'] . ']', (isset($products_url[$languages[$i]['id']]) ? $products_url[$languages[$i]['id']] : tep_get_products_url($pInfo->products_id, $languages[$i]['id']))); ?></td>
1060
1061 to:
1062
1063 <td class="main"><?php echo tep_image(DIR_WS_CATALOG_LANGUAGES . $languages[$i]['directory'] . '/images/' . $languages[$i]['image'], $languages[$i]['name']) . '&nbsp;' . tep_draw_input_field('products_url[' . $languages[$i]['id'] . ']', (isset($products_url[$languages[$i]['id']]) ? stripslashes($products_url[$languages[$i]['id']]) : tep_get_products_url($pInfo->products_id, $languages[$i]['id']))); ?></td>
1064
1065 ------------------------------------------------------------------------------
1066 Order Status Filtering
1067 http://www.oscommerce.com/community/bugs,1543
1068 ------------------------------------------------------------------------------
1069
1070 Problem:
1071
1072 After changing the order status filtering on the Administration Tool -> Customers -> Orders page, selecting "All Orders" would show an empty listing of orders.
1073
1074 Solution:
1075
1076 Line 357 in catalog/admin/orders.php must be changed from:
1077
1078 } elseif (isset($HTTP_GET_VARS['status'])) {
1079
1080 to:
1081
1082 } elseif (isset($HTTP_GET_VARS['status']) && is_numeric($HTTP_GET_VARS['status']) && ($HTTP_GET_VARS['status'] > 0)) {
1083
1084 ------------------------------------------------------------------------------
1085 MySQL 5.0 Compatibility
1086 ------------------------------------------------------------------------------
1087
1088 Problem:
1089
1090 MySQL 5.0 introduces Server SQL modes as part of its SQL 2003 standards support, and uses a more stricter approach to executing SQL queries. This is performed by default with setting STRICT_TRANS_TABLES as a Server SQL mode.
1091
1092 Due to this new setting, MySQL fails on certain SQL queries and produces error messages on the screen.
1093
1094 Solution:
1095
1096 Lines 213-223 in catalog/advanced_search_result.php must be changed from:
1097
1098 $from_str = "from " . TABLE_PRODUCTS . " p left join " . TABLE_MANUFACTURERS . " m using(manufacturers_id) left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id, " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_CATEGORIES . " c, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c";
1099
1100 if ( (DISPLAY_PRICE_WITH_TAX == 'true') && (tep_not_null($pfrom) || tep_not_null($pto)) ) {
1101   if (!tep_session_is_registered('customer_country_id')) {
1102     $customer_country_id = STORE_COUNTRY;
1103     $customer_zone_id = STORE_ZONE;
1104   }
1105   $from_str .= " left join " . TABLE_TAX_RATES . " tr on p.products_tax_class_id = tr.tax_class_id left join " . TABLE_ZONES_TO_GEO_ZONES . " gz on tr.tax_zone_id = gz.geo_zone_id and (gz.zone_country_id is null or gz.zone_country_id = '0' or gz.zone_country_id = '" . (int)$customer_country_id . "') and (gz.zone_id is null or gz.zone_id = '0' or gz.zone_id = '" . (int)$customer_zone_id . "')";
1106 }
1107
1108 $where_str = " where p.products_status = '1' and p.products_id = pd.products_id and pd.language_id = '" . (int)$languages_id . "' and p.products_id = p2c.products_id and p2c.categories_id = c.categories_id ";
1109
1110 to:
1111
1112 $from_str = "from " . TABLE_PRODUCTS . " p left join " . TABLE_MANUFACTURERS . " m using(manufacturers_id) left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id";
1113
1114 if ( (DISPLAY_PRICE_WITH_TAX == 'true') && (tep_not_null($pfrom) || tep_not_null($pto)) ) {
1115   if (!tep_session_is_registered('customer_country_id')) {
1116     $customer_country_id = STORE_COUNTRY;
1117     $customer_zone_id = STORE_ZONE;
1118   }
1119   $from_str .= " left join " . TABLE_TAX_RATES . " tr on p.products_tax_class_id = tr.tax_class_id left join " . TABLE_ZONES_TO_GEO_ZONES . " gz on tr.tax_zone_id = gz.geo_zone_id and (gz.zone_country_id is null or gz.zone_country_id = '0' or gz.zone_country_id = '" . (int)$customer_country_id . "') and (gz.zone_id is null or gz.zone_id = '0' or gz.zone_id = '" . (int)$customer_zone_id . "')";
1120 }
1121
1122 $from_str .= ", " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_CATEGORIES . " c, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c";
1123
1124 $where_str = " where p.products_status = '1' and p.products_id = pd.products_id and pd.language_id = '" . (int)$languages_id . "' and p.products_id = p2c.products_id and p2c.categories_id = c.categories_id ";
1125
1126 The following lines must be replaced in catalog/index.php:
1127
1128 Line 175, from:
1129
1130 $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS . " m, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id where p.products_status = '1' and p.manufacturers_id = m.manufacturers_id and m.manufacturers_id = '" . (int)$HTTP_GET_VARS['manufacturers_id'] . "' and p.products_id = p2c.products_id and pd.products_id = p2c.products_id and pd.language_id = '" . (int)$languages_id . "' and p2c.categories_id = '" . (int)$HTTP_GET_VARS['filter_id'] . "'";
1131
1132 to:
1133
1134 $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS . " p left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id, " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS . " m, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c where p.products_status = '1' and p.manufacturers_id = m.manufacturers_id and m.manufacturers_id = '" . (int)$HTTP_GET_VARS['manufacturers_id'] . "' and p.products_id = p2c.products_id and pd.products_id = p2c.products_id and pd.language_id = '" . (int)$languages_id . "' and p2c.categories_id = '" . (int)$HTTP_GET_VARS['filter_id'] . "'";
1135
1136 Line 178, from:
1137
1138 $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS . " m left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id where p.products_status = '1' and pd.products_id = p.products_id and pd.language_id = '" . (int)$languages_id . "' and p.manufacturers_id = m.manufacturers_id and m.manufacturers_id = '" . (int)$HTTP_GET_VARS['manufacturers_id'] . "'";
1139
1140 to:
1141
1142 $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS . " p left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id, " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS . " m where p.products_status = '1' and pd.products_id = p.products_id and pd.language_id = '" . (int)$languages_id . "' and p.manufacturers_id = m.manufacturers_id and m.manufacturers_id = '" . (int)$HTTP_GET_VARS['manufacturers_id'] . "'";
1143
1144 Line 184, from:
1145
1146 $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS . " m, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id where p.products_status = '1' and p.manufacturers_id = m.manufacturers_id and m.manufacturers_id = '" . (int)$HTTP_GET_VARS['filter_id'] . "' and p.products_id = p2c.products_id and pd.products_id = p2c.products_id and pd.language_id = '" . (int)$languages_id . "' and p2c.categories_id = '" . (int)$current_category_id . "'";
1147
1148 to:
1149
1150 $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS . " p left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id, " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS . " m, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c where p.products_status = '1' and p.manufacturers_id = m.manufacturers_id and m.manufacturers_id = '" . (int)$HTTP_GET_VARS['filter_id'] . "' and p.products_id = p2c.products_id and pd.products_id = p2c.products_id and pd.language_id = '" . (int)$languages_id . "' and p2c.categories_id = '" . (int)$current_category_id . "'";
1151
1152 Line 187, from:
1153
1154 $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_PRODUCTS . " p left join " . TABLE_MANUFACTURERS . " m on p.manufacturers_id = m.manufacturers_id, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id where p.products_status = '1' and p.products_id = p2c.products_id and pd.products_id = p2c.products_id and pd.language_id = '" . (int)$languages_id . "' and p2c.categories_id = '" . (int)$current_category_id . "'";
1155
1156 to:
1157
1158 $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price from " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_PRODUCTS . " p left join " . TABLE_MANUFACTURERS . " m on p.manufacturers_id = m.manufacturers_id left join " . TABLE_SPECIALS . " s on p.products_id = s.products_id, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c where p.products_status = '1' and p.products_id = p2c.products_id and pd.products_id = p2c.products_id and pd.language_id = '" . (int)$languages_id . "' and p2c.categories_id = '" . (int)$current_category_id . "'";
1159
1160 Line 292 in catalog/admin/categories.php must be changed from:
1161
1162 tep_db_query("insert into " . TABLE_PRODUCTS . " (products_quantity, products_model,products_image, products_price, products_date_added, products_date_available, products_weight, products_status, products_tax_class_id, manufacturers_id) values ('" . tep_db_input($product['products_quantity']) . "', '" . tep_db_input($product['products_model']) . "', '" . tep_db_input($product['products_image']) . "', '" . tep_db_input($product['products_price']) . "',  now(), '" . tep_db_input($product['products_date_available']) . "', '" . tep_db_input($product['products_weight']) . "', '0', '" . (int)$product['products_tax_class_id'] . "', '" . (int)$product['manufacturers_id'] . "')");
1163
1164 to:
1165
1166 tep_db_query("insert into " . TABLE_PRODUCTS . " (products_quantity, products_model,products_image, products_price, products_date_added, products_date_available, products_weight, products_status, products_tax_class_id, manufacturers_id) values ('" . tep_db_input($product['products_quantity']) . "', '" . tep_db_input($product['products_model']) . "', '" . tep_db_input($product['products_image']) . "', '" . tep_db_input($product['products_price']) . "',  now(), " . (empty($product['products_date_available']) ? "null" : "'" . tep_db_input($product['products_date_available']) . "'") . ", '" . tep_db_input($product['products_weight']) . "', '0', '" . (int)$product['products_tax_class_id'] . "', '" . (int)$product['manufacturers_id'] . "')");
1167
1168 The following SQL queries need to be performed:
1169
1170 ALTER TABLE whos_online MODIFY COLUMN last_page_url VARCHAR(255) NOT NULL;
1171
1172 ALTER TABLE customers MODIFY COLUMN customers_default_address_id INTEGER;
1173
1174 ALTER TABLE customers_basket MODIFY COLUMN final_price DECIMAL(15,4);