· 10 years ago · Mar 19, 2016, 10:08 AM
1<?php
2/*****************************************************************************\
3+-----------------------------------------------------------------------------+
4| X-Cart |
5| Copyright (c) 2001-2005 Ruslan R. Fazliev <rrf@rrf.ru> |
6| All rights reserved. |
7+-----------------------------------------------------------------------------+
8| PLEASE READ THE FULL TEXT OF SOFTWARE LICENSE AGREEMENT IN THE "COPYRIGHT" |
9| FILE PROVIDED WITH THIS DISTRIBUTION. THE AGREEMENT TEXT IS ALSO AVAILABLE |
10| AT THE FOLLOWING URL: http://www.x-cart.com/license.php |
11| |
12| THIS AGREEMENT EXPRESSES THE TERMS AND CONDITIONS ON WHICH YOU MAY USE |
13| THIS SOFTWARE PROGRAM AND ASSOCIATED DOCUMENTATION THAT RUSLAN R. |
14| FAZLIEV (hereinafter referred to as "THE AUTHOR") IS FURNISHING OR MAKING |
15| AVAILABLE TO YOU WITH THIS AGREEMENT (COLLECTIVELY, THE "SOFTWARE"). |
16| PLEASE REVIEW THE TERMS AND CONDITIONS OF THIS LICENSE AGREEMENT |
17| CAREFULLY BEFORE INSTALLING OR USING THE SOFTWARE. BY INSTALLING, |
18| COPYING OR OTHERWISE USING THE SOFTWARE, YOU AND YOUR COMPANY |
19| (COLLECTIVELY, "YOU") ARE ACCEPTING AND AGREEING TO THE TERMS OF THIS |
20| LICENSE AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY THIS |
21| AGREEMENT, DO NOT INSTALL OR USE THE SOFTWARE. VARIOUS COPYRIGHTS AND |
22| OTHER INTELLECTUAL PROPERTY RIGHTS PROTECT THE SOFTWARE. THIS |
23| AGREEMENT IS A LICENSE AGREEMENT THAT GIVES YOU LIMITED RIGHTS TO USE |
24| THE SOFTWARE AND NOT AN AGREEMENT FOR SALE OR FOR TRANSFER OF TITLE.|
25| THE AUTHOR RETAINS ALL RIGHTS NOT EXPRESSLY GRANTED BY THIS AGREEMENT. |
26| |
27| The Initial Developer of the Original Code is Ruslan R. Fazliev |
28| Portions created by Ruslan R. Fazliev are Copyright (C) 2001-2005 |
29| Ruslan R. Fazliev. All Rights Reserved. |
30+-----------------------------------------------------------------------------+
31\*****************************************************************************/
32
33#
34# $Id: func.php,v 1.395.2.176 2005/03/23 08:35:33 mclap Exp $
35#
36
37if ( !defined('XCART_START') ) { header("Location: ../"); die("Access denied"); }
38
39#
40# SPM function to generate main menu link images
41#
42function generateMMImage($text,$id){
43
44 $pointSize = 11.5;
45 #$font = "Baskerville-Light.ttf";
46 $font = "../fonts/Baskerville-Normal.ttf";
47
48 $bbox=imagettfbbox($pointSize,0,$font,$text);
49 $textWidth = $bbox[2] - $bbox[0];
50 $textHeight = abs($bbox[7] - $bbox[1]);
51 $img = imagecreate($textWidth+1,21);
52
53 # Grey version
54
55 //$background = imagecolorallocate($img,211,211,213);
56 //$shadow = imagecolorallocate($img,109,109,116);
57 //$typeColour = imagecolorallocate($img,255,255,255);
58
59 # Blue version
60
61 $background = imagecolorallocate($img,202,227,243);
62 $shadowColour = imagecolorallocate($img,255,255,255);
63 $typeColour = imagecolorallocate($img,76,140,191);
64
65 imagefill($img,0,0,$background);
66 imagettftext ($img, $pointSize, 0, 1, 14, $shadowColour, $font, $text);
67 imagettftext ($img, $pointSize, 0, 0, 13, $typeColour, $font, $text);
68
69 #imagepng($img,"/var/www/shop/panel_images/MM_".$id.".png");
70 imagepng($img,"../panel_images/MM_".$id.".png");
71 imagedestroy($img);
72}
73
74#
75# SPM functions to show/replace CMS tags with html tags
76#
77
78function replaceCMSTags($string){
79 $string = str_replace("[H]","<font class='subHead'>",$string);
80 $string = str_replace("[/H]","</font>",$string);
81 $string = str_replace("[B]","<strong>",$string);
82 $string = str_replace("[/B]","</strong>",$string);
83 $string = str_replace("[U]","<u>",$string);
84 $string = str_replace("[/U]","</u>",$string);
85 $string = str_replace("[I]","<I>",$string);
86 $string = str_replace("[/I]","</I>",$string);
87 $string = str_replace("[w-","<a href=",$string);
88 $string = str_replace("[/w]","</a>",$string);
89 $string = str_replace("/w]",">",$string);
90
91 return $string;
92}
93
94function showCMSTags($string){
95 $string = str_replace("<font class='subHead'>","[H]",$string);
96 $string = str_replace("</font>","[/H]",$string);
97 $string = str_replace("<strong>","[B]",$string);
98 $string = str_replace("</strong>","[/B]",$string);
99 $string = str_replace("<u>","[U]",$string);
100 $string = str_replace("</u>","[/U]",$string);
101 $string = str_replace("<I>","[I]",$string);
102 $string = str_replace("</I>","[/I]",$string);
103 $string = str_replace("<a href=","[w-",$string);
104 $string = str_replace("</a>","[/w]",$string);
105 $string = str_replace("'>","'/w]",$string);
106
107 return $string;
108}
109
110function showCMSBullets($string,$size,$class=""){
111 while(strstr($string,"<UL class='$class'>")){
112 $start = strpos($string,"<UL class='$class'>");
113 $end = strpos($string,"</UL>");
114 $length = $end - $start;
115 $text = substr($string,$start,$length);
116 $bullets = str_replace("</FONT></LI>\n<LI><FONT class='body$size'>","",$text);
117 $string = str_replace($text,$bullets,$string);
118 $string = str_replace("<UL class='$class'><LI><FONT class='body$size'>","[BL]",$string);
119 $string = str_replace("</FONT></LI></UL>","[/BL]",$string);
120 $string = str_replace("<UL class='$class'>","[BL]",$string);//remove any rogue ones to stop loop
121 $string = str_replace("</UL>","[/BL]",$string);//remove any rogue ones to stop loop
122 }
123 return $string;
124}
125
126function replaceCMSBullets($string,$size,$class=""){
127
128 while(strstr($string,"[BL]")){
129 $start = strpos($string,"[BL]");
130 $end = strpos($string,"[/BL]");
131 $length = $end - $start;
132 $text = substr($string,$start,$length);
133 $bullets = str_replace("<br />","</FONT></LI>\n<LI><FONT class='body$size'>",$text);
134 $string = str_replace($text,$bullets,$string);
135 $string = str_replace("[BL]","<UL class='$class'><LI><FONT class='body$size'>",$string);
136 $string = str_replace("[/BL]","</FONT></LI></UL>",$string);
137 }
138 return $string;
139}
140
141#
142# SPM functions for section header and panel corner image creation
143#
144function hex2rgb($hex){
145
146 // break into hex 3-tuple
147 $cutpoint = ceil(strlen($hex) / 2)-1;
148 $rgb = explode(':', wordwrap($hex, $cutpoint, ':', $cutpoint), 3);
149
150 // convert each tuple to decimal
151 $rgb[0] = (isset($rgb[0]) ? hexdec($rgb[0]) : 0);
152 $rgb[1] = (isset($rgb[1]) ? hexdec($rgb[1]) : 0);
153 $rgb[2] = (isset($rgb[2]) ? hexdec($rgb[2]) : 0);
154
155 return $rgb;
156}
157
158function saveHeaderImages($id,$colour){
159 global $imgPrefix;
160 # Best settings:
161 //$left = imagecreatetruecolor(11, 23);
162 //imagefilledellipse ( $left, 11, 11, 23, 25, $fill );
163
164 #change the hex colour to rgb
165 $rgb = hex2rgb($colour);
166 #set up the image
167 $left = imagecreatetruecolor(11, 23);
168 $bg = imagecolorallocate($left,255,255,255);
169 $fill = imagecolorallocate($left,$rgb[0],$rgb[1],$rgb[2]);
170 imagefill($left,0,0,$bg);
171
172 #draw coloured ellipse
173 imagefilledellipse ( $left, 11, 11, 23, 25, $fill );
174 #save file, rotate and save again
175 imagepng($left,"/var/www/shop/skin1/images/".$imgPrefix."section_end_left_".$id.".png");
176 $right = imagerotate($left,180,0);
177 imagepng($right,"/var/www/shop/skin1/images/".$imgPrefix."section_end_right_".$id.".png");
178 imagedestroy($left);
179
180}
181
182function createPanelCorners($id,$colour,$tintBy){
183 global $imgPrefix;
184 global $tintRGB;
185
186 #change the hex colour to rgb
187 $rgb = hex2rgb($colour);
188
189 # create image and fill with white
190 $dark = imagecreatetruecolor(9, 9);
191 $light = imagecreatetruecolor(9, 9);
192 $darkBG = imagecolorallocate($dark,255,255,255);
193 $lightBG = imagecolorallocate($light,255,255,255);
194 $full = imagecolorallocate($dark,$rgb[0],$rgb[1],$rgb[2]);
195 foreach($rgb as $k => $v){
196 $newVal = $rgb[$k] * $tintBy;
197 if($newVal >= 255){$newVal=255;}
198 $tint[$k] = intval($newVal);
199 }
200
201 $tint = imagecolorallocatealpha($light,$rgb[0],$rgb[1],$rgb[2],50);
202 imagefill($dark,0,0,$darkBG);
203 imagefill($light,0,0,$lightBG);
204
205
206 #draw coloured ellipse
207 imagefilledellipse ( $dark, 9, 9, 19, 19, $full );
208 imagefilledellipse ( $light, 9, 9, 19, 19, $tint );
209
210 # get colour from tinted image to save to database
211 $tintRGB = imagecolorat($light,5,5);
212 $r = ($tintRGB >> 16) & 0xFF;
213 $g = ($tintRGB >> 8) & 0xFF;
214 $b = $tintRGB & 0xFF;
215 $tintRGB = dechex($r).dechex($g).dechex($b);
216
217 #save and rotate for each file needed
218 imagepng($dark,"/var/www/shop/skin1/images/".$imgPrefix."section_panel_tl".$id.".png");
219 $bl = imagerotate($dark,-90,0);
220 imagepng($bl,"/var/www/shop/skin1/images/".$imgPrefix."section_panel_tr".$id.".png");
221 $br = imagerotate($dark,180,0);
222 imagepng($br,"/var/www/shop/skin1/images/".$imgPrefix."section_panel_br".$id.".png");
223 $tr = imagerotate($dark,90,0);
224 imagepng($tr,"/var/www/shop/skin1/images/".$imgPrefix."section_panel_bl".$id.".png");
225
226 imagepng($light,"/var/www/shop/skin1/images/".$imgPrefix."section_panel_tint_tl".$id.".png");
227 $bl_tint = imagerotate($light,-90,0);
228 imagepng($bl_tint,"/var/www/shop/skin1/images/".$imgPrefix."section_panel_tint_tr".$id.".png");
229 $br_tint = imagerotate($light,180,0);
230 imagepng($br_tint,"/var/www/shop/skin1/images/".$imgPrefix."section_panel_tint_br".$id.".png");
231 $tr_tint = imagerotate($light,90,0);
232 imagepng($tr_tint,"/var/www/shop/skin1/images/".$imgPrefix."section_panel_tint_bl".$id.".png");
233
234 imagedestroy($dark);
235 imagedestroy($tr);
236 imagedestroy($br);
237 imagedestroy($bl);
238 imagedestroy($light);
239 imagedestroy($tr_tint);
240 imagedestroy($br_tint);
241 imagedestroy($bl_tint);
242}
243
244function createCategoryHeader($id,$colour,$text,$lng){
245
246 #change the hex colour to rgb
247 $rgb = hex2rgb($colour);
248
249 # set up text
250 $pointSize = 22;
251 $font = "../fonts/NewsGothicBT.ttf";
252
253 $bbox=imagettfbbox($pointSize,0,$font,$text);
254
255 $textWidth = $bbox[2] - $bbox[0];
256 $textHeight = abs($bbox[7] - $bbox[1]);
257 $baseline = abs(0 - $bbox[7]);
258
259 $img = imagecreate($textWidth+2,$textHeight+2);
260 $bg = imagecolorallocate($img,$rgb[0],$rgb[1],$rgb[2]);
261 $white = imagecolorallocate($img,255,255,255);
262
263 imagefill($img,0,0,$bg);
264
265 imagettftext ($img, $pointSize, 0, 0, $baseline, $white, $font, $text);
266 imagepng($img,"/var/www/shop/skin1/images/".$lng."/tt_category_header".$id.".png");
267 imagedestroy($img);
268
269}
270
271#
272# update panel clicks function
273#
274
275function update_panel_clicks($panelId){
276 global $sql_tbl;
277 db_query("UPDATE $sql_tbl[panels] set clicks=$sql_tbl[panels].clicks+1 where panelId=$panelId");
278}
279
280#
281# Database abstract layer functions
282#
283function db_connect($sql_host, $sql_user, $sql_password) {
284 return mysql_connect($sql_host, $sql_user, $sql_password);
285}
286
287function db_select_db($sql_db) {
288 return mysql_select_db($sql_db) || die("Could not connect to SQL db");
289}
290
291function db_query($query) {
292 global $debug_mode;
293 global $mysql_autorepair;
294
295 if(defined("START_TIME")) {
296 global $__sql_time;
297 $t = func_microtime();
298 }
299 $result = mysql_query($query);
300 if(defined("START_TIME")) {
301 $__sql_time += func_microtime()-$t;
302 }
303
304 #
305 # Auto repair
306 #
307 if( !$result && $mysql_autorepair && preg_match("/'(\S+)\.(MYI|MYD)/",mysql_error(), $m) ){
308 $stm = "REPAIR TABLE $m[1]";
309 error_log("Repairing table $m[1]", 0);
310 if ($debug_mode == 1 || $debug_mode == 3) {
311 $mysql_error = mysql_errno()." : ".mysql_error();
312 echo "<B><FONT COLOR=DARKRED>Repairing table $m[1]...</FONT></B>$mysql_error<BR>";
313 flush();
314 }
315 $result = mysql_query($stm);
316 if (!$result)
317 error_log("Repaire table $m[1] is failed: ".mysql_errno()." : ".mysql_error(), 0);
318 else
319 $result = mysql_query($query); # try repeat query...
320 }
321 if (db_error($result, $query) && $debug_mode==1)
322 exit;
323 return $result;
324}
325
326function db_result($result, $offset) {
327 return mysql_result($result, $offset);
328}
329
330function db_fetch_row($result) {
331 return mysql_fetch_row($result);
332}
333
334function db_fetch_array($result, $flag=MYSQL_ASSOC) {
335 return mysql_fetch_array($result, $flag);
336}
337
338function db_free_result($result) {
339 @mysql_free_result($result);
340}
341
342function db_num_rows($result) {
343 return mysql_num_rows($result);
344}
345
346function db_insert_id() {
347 return mysql_insert_id();
348}
349
350function db_affected_rows() {
351 return mysql_affected_rows();
352}
353
354function db_error($mysql_result, $query) {
355 global $debug_mode, $error_file_size_limit, $error_file_path, $PHP_SELF;
356 global $config, $login, $REMOTE_ADDR, $current_location;
357
358 if ($mysql_result)
359 return false;
360 else {
361 $back_trace = func_get_backtrace();
362
363 $mysql_error = mysql_errno()." : ".mysql_error();
364 if (@$config["Email_Note"]["admin_sqlerror_notify"]=="Y") {
365 x_session_register("login");
366 $err_str = "Date : ".date("d-M-Y H:i:s")."\n";
367 $err_str .= "Site : ".$current_location."\n";
368 $err_str .= "Script : ".$PHP_SELF."\n";
369 $err_str .= "Remote IP : $REMOTE_ADDR\n";
370 $err_str .= "Logged as : $login\n";
371 $err_str .= "SQL query : $query\n";
372 $err_str .= "Error code : ".mysql_errno()."\n";
373 $err_str .= "Description :\n\n".mysql_error()."\n";
374 $err_str .= "Backtrace :\n".implode("\n", $back_trace);
375 func_send_simple_mail($config["Company"]["site_administrator"], $config["Company"]["company_name"].": SQL Error notification", $err_str, $config["Company"]["site_administrator"]);
376 }
377 if ($debug_mode == 1 || $debug_mode == 3) {
378 echo "<B><FONT COLOR=DARKRED>INVALID SQL: </FONT></B>$mysql_error<BR>";
379 echo "<B><FONT COLOR=DARKRED>SQL QUERY FAILURE:</FONT></B> $query <BR>";
380 flush();
381 }
382 if ($debug_mode == 2 || $debug_mode == 3) {
383 $filename = $error_file_path."/x-errors_sql.txt";
384 if ($error_file_size_limit!=0 && @filesize($filename)>$error_file_size_limit*1024)
385 @unlink($filename);
386 if ($fp = @fopen($filename, "a+")) {
387 $err_str = date("[d-M-Y H:i:s]")." SQL error: $PHP_SELF\n".$query."\n".$mysql_error;
388 $err_str .= "\nBacktrace:\n".implode("\n", $back_trace);
389 $err_str .= "\n-------------------------------------------------\n";
390 fwrite($fp, $err_str);
391 fclose($fp);
392 }
393 }
394 }
395 return true;
396}
397
398#
399# SPM same as func_query but adds given column name to top level array keys. produces array like this:
400#
401
402/*
403
404Array
405(
406 [x] => Array
407 (
408 [0] => Array
409 (
410 [colName] => x
411 )
412
413 [1] => Array
414 (
415 [colName] => x
416 )
417 )
418
419 [y] => Array
420 (
421 [0] => Array
422 (
423 [colName] => y
424 )
425
426 [1] => Array
427 (
428 [colName] => y
429 )
430 )
431
432*/
433
434function func_query_keyed($colName,$query) {
435
436 $result = false;
437 if ($p_result = db_query($query)) {
438 while($arr = db_fetch_array($p_result))
439 $result[$arr[$colName]][]=$arr;
440 db_free_result($p_result);
441 }
442
443 return $result;
444
445}
446
447#
448# Execute mysql query and store result into associative array with
449# column names as keys...
450#
451
452function func_query($query) {
453
454 $result = false;
455 if ($p_result = db_query($query)) {
456 while($arr = db_fetch_array($p_result))
457 $result[]=$arr;
458 db_free_result($p_result);
459 }
460
461 return $result;
462
463}
464
465#
466# Execute mysql query and store result into associative array with
467# column names as keys and then return first element of this array
468# If array is empty return array().
469#
470function func_query_first($query) {
471
472 if ($p_result = db_query($query)) {
473 $result = db_fetch_array($p_result);
474 db_free_result($p_result);
475 }
476 return is_array($result)?$result:array();
477
478}
479
480#
481# Execute mysql query and store result into associative array with
482# column names as keys and then return first cell of first element of this array
483# If array is empty return false.
484#
485function func_query_first_cell($query) {
486 if ($p_result = db_query($query)) {
487 $result = db_fetch_row($p_result);
488 db_free_result($p_result);
489 }
490 return is_array($result)?$result[0]:false;
491}
492
493#
494# This function replaced standard PHP function header("Location...")
495#
496function func_header_location($location) {
497
498 global $XCART_SESSION_NAME, $XCARTSESSID, $HTTP_COOKIE_VARS;
499 global $use_sessions_type, $is_location;
500 global $HTTP_SERVER_VARS;
501
502 $is_location = 'Y';
503 x_session_save();
504
505 if ($use_sessions_type < 3) {
506 session_write_close();
507 }
508
509 if (!empty($XCARTSESSID) && !isset($HTTP_COOKIE_VARS[$XCART_SESSION_NAME]) && !eregi("$XCART_SESSION_NAME=", $location)) {
510 $location .= ((strpos($location, '?') != false)?'&':'?')."$XCART_SESSION_NAME=".$XCARTSESSID;
511 }
512
513 $header_location = (strpos($HTTP_SERVER_VARS["HTTP_USER_AGENT"],'Opera')!==false || @preg_match("/Microsoft|WebSTAR|Xitami/", getenv("SERVER_SOFTWARE")) ? "Refresh: 0; URL=" : "Location: ");
514 if (!headers_sent()) {
515 header($header_location.$location);
516 exit();
517 }
518 else {
519 echo "<BR><BR><DIV align='center'><FONT class='standardMessage'>".func_get_langvar_by_name("txt_header_location_note", array("time" => 5, "location" => $location))."</FONT></DIV>";
520 echo "<META http-equiv=\"Refresh\" content=\"0;URL=$location\">";
521 }
522
523 func_flush();
524 exit();
525
526}
527
528#
529# Get image size abstract function
530#
531function func_get_image_size($filename) {
532 list($width, $height, $type) = getimagesize($filename);
533 switch($type) {
534 case "1": $type = "image/gif";
535 break;
536 case "2": $type = "image/pjpeg";
537 break;
538 case "3": $type = "image/png";
539 break;
540 case "4": $type = "application/x-shockwave-flash";
541 break;
542 case "5": $type = "image/psd";
543 break;
544 case "6": $type = "image/bmp";
545 break;
546 default: $type = "";
547 }
548 if (!empty($type))
549 return array(@filesize($filename),$width,$height,$type);
550 else
551 return false;
552}
553
554#
555# Determine that $userfile is image file with non zero size
556#
557function func_is_image_userfile($userfile, $userfile_size, $userfile_type) {
558 return (($userfile != "none") && ($userfile != "") && ($userfile_size > 0) && (substr($userfile_type, 0, 6) == 'image/' || $userfile_type == 'application/x-shockwave-flash'));
559}
560
561function func_mail_quote($string, $charset) {
562 return "=?".$charset."?B?".base64_encode($string)."?=";
563}
564
565#
566# SPM - function to check CSV content
567#
568function makeDataCSVCompatible($csvData) {
569 $csvData = str_replace("\n", " ", $csvData);
570 $csvData = str_replace("\r", "", $csvData);
571 $csvData = str_replace("\"", "\"\"", $csvData);
572 return($csvData);
573}
574
575
576#
577# SPM - function to create content for csv order file
578#
579function createCSVContent($order,$products){
580
581 if (($order["orderid"] > 0) && (count($order) > 0) && (count($products) > 0)) {
582 foreach ($products as $thisItem) {
583
584 $orderid = $order["orderid"];
585
586 /*
587 # add zeros to front of oerder id to make up the bytes to 9
588 for($i=0;$i< intval(9 - strlen($order["orderid"]));$i++){
589 $orderid = "0".$orderid;
590 }
591 */
592
593 # if no delivery address present, use billing address
594 if($order["s_address"] == ""){
595 $order["s_address"] = $order["b_address"];
596 $order["s_address_2"] = $order["b_address_2"];
597 $order["s_city"] = $order["b_city"];
598 $order["s_county"] = $order["b_county"];
599 $order["s_zipcode"] = $order["b_zipcode"];
600 $order["s_country"] = $order["b_country"];
601 }
602
603 # concat delivery address from order elements
604 $delivery_address = $order["s_firstname"]." ".$order["s_lastname"].",".$order["s_address"].",".$order["s_address_2"].",".$order["s_city"].",".$order["s_county"].",".$order["s_zipcode"].",".$order["phone"].",".$order["email"];
605
606 $content .= 'd' . substr(makeDataCSVCompatible($orderid), 0, 9) . date("dm",$order["date"]) . ','; // Order Number
607 $content .= '' . substr(makeDataCSVCompatible(date("dmy",$order["date"])), 0, 6) . ','; // Order Date
608 $content .= '"d' . substr(makeDataCSVCompatible($orderid), 0, 9) . ',' . substr(makeDataCSVCompatible($delivery_address), 0, 200) . '",'; // Delivery Details (Name and Address etc)
609 $content .= '0,'; // Delivery Sequence
610 $content .= 'N,'; // Forward/Normal Order
611 $content .= '' . substr(makeDataCSVCompatible(date("dmy",$order["date"])), 0, 6) . ','; // Date Delivery Required
612 $content .= ','; // Class 1
613 $content .= ','; // Class 2
614 $content .= ','; // Class 3
615 $content .= ','; // Product Name
616 $content .= $order["coupon"].','; // IPaq Reference
617 $content .= '' . substr(makeDataCSVCompatible($thisItem["productcode"]), 0, 15) . ','; // Product Code
618 $content .= '' . substr(makeDataCSVCompatible($thisItem["amount"]), 0, 5) . ','; // Quantity
619 $content .= '' . "\r\n"; // Order Reference
620 }
621 if (strlen($content) > 0) {
622 // Save file in csv directory with order number
623 $thisFilename = CSV_DIR . $orderid . ".csv";
624 if (!is_file($thisFilename)) {
625 $fp = @fopen ($thisFilename, "w");
626 $write = @fwrite( $fp, $content);
627 @fclose( $fp );
628
629 if (is_file($thisFilename)) {
630 $outcome["success"] = TRUE;
631 $outcome["file"] = $thisFilename;
632 } else {
633 $outcome["success"] = FALSE;
634 $outcome["errorCode"] = "004";// failed to create file
635 }
636 } else {
637 $outcome["success"] = FALSE;
638 $outcome["errorCode"] = "003";// file exists
639 }
640 } else {
641 $outcome["success"] = FALSE;
642 $outcome["errorCode"] = "002";// failed to create csv content
643 }
644 } else {
645 $outcome["success"] = FALSE;
646 $outcome["errorCode"] = "001";// order or products empty
647 }
648 return $outcome;
649}
650
651#
652# SPM - function to prepare CSV email
653#
654
655function prepOrderEmail($filePath,$fileName,$from,$message){
656
657 $lend = "\n";
658 $break = "\n\n";
659
660 // mime boundary
661 $semi_rand = md5(time());
662 $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
663
664 // filePath must include the file name
665 // fixed by mhedley@jackel in accordance with RFC4180
666 // text/csv appropriate MIME for $fileType
667 //
668 $fileType = "text/csv";
669 $file = fopen($filePath,'rb');
670 $data = fread($file,filesize($filePath));
671 fclose($file);
672
673 $data = chunk_split(base64_encode($data));
674
675 // headers
676 $mail_elements["headers"] .= "From: ".$from.$lend;
677 $mail_elements["headers"] .= "X-Mailer: PHP/".phpversion().$lend;
678 $mail_elements["headers"] .= "MIME-Version: 1.0".$lend;
679 $mail_elements["headers"] .= "Content-Type: multipart/mixed; boundary=".$mime_boundary;
680
681 // message part
682 $mail_elements["body"] .= "--{$mime_boundary}".$lend;
683 $mail_elements["body"] .= "Content-Type:text/html; charset=\"iso-8859-1\"".$lend;
684 $mail_elements["body"] .= "Content-Transfer-Encoding: 7bit".$break;
685 $mail_elements["body"] .= $message.$break;
686
687 // attachment part
688 $mail_elements["body"] .= "--{$mime_boundary}".$lend;
689 $mail_elements["body"] .= "Content-Type: ".$fileType."; name=\"".$fileName."\"\n";
690 $mail_elements["body"] .= "Content-Disposition: attachment; filename=\"{$fileatt_name}\"\n";
691 $mail_elements["body"] .= "Content-Transfer-Encoding: base64".$break;
692 $mail_elements["body"] .= $data . "\n\n";
693 $mail_elements["body"] .= "--{$mime_boundary}--".$lend;
694
695 return $mail_elements;
696}
697
698#
699# SPM - function to send CSV email
700#
701
702function func_send_csv_mail($order,$products){
703 global $mail_smarty, $sql_tbl;
704 global $config;
705
706 $csvResult = createCSVContent($order,$products);
707
708 $lend = "\n";
709
710
711 if (is_file($csvResult["file"])) {
712 // CSV file created, so needs to be attatched to email as order.csv
713 // Therefore, have to check the current order.csv directory to make sure one does not exist
714 // as that means the system is in the middle of sending an order
715
716 $orderCSVAttempt = 0;
717
718 while ((is_file(CSV_DIR . CSV_FILENAME)) && ($orderCSVAttempt < 5)) {
719 sleep(1);
720 $orderCSVAttempt++;
721 }
722 }
723 if (!(is_file(CSV_DIR . CSV_FILENAME))) {
724 if (copy($csvResult["file"], CSV_DIR . CSV_FILENAME)) {
725
726 $to = $config["Company"]["csv_orders_email"];
727 $subject = "Tommee Tippee Web Order #" .$order["orderid"];
728 $message = "The attached file contains order information for order: ".$order["orderid"].$break;
729 $from = "weborder@tommeetippee.com <$to>";
730
731 $mail_elements = prepOrderEmail(CSV_DIR . CSV_FILENAME, CSV_FILENAME, $from, $message);
732
733 $success = mail($to,$subject,$mail_elements["body"],$mail_elements["headers"]);
734 # send duplicate for testing
735 mail("smarlow@different-uk.com",$subject,$mail_elements["body"],$mail_elements["headers"]);
736
737 if(!$success){
738 $to = $config["Company"]["error_email"];
739 $from = "Order System <$to>";
740 $subject = "IMPORTANT: Order failure";
741 $message_header = "Content-Type: text/plain;".$lend;
742 $headers = "From: ".$from.$lend."X-Mailer: PHP/".phpversion().$lend."MIME-Version: 1.0".$lend.$message_header;
743 $body = "The website encountered an error (Error id: $csvResult[errorCode]) sending the CSV file to the JBA system for order number: ".$order["orderid"]."\r\n\r\n";
744 $body .= "This order will need to be manually processed - the details can be found in the Administration System under 'Orders'.\r\n\r\n";
745 $body .= "Please inform the site manager and/or developer to ensure this error is corrected.";
746 mail($to,$subject,$body,$headers);
747 }
748 unlink(CSV_DIR . CSV_FILENAME);
749 unlink($csvResult["file"]);
750 }
751 }
752}
753
754#
755# Send mail abstract function
756# $from - from/reply-to address
757#
758function func_send_mail($to, $subject_template, $body_template, $from, $to_admin, $crypted=false) {
759 global $mail_smarty, $sql_tbl;
760 global $config;
761 global $current_language, $store_language, $shop_language;
762 global $to_customer;
763 global $override_lng_code;
764
765 if (empty($to)) return;
766
767 $encrypt_mail = $crypted && $config["Security"]["crypt_method"];
768
769 $lng_code = "";
770 if ($to_admin) {
771 $lng_code = ($current_language?$current_language:$config["default_admin_language"]);
772 }
773 elseif ($to_customer) {
774 $lng_code = $to_customer;
775 }
776 else {
777 $lng_code = $shop_language;
778 }
779
780 $charset = func_query_first_cell ("SELECT charset FROM $sql_tbl[countries] WHERE code='$lng_code'");
781 $override_lng_code = $lng_code;
782
783 $mail_smarty->assign_by_ref ("config", $config);
784
785 if ($config["Email"]["html_mail"] == "Y" && !$encrypt_mail) {
786 # Select HTML-style templates is this option is enabled.
787 if (file_exists($mail_smarty->template_dir."/mail/html/".basename($body_template))) {
788 $mail_smarty->assign("mail_body_template","mail/html/".basename($body_template));
789 $body_template = "mail/html/html_message_template.tpl";
790 }
791 }
792 $mail_message = func_display($body_template,$mail_smarty,false);
793 $mail_subject = chop(func_display($subject_template,$mail_smarty,false));
794
795 if (X_DEF_OS_WINDOWS) {
796 $mail_message=str_replace("\n","\r\n",$mail_message);
797 $lend = "\r\n";
798 }
799 else
800 $lend = "\n";
801
802 $files = array();
803 if($config["Email"]["html_mail"] == "Y") {
804 list($mail_message, $tmp) = func_attach_images($mail_message);
805 if(!empty($tmp)) {
806 foreach($tmp as $k => $v)
807 $files[] = $v;
808 }
809 }
810
811 if($encrypt_mail)
812 $mail_message = func_pgp_encrypt ($mail_message);
813
814 if ($config["Email"]["html_mail"] == "Y" && !$encrypt_mail)
815 $message_header = "Content-Type: text/html; charset=".$charset.$lend;
816 else
817 $message_header = "Content-Type: text/plain; charset=".$charset.$lend;
818 $message_header .= "Content-Disposition: inline".$lend."Content-Transfer-Encoding: 8bit".$lend;
819
820 if(!empty($files) && is_array($files)) {
821 $boundary = substr(uniqid(time()."_"), 0, 16);
822 $mail_message = "--".$boundary.$lend.$message_header.$mail_message.$lend;
823 $message_header = "Content-Type: multipart/related; boundary=\"$boundary\"".$lend;
824 foreach($files as $k => $v) {
825 $mail_message .= "--".$boundary.$lend;
826 $mail_message .= "Content-Type: $v[type]; name=\"$v[name]\"".$lend;
827 $mail_message .= "Content-Disposition: inline; filename=\"$v[name]\"".$lend;
828 $mail_message .= "Content-Transfer-Encoding: base64".$lend;
829 $mail_message .= "Content-ID: <$v[name]>".$lend;
830 $mail_message .= $lend.chunk_split(base64_encode($v['data'])).$lend;
831 }
832 $mail_message .= "--".$boundary."--".$lend;
833 }
834
835 $m_from = $from;
836 if ($config["Email"]["use_base64_headers"] == "Y")
837 $mail_subject = func_mail_quote($mail_subject,$charset);
838
839 $headers = "From: ".$m_from.$lend."X-Mailer: PHP/".phpversion().$lend."MIME-Version: 1.0".$lend.$message_header;
840 if (trim($m_from) != "")
841 $headers .= "Reply-to: ".$m_from.$lend;
842
843 if (preg_match('/([^ @,;<>]+@[^ @,;<>]+)/S', $from, $m))
844 @mail($to,$mail_subject,$mail_message,$headers, "-f".$m[1]);
845 else
846 @mail($to,$mail_subject,$mail_message,$headers);
847}
848
849function func_send_simple_mail($to, $subject, $body, $from) {
850 global $config;
851 global $current_language;
852 global $sql_tbl;
853
854 if (empty($to)) return;
855
856 if (X_DEF_OS_WINDOWS) {
857 $body=str_replace("\n","\r\n",$body);
858 $lend = "\r\n";
859 }
860 else
861 $lend = "\n";
862
863 if (!empty($current_language))
864 $charset = func_query_first_cell ("SELECT charset FROM $sql_tbl[countries] WHERE code='$current_language'");
865
866 if (empty($charset))
867 $charset = func_query_first_cell ("SELECT charset FROM $sql_tbl[countries] WHERE code='".$config["default_admin_language"]."'");
868
869 if ($config["Email"]["use_base64_headers"] == "Y") {
870 $m_from = $from;
871 $m_subject = func_mail_quote($subject,$charset);
872 }
873 else {
874 $m_from = $from;
875 $m_subject = $subject;
876 }
877
878 $headers = "From: ".$m_from.$lend."X-Mailer: PHP/".phpversion().$lend;
879 if (trim($m_from) != "")
880 $headers .= "Reply-to: ".$m_from.$lend;
881
882 $headers .= "MIME-Version: 1.0".$lend;
883 if ($config["Email"]["html_mail"] == "Y")
884 $headers .= "Content-Type: text/html; charset=".$charset.$lend;
885 else
886 $headers .= "Content-Type: text/plain; charset=".$charset.$lend;
887
888 if (preg_match('/([^ @,;<>]+@[^ @,;<>]+)/S', $from, $m))
889 @mail($to,$m_subject,$body,$headers, "-f".$m[1]);
890 else
891 @mail($to,$m_subject,$body,$headers);
892}
893
894#
895# Simple crypt function. Returns an encrypted version of argument.
896# Does not matter what type of info you encrypt, the function will return
897# a string of ASCII chars representing the encrypted version of argument.
898# Note: text_crypt returns string, which length is 2 time larger
899#
900function text_crypt_symbol($c) {
901# $c is ASCII code of symbol. returns 2-letter text-encoded version of symbol
902
903 global $START_CHAR_CODE;
904
905 return chr($START_CHAR_CODE + ($c & 240) / 16).chr($START_CHAR_CODE + ($c & 15));
906}
907
908function text_crypt($s, $is_blowfish = false) {
909 global $START_CHAR_CODE, $CRYPT_SALT, $merchant_password, $current_area, $active_modules, $blowfish, $config;
910
911 if ($s == "")
912 return $s;
913 if($is_blowfish && $merchant_password && ($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"])) && $blowfish && $config['Security']['blowfish_enabled'] == 'Y') {
914 $s = trim($s);
915 $result = addslashes("B".func_crc32($s).func_bf_crypt($s, $merchant_password));
916 } else {
917 $enc = rand(1,255); # generate random salt.
918 $result = "S".text_crypt_symbol($enc); # include salt in the result;
919 $enc ^= $CRYPT_SALT;
920 for ($i = 0; $i < strlen($s); $i++) {
921 $r = ord(substr($s, $i, 1)) ^ $enc++;
922 if ($enc > 255)
923 $enc = 0;
924 $result .= text_crypt_symbol($r);
925 }
926 }
927 return $result;
928}
929
930function text_decrypt_symbol($s, $i) {
931# $s is a text-encoded string, $i is index of 2-char code. function returns number in range 0-255
932
933 global $START_CHAR_CODE;
934
935 return (ord(substr($s, $i, 1)) - $START_CHAR_CODE)*16 + ord(substr($s, $i+1, 1)) - $START_CHAR_CODE;
936}
937
938function text_decrypt($s) {
939 global $START_CHAR_CODE, $CRYPT_SALT, $merchant_password, $current_area, $active_modules, $blowfish;
940
941 if ($s == "")
942 return $s;
943 $crypt_method = substr($s, 0, 1);
944 $s = substr($s, 1);
945 if($crypt_method == 'B') {
946 if($merchant_password && ($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"])) && $blowfish) {
947 $crc32 = substr($s, 0, 4);
948 $s = substr($s, 4);
949 $result = func_bf_decrypt($s, $merchant_password);
950 if(func_crc32($result) != $crc32) {
951 $result = func_get_langvar_by_name('err_data_corrupted');
952 }
953 } else {
954 return false;
955 }
956 } elseif($crypt_method != 'B') {
957 if($crypt_method != 'S') {
958 $s = $crypt_method.$s;
959 }
960 $enc = $CRYPT_SALT ^ text_decrypt_symbol($s, 0);
961 $result = "";
962 for ($i = 2; $i < strlen($s); $i+=2) { # $i=2 to skip salt
963 $result .= chr(text_decrypt_symbol($s, $i) ^ $enc++);
964 if ($enc > 255)
965 $enc = 0;
966 }
967 }
968 return $result;
969}
970
971#
972# Recursively deletes category with all its contents
973#
974
975function func_rm_dir_files ($path) {
976 $dir = opendir ($path);
977
978 while ($file = readdir ($dir)) {
979 if (($file == ".") or ($file == ".."))
980 continue;
981 if (filetype ("$path/$file") == "dir") {
982 func_rm_dir_files ("$path/$file");
983 rmdir ("$path/$file");
984 } else {
985 unlink ("$path/$file");
986 }
987 }
988 closedir($dir);
989}
990
991function func_rm_dir ($path) {
992 func_rm_dir_files ($path);
993 rmdir ($path);
994}
995
996#
997# Delete product from products table + all associated information
998# $productid - product's id
999#
1000function func_delete_product($productid, $update_categories=true) {
1001 global $sql_tbl, $xcart_dir;
1002
1003 $product_categories = func_query("SELECT categoryid FROM $sql_tbl[products_categories] WHERE productid='$productid'");
1004
1005 db_query("delete from $sql_tbl[pricing] where productid='$productid'");
1006 db_query("delete from $sql_tbl[product_links] where productid1='$productid' or productid2='$productid'");
1007 db_query("delete from $sql_tbl[featured_products] where productid='$productid'");
1008 db_query("delete from $sql_tbl[products] where productid='$productid'");
1009 db_query("delete from $sql_tbl[delivery] where productid='$productid'");
1010 db_query("delete from $sql_tbl[images] where productid='$productid'");
1011 db_query("delete from $sql_tbl[thumbnails] where productid='$productid'");
1012 db_query("delete from $sql_tbl[extra_field_values] where productid='$productid'");
1013 db_query("delete from $sql_tbl[products_categories] where productid='$productid'");
1014
1015 # Feature comparison module
1016 if(func_query_first_cell("SELECT module_name FROM $sql_tbl[modules] WHERE module_name='Feature_Comparison'")) {
1017 if(!isset($sql_tbl['product_features']) || !isset($sql_tbl['product_foptions'])) {
1018 include_once $xcart_dir."/modules/Feature_Comparison/config.php";
1019 }
1020 db_query("DELETE FROM $sql_tbl[product_features] WHERE productid='$productid'");
1021 db_query("DELETE FROM $sql_tbl[product_foptions] WHERE productid='$productid'");
1022 }
1023
1024 # Product options module
1025 if(func_query_first_cell("SELECT module_name FROM $sql_tbl[modules] WHERE module_name='Product_Options'")) {
1026 if(!isset($sql_tbl['classes']) || !isset($sql_tbl['class_options'])) {
1027 include_once $xcart_dir."/modules/Product_Options/config.php";
1028 }
1029 $classes = func_create_hash_keys(func_query("SELECT classid FROM $sql_tbl[classes] WHERE productid='$productid'"), "classid");
1030 db_query("delete from $sql_tbl[classes] where productid='$productid'");
1031 if(!empty($classes)) {
1032 $options = array_keys(func_create_hash_keys(func_query("SELECT optionid FROM $sql_tbl[class_options] where classid IN ('".implode("','", array_keys($classes))."')"), "optionid"));
1033 db_query("delete from $sql_tbl[class_options] where classid IN ('".implode("','", array_keys($classes))."')");
1034 db_query("delete from $sql_tbl[class_lng] where classid IN ('".implode("','", array_keys($classes))."')");
1035 if(!empty($options)) {
1036 db_query("DELETE FROM $sql_tbl[product_options_lng] WHERE optionid IN ('".implode("','", $options)."')");
1037 db_query("DELETE FROM $sql_tbl[product_options_ex] WHERE optionid IN ('".implode("','", $options)."')");
1038 db_query("DELETE FROM $sql_tbl[variant_items] WHERE optionid IN ('".implode("','", $options)."')");
1039 }
1040 }
1041 db_query("DELETE FROM $sql_tbl[product_options_js] WHERE productid='$productid'");
1042 db_query("DELETE FROM $sql_tbl[variants] WHERE productid='$productid'");
1043 }
1044
1045 db_query("DELETE FROM $sql_tbl[product_votes] WHERE productid='$productid'");
1046 db_query("DELETE FROM $sql_tbl[product_reviews] WHERE productid='$productid'");
1047 db_query("DELETE FROM $sql_tbl[products_lng] WHERE productid='$productid'");
1048 db_query("DELETE FROM $sql_tbl[subscriptions] where productid='$productid'");
1049 db_query("DELETE FROM $sql_tbl[subscription_customers] where productid='$productid'");
1050 db_query("DELETE FROM $sql_tbl[download_keys] where productid='$productid'");
1051 db_query("DELETE FROM $sql_tbl[discount_coupons] where productid='$productid'");
1052 db_query("DELETE FROM $sql_tbl[stats_customers_products] where productid='$productid'");
1053 db_query("DELETE FROM $sql_tbl[wishlist] where productid='$productid'");
1054 db_query("DELETE FROM $sql_tbl[product_bookmarks] where productid='$productid'");
1055
1056 # Product configurator module
1057 if (func_query_first_cell("SELECT module_name FROM $sql_tbl[modules] WHERE module_name='Product_Configurator'")) {
1058 #
1059 # If Product Configurator installed delete the related information
1060 #
1061 include_once $xcart_dir."/modules/Product_Configurator/config.php";
1062
1063 $classes = func_query("SELECT classid FROM $sql_tbl[pconf_products_classes] WHERE productid='$productid'");
1064 if (is_array($classes)) {
1065 #
1066 # Delete all classification info related with this product
1067 #
1068 foreach ($classes as $k=>$v) {
1069 db_query("DELETE FROM $sql_tbl[pconf_class_specifications] where classid='$v[classid]'");
1070 db_query("DELETE FROM $sql_tbl[pconf_class_requirements] where classid='$v[classid]'");
1071 }
1072 }
1073 db_query("DELETE FROM $sql_tbl[pconf_products_classes] where productid='$productid'");
1074
1075 #
1076 # Delete configurable product
1077 #
1078 $steps = func_query("SELECT stepid FROM $sql_tbl[pconf_wizards] WHERE productid='$productid'");
1079 if (is_array($steps)) {
1080 #
1081 # Delete the data related with wizards' steps
1082 #
1083 foreach ($steps as $k=>$v) {
1084 $slots = func_query("SELECT slotid FROM $sql_tbl[pconf_slots] WHERE stepid='$stepid'");
1085 if (is_array($slots)) {
1086 #
1087 # Delete data related with slots
1088 #
1089 foreach ($slots as $k1=>$v1) {
1090 db_query("DELETE FROM $sql_tbl[pconf_slot_rules] WHERE slotid='$v1[slotid]'");
1091 db_query("DELETE FROM $sql_tbl[pconf_slot_markups] WHERE slotid='$v1[slotid]'");
1092 }
1093 }
1094 db_query("DELETE FROM $sql_tbl[pconf_slots] WHERE stepid='$v[stepid]'");
1095 }
1096 }
1097
1098 db_query("DELETE FROM $sql_tbl[pconf_wizards] where productid='$productid'");
1099 }
1100
1101#
1102# Update product count for categories
1103#
1104 if ($update_categories && is_array($product_categories))
1105 func_recalc_product_count($product_categories);
1106
1107 return true;
1108
1109}
1110
1111#
1112# Delete profile from customers table + all associated information
1113#
1114function func_delete_profile($user,$usertype) {
1115 global $files_dir_name, $single_mode, $sql_tbl;
1116 global $active_modules;
1117
1118 if ($usertype == "A" || ($active_modules["Simple_Mode"] && $usertype == "P")) {
1119 $users_count = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[customers] WHERE usertype='$usertype'");
1120 if ($users_count == 1) {
1121 func_header_location("error_message.php?last_admin");
1122 }
1123 }
1124
1125 if($usertype=="P" && !$single_mode) {
1126# If user is provider delete some associated info to keep DB integrity
1127# Delete products
1128#
1129 $products = func_query("SELECT productid FROM $sql_tbl[products] WHERE provider='$user'");
1130 if (!empty($products))
1131 foreach($products as $product)
1132 func_delete_product($product["productid"]);
1133#
1134# Delete Shipping, Discounts, Coupons, States/Tax, Countries/Tax
1135#
1136 db_query("delete from $sql_tbl[shipping_rates] where provider='$user'");
1137 db_query("delete from $sql_tbl[discounts] where provider='$user'");
1138 db_query("delete from $sql_tbl[discount_coupons] where provider='$user'");
1139 db_query("delete from $sql_tbl[extra_fields] where provider='$user'");
1140 db_query("delete from $sql_tbl[tax_rates] where provider='$user'");
1141 db_query("delete from $sql_tbl[zones] where provider='$user'");
1142
1143#
1144# Delete provider's file dir
1145#
1146 @func_rm_dir ("$files_dir_name/$user");
1147 }
1148
1149#
1150# If it is partner, then remove all his information
1151#
1152 if ($usertype == "B" && func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[modules] WHERE module_name='XAffiliate'") > 0) {
1153 if (empty($active_modules["XAffiliate"]))
1154 include $xcart_dir."XAffiliate/config.php";
1155 db_query ("DELETE FROM $sql_tbl[partner_clicks] WHERE login='$user'");
1156 db_query ("DELETE FROM $sql_tbl[partner_commissions] WHERE login='$user'");
1157 db_query ("DELETE FROM $sql_tbl[partner_payment] WHERE login='$user'");
1158 db_query ("DELETE FROM $sql_tbl[partner_views] WHERE login='$user'");
1159 }
1160
1161 db_query("DELETE FROM $sql_tbl[register_field_values] WHERE login='$user'");
1162 db_query("DELETE FROM $sql_tbl[customers] WHERE login='$user' AND usertype='$usertype'");
1163}
1164
1165#
1166# Get information associated with user
1167#
1168function func_userinfo($user,$usertype, $extended=true) {
1169 global $sql_tbl, $single_mode, $shop_language, $default_user_profile_fields, $config;
1170 global $active_modules;
1171
1172 $userinfo = func_query_first("SELECT $sql_tbl[customers].* FROM $sql_tbl[customers] WHERE $sql_tbl[customers].login='$user' AND $sql_tbl[customers].usertype='$usertype'");
1173
1174 if ($extended) {
1175 $extended_info = func_query_first("SELECT * FROM $sql_tbl[orders] WHERE login='$user' ORDER BY orderid DESC LIMIT 1");
1176 if (empty($extended_info)) {
1177 $userinfo["b_title"] = $userinfo["s_title"] = $userinfo["title"];
1178 $userinfo["b_firstname"] = $userinfo["s_firstname"] = $userinfo["firstname"];
1179 $userinfo["b_lastname"] = $userinfo["s_lastname"] = $userinfo["lastname"];
1180 }
1181 else {
1182 $userinfo["b_title"] = $extended_info["b_title"];
1183 $userinfo["b_firstname"] = $extended_info["b_firstname"];
1184 $userinfo["b_lastname"] = $extended_info["b_lastname"];
1185 $userinfo["s_title"] = $extended_info["s_title"];
1186 $userinfo["s_firstname"] = $extended_info["s_firstname"];
1187 $userinfo["s_lastname"] = $extended_info["s_lastname"];
1188 }
1189 unset($extended_info);
1190 }
1191
1192 $userinfo["passwd1"] = stripslashes(text_decrypt($userinfo["password"]));
1193 $userinfo["passwd2"] = stripslashes(text_decrypt($userinfo["password"]));
1194 $userinfo["password"] = stripslashes(text_decrypt($userinfo["password"]));
1195 $userinfo["card_number"] = text_decrypt($userinfo["card_number"]);
1196 list($userinfo["b_address"], $userinfo["b_address_2"]) = split("[\n\r]+", $userinfo["b_address"]);
1197 $userinfo["b_statename"] = func_get_state($userinfo["b_state"], $userinfo["b_country"]);
1198 $userinfo["b_countryname"] = func_get_country($userinfo["b_country"]);
1199 list($userinfo["s_address"], $userinfo["s_address_2"]) = split("[\n\r]+", $userinfo["s_address"]);
1200 $userinfo["s_statename"] = func_get_state($userinfo["s_state"], $userinfo["s_country"]);
1201 $userinfo["s_countryname"] = func_get_country($userinfo["s_country"]);
1202 if ($config["General"]["use_counties"] == "Y") {
1203 $userinfo["b_countyname"] = func_get_county($userinfo["b_county"]);
1204 $userinfo["s_countyname"] = func_get_county($userinfo["s_county"]);
1205 }
1206 if($userinfo["usertype"] == "B" && !empty($active_modules["XAffiliate"]))
1207 $userinfo["plan_id"] = func_query_first_cell("SELECT plan_id FROM $sql_tbl[partner_commissions] WHERE login = '$userinfo[login]'");
1208 $email = $userinfo["email"];
1209
1210 # Get additional fields
1211 $userinfo['additional_fields'] = func_get_additional_fields($usertype, $user);
1212 $fields = func_query("SELECT $sql_tbl[register_fields].fieldid, $sql_tbl[register_fields].section, $sql_tbl[register_field_values].value FROM $sql_tbl[register_fields] LEFT JOIN $sql_tbl[register_field_values] ON $sql_tbl[register_fields].fieldid = $sql_tbl[register_field_values].fieldid AND $sql_tbl[register_field_values].login = '$user' WHERE $sql_tbl[register_fields].avail LIKE '%$usertype%' ORDER BY $sql_tbl[register_fields].section, $sql_tbl[register_fields].orderby");
1213 if($fields) {
1214 foreach($fields as $k => $v) {
1215 $fields[$k]['title'] = func_get_languages_alt("lbl_register_field_".$v['fieldid'], $shop_language);
1216 }
1217 $userinfo['additional_fields'] = $fields;
1218 }
1219
1220 # Get default fields
1221 $default_fields = unserialize($config["User_Profiles"]["register_fields"]);
1222 if(!$default_fields) {
1223 $default_fields = array();
1224 foreach($default_user_profile_fields as $k => $v) {
1225 $default_fields[$k] = true;
1226 }
1227 } else {
1228 $tmp = array();
1229 foreach($default_fields as $k => $v) {
1230 if(strpos($v['avail'], $usertype) === false)
1231 continue;
1232 $tmp[$v['field']] = true;
1233 }
1234 $default_fields = $tmp;
1235 unset($tmp);
1236 }
1237 if($default_fields) {
1238 $userinfo['default_fields'] = $default_fields;
1239 }
1240
1241 return $userinfo;
1242}
1243
1244#
1245# Get the customer's zone
1246#
1247function func_get_customer_zone_ship ($username, $provider, $type) {
1248 global $sql_tbl;
1249 global $single_mode;
1250
1251 $zones = func_get_customer_zones_avail($username, $provider, "S");
1252 $zone = 0; # default zone
1253 if (is_array($zones)) {
1254 $provider_condition = ($single_mode) ? "" : " AND provider='".addslashes($provider)."'";
1255 $tmp = func_query("SELECT zoneid FROM $sql_tbl[shipping_rates] WHERE zoneid IN ('".implode("','",array_keys($zones))."') $provider_condition AND type='$type' GROUP BY zoneid");
1256 if (is_array($tmp)) {
1257 $unused = $zones;
1258 # remove not available zones
1259 foreach($tmp as $v) unset($unused[$v["zoneid"]]);
1260 foreach($unused as $k=>$v) unset($zones[$k]);
1261
1262 reset($zones);
1263 $zone = key($zones); #extract first zone
1264 }
1265 }
1266
1267 return $zone;
1268}
1269
1270#
1271# Get the customer's zones
1272#
1273function func_get_customer_zones_avail ($username, $provider, $address_type="S") {
1274 global $sql_tbl, $config, $single_mode;
1275 static $results_cache = array();
1276
1277 # Define which address type should be compared
1278 if ($address_type == "B")
1279 $address_prefix = "b_";
1280 else
1281 $address_prefix = "s_";
1282
1283 $zones = array();
1284
1285 if (is_array($username)) {
1286 $customer_info = $username;
1287 }
1288 elseif (!empty($username)) {
1289 $customer_info = func_userinfo($username, "C");
1290 }
1291 elseif ($config["General"]["apply_default_country"] == "Y") {
1292 # Set the default user address
1293 $customer_info[$address_prefix."country"] = $config["General"]["default_country"];
1294 $customer_info[$address_prefix."state"] = $config["General"]["default_state"];
1295 $customer_info[$address_prefix."county"] = $config["General"]["default_county"];
1296 $customer_info[$address_prefix."zipcode"] = $config["General"]["default_zipcode"];
1297 $customer_info[$address_prefix."city"] = $config["General"]["default_city"];
1298 }
1299
1300 $customer_login = "";
1301 if (!empty($customer_info)) {
1302 $customer_login = $customer_info["login"];
1303 #
1304 # Check local zones cache
1305 #
1306 if (isset($results_cache[$customer_login][$provider][$address_type]))
1307 return $results_cache[$customer_login][$provider][$address_type];
1308 #
1309 # Generate the zones list
1310 #
1311 $provider_condition = ($single_mode ? "" : "AND provider='$provider'");
1312
1313 $is_country_found = true;
1314 $is_state_found = true;
1315 $is_county_found = true;
1316
1317 # Possible zones for customer's country...
1318 $possible_zones = func_query("SELECT $sql_tbl[zone_element].zoneid FROM $sql_tbl[zone_element], $sql_tbl[zones] WHERE $sql_tbl[zone_element].zoneid=$sql_tbl[zones].zoneid AND $sql_tbl[zone_element].field='".$customer_info[$address_prefix."country"]."' AND $sql_tbl[zone_element].field_type='C' $provider_condition GROUP BY $sql_tbl[zone_element].zoneid");
1319
1320 if (is_array($possible_zones)) {
1321 $cs_state = $customer_info[$address_prefix."state"];
1322 $cs_country = $customer_info[$address_prefix."country"];
1323 $cs_pair = $cs_country."_".$cs_state;
1324 foreach ($possible_zones as $pzone) {
1325 $zones[$pzone["zoneid"]] = 10;
1326 $is_state_found = true;
1327 $is_county_found = true;
1328
1329 # Possible zones for customer's state...
1330 $state_zone = func_query_first_cell("SELECT zoneid FROM $sql_tbl[zone_element], $sql_tbl[states] WHERE $sql_tbl[zone_element].field='".addslashes($cs_pair)."' AND $sql_tbl[zone_element].field_type='S' AND $sql_tbl[states].code='".addslashes($cs_state)."' AND $sql_tbl[states].country_code='".addslashes($cs_country)."' AND $sql_tbl[zone_element].zoneid='$pzone[zoneid]'");
1331 if (!empty($state_zone)) {
1332 # State found: increase the priority
1333 $zones[$pzone["zoneid"]] = 20;
1334
1335 if ($config["General"]["use_counties"] == "Y") {
1336 # Possible zones for customer's county...
1337 $county_zone = func_query_first_cell("SELECT zoneid FROM $sql_tbl[zone_element] WHERE field_type='G' AND field='".$customer_info[$address_prefix."county"]."' AND zoneid='$pzone[zoneid]'");
1338
1339 if (!empty($county_zone))
1340 $zones[$pzone["zoneid"]] = 30;
1341 else {
1342 $is_county = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[zone_element] WHERE $sql_tbl[zone_element].field_type='G' AND $sql_tbl[zone_element].zoneid='$pzone[zoneid]'");
1343 if ($is_county)
1344 unset($zones[$pzone["zoneid"]]);
1345 $is_county_found = false;
1346 continue;
1347 }
1348 }
1349 }
1350 else {
1351 # State not found: check if defined other states
1352 $is_states = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[zone_element] WHERE $sql_tbl[zone_element].field_type='S' AND $sql_tbl[zone_element].zoneid='$pzone[zoneid]'");
1353 if ($is_states) {
1354 unset($zones[$pzone["zoneid"]]);
1355 $is_state_found = false;
1356 continue;
1357 }
1358 }
1359 }
1360 }
1361 else
1362 $is_country_found = false;
1363
1364 if ($is_country_found && $is_state_found && $is_county_found) {
1365
1366 $empty_condition = " AND $sql_tbl[zone_element].field<>'%'";
1367
1368 #
1369 # Checking the city, address and zip code masks
1370 #
1371 $city_zones = func_query("SELECT $sql_tbl[zone_element].zoneid FROM $sql_tbl[zone_element], $sql_tbl[zones] WHERE $sql_tbl[zone_element].zoneid=$sql_tbl[zones].zoneid AND $sql_tbl[zone_element].field_type='T' AND '".addslashes($customer_info[$address_prefix."city"])."' LIKE $sql_tbl[zone_element].field $empty_condition $provider_condition");
1372 if (is_array($city_zones))
1373 foreach ($city_zones as $k=>$v)
1374 $zones[$v["zoneid"]] += 1;
1375 elseif (is_array($zones)) {
1376 foreach ($zones as $k=>$v) {
1377 $is_city = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[zone_element] WHERE $sql_tbl[zone_element].field_type='T' AND $sql_tbl[zone_element].zoneid='$k' $empty_condition");
1378 if ($is_city)
1379 unset($zones[$k]);
1380 }
1381 }
1382
1383 $zipcode_zones = func_query("SELECT $sql_tbl[zone_element].zoneid FROM $sql_tbl[zone_element], $sql_tbl[zones] WHERE $sql_tbl[zone_element].zoneid=$sql_tbl[zones].zoneid AND $sql_tbl[zone_element].field_type='Z' AND '".addslashes($customer_info[$address_prefix."zipcode"])."' LIKE $sql_tbl[zone_element].field $empty_condition $provider_condition");
1384 if (is_array($zipcode_zones))
1385 foreach ($zipcode_zones as $k=>$v)
1386 $zones[$v["zoneid"]] += 1;
1387 elseif (is_array($zones)) {
1388 foreach ($zones as $k=>$v) {
1389 $is_zipcodes = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[zone_element] WHERE $sql_tbl[zone_element].field_type='Z' AND $sql_tbl[zone_element].zoneid='$k' $empty_condition");
1390 if ($is_zipcodes)
1391 unset($zones[$k]);
1392 }
1393 }
1394
1395 $address_zones = func_query("SELECT $sql_tbl[zone_element].zoneid FROM $sql_tbl[zone_element], $sql_tbl[zones] WHERE $sql_tbl[zone_element].zoneid=$sql_tbl[zones].zoneid AND $sql_tbl[zone_element].field_type='A' AND ('".addslashes($customer_info[$address_prefix."address"])."' LIKE $sql_tbl[zone_element].field OR '".addslashes($customer_info[$address_prefix."address_2"])."' LIKE $sql_tbl[zone_element].field) $empty_condition $provider_condition");
1396 if (is_array($address_zones))
1397 foreach ($address_zones as $k=>$v)
1398 $zones[$v["zoneid"]] += 1;
1399 elseif (is_array($zones)) {
1400 foreach ($zones as $k=>$v) {
1401 $is_address = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[zone_element] WHERE $sql_tbl[zone_element].field_type='A' AND $sql_tbl[zone_element].zoneid='$k' $empty_condition");
1402 if ($is_address)
1403 unset($zones[$k]);
1404 }
1405 }
1406 }
1407
1408 }
1409
1410 $zones[0] = 0;
1411 arsort($zones, SORT_NUMERIC);
1412
1413 if (!empty($customer_login)) {
1414 $results_cache[$customer_login][$provider][$address_type] = $zones;
1415 }
1416
1417 return $zones;
1418}
1419
1420#
1421# Get county by code
1422#
1423function func_get_county ($countyid) {
1424 global $sql_tbl;
1425
1426 $county_name = func_query_first_cell("SELECT county FROM $sql_tbl[counties] WHERE countyid='$countyid'");
1427 return ($county_name ? $county_name : $countyid);
1428}
1429#
1430# Get state by code
1431#
1432function func_get_state ($state_code, $country_code) {
1433 global $sql_tbl;
1434
1435 $state_name = func_query_first_cell("SELECT state FROM $sql_tbl[states] WHERE country_code='$country_code' AND code='".addslashes($state_code)."'");
1436 return ($state_name ? $state_name : $state_code);
1437}
1438
1439#
1440# Get country by code
1441#
1442function func_get_country ($country_code, $force_code = '') {
1443 global $sql_tbl, $shop_language;
1444
1445 $code = (empty($force_code)?$shop_language:$force_code);
1446 $country_name = func_query_first_cell("SELECT value as country FROM $sql_tbl[languages] WHERE name='country_$country_code' AND code = '$code'");
1447 return ($country_name ? $country_name : $country_code);
1448}
1449
1450#
1451# Convert price to "XXXXX.XX" format
1452#
1453function price_format($price) {
1454 return sprintf("%.2f",round((double)$price+0.00000000001,2));
1455}
1456
1457function func_get_products_providers ($products) {
1458 $products_providers = array ();
1459 if(!empty($products)) {
1460 foreach ($products as $product) {
1461 if (!in_array ($product["provider"], $products_providers)) {
1462 $products_providers [] = $product["provider"];
1463 }
1464 }
1465 }
1466
1467 return $products_providers;
1468}
1469
1470function func_get_products_by_provider ($products, $provider) {
1471 global $single_mode;
1472
1473 $result = array ();
1474
1475 if ($single_mode) {
1476 $result = $products;
1477 } else {
1478 foreach ($products as $k=>$product) {
1479 if ($product["provider"] == $provider)
1480 $result[$k] = $product;
1481 }
1482 }
1483
1484 return $result;
1485}
1486
1487#
1488# This function do real shipping calcs
1489#
1490function func_real_shipping($delivery) {
1491
1492 global $intershipper_rates, $sql_tbl;
1493
1494 $shipping_codes = func_query_first("select code, subcode from $sql_tbl[shipping] where shippingid='$delivery'");
1495
1496 if ($intershipper_rates) {
1497 foreach($intershipper_rates as $rate)
1498 if ($rate["methodid"]==$shipping_codes["subcode"])
1499 return $rate["rate"];
1500 } else
1501 return "0.00";
1502
1503}
1504
1505#
1506# This function calculates costs of contents of shopping cart
1507#
1508function func_calculate($cart, $products, $login, $login_type) {
1509 global $config, $single_mode, $sql_tbl;
1510 global $xcart_dir, $active_modules;
1511
1512 $return = array ();
1513 $return ["orders"] = array ();
1514
1515 if ($active_modules["Special_Offers"]) {
1516 include $xcart_dir."/modules/Special_Offers/calculate_init.php";
1517 }
1518
1519 if ($single_mode) {
1520 $result = func_calculate_single ($cart, $products, $login, $login_type);
1521 $return = $result;
1522 $return ["orders"][0] = $result;
1523 $return ["orders"][0]["provider"] = (!empty($products) ? $products[0]["provider"] : "");
1524 if ($active_modules["Special_Offers"]) {
1525 include $xcart_dir."/modules/Special_Offers/calculate_return.php";
1526 }
1527 }
1528 else {
1529 $products_providers = func_get_products_providers ($products);
1530
1531 $key = 0;
1532
1533 foreach ($products_providers as $provider_for) {
1534 $_products = func_get_products_by_provider ($products, $provider_for);
1535 $result = func_calculate_single ($cart, $_products, $login, $login_type, $provider_for);
1536
1537 $return ["total_cost"] += $result ["total_cost"];
1538 $return ["shipping_cost"] += $result ["shipping_cost"];
1539 $return ["display_shipping_cost"] += $result ["display_shipping_cost"];
1540 $return ["tax_cost"] += $result ["tax_cost"];
1541 $return ["discount"] += $result ["discount"];
1542 if ($result["coupon"]) {
1543 $return ["coupon"] = $result ["coupon"];
1544 }
1545 $return ["coupon_discount"] += $result ["coupon_discount"];
1546 $return ["subtotal"] += $result ["subtotal"];
1547 $return ["display_subtotal"] += $result ["display_subtotal"];
1548 $return ["discounted_subtotal"] += $result ["discounted_subtotal"];
1549 $return ["display_discounted_subtotal"] += $result ["display_discounted_subtotal"];
1550 $return ["products"] = func_array_merge($return ["products"], $result ["products"]);
1551
1552 if (empty($return["taxes"]))
1553 $return["taxes"] = $result["taxes"];
1554 elseif (is_array($result["taxes"])) {
1555 foreach ($result["taxes"] as $k=>$v) {
1556 if (in_array($k, array_keys($return["taxes"])))
1557 $return["taxes"][$k]["tax_cost"] += $v["tax_cost"];
1558 else
1559 $return["taxes"][$k] = $v;
1560 }
1561 }
1562
1563 $return ["orders"][$key] = $result;
1564 $return ["orders"][$key]["provider"] = $provider_for;
1565
1566 if ($active_modules["Special_Offers"]) {
1567 include $xcart_dir."/modules/Special_Offers/calculate_return.php";
1568 }
1569
1570 $key ++;
1571 }
1572
1573 if (!empty($cart["giftcerts"])) {
1574 $_products = array ();
1575 $result = func_calculate_single ($cart, $_products, $login, $login_type);
1576 $return ["total_cost"] += $result ["total_cost"];
1577 $return ["shipping_cost"] += $result ["shipping_cost"];
1578 $return ["display_shipping_cost"] += $result ["display_shipping_cost"];
1579 $return ["tax_cost"] += $result ["tax_cost"];
1580 $return ["discount"] += $result ["discount"];
1581 $return ["subtotal"] += $result ["subtotal"];
1582 $return ["display_subtotal"] += $result ["display_subtotal"];
1583 $return ["discounted_subtotal"] += $result ["discounted_subtotal"];
1584 $return ["display_discounted_subtotal"] += $result ["display_discounted_subtotal"];
1585 $return ["coupon_discount"] += $result ["coupon_discount"];
1586
1587 $return ["orders"][$key] = $result;
1588 $return ["orders"][$key]["provider"] = ""; #$provider_for;
1589 $key++;
1590 }
1591 }
1592
1593 $return["display_cart_products_tax_rates"] = "N";
1594 $return["product_tax_name"] = "";
1595 if ($config["Taxes"]["display_cart_products_tax_rates"] == "Y") {
1596 $_taxes = array();
1597 foreach ($return["orders"] as $k=>$v) {
1598 if (is_array($v["products"])) {
1599 foreach ($v["products"] as $i=>$j) {
1600 if (is_array(@$j["taxes"])) {
1601 foreach ($j["taxes"] as $_tn=>$_tax) {
1602 if ($_tax["tax_value"] == 0)
1603 continue;
1604 if (!isset($_taxes[$_tn]))
1605 $_taxes[] = $_tax["tax_display_name"];
1606 }
1607 }
1608 }
1609 }
1610 }
1611
1612 if (count($_taxes) > 0) {
1613 $return["display_cart_products_tax_rates"] = "Y";
1614 if (count($_taxes) == 1)
1615 $return["product_tax_name"] = $_taxes[0];
1616 }
1617 }
1618
1619#
1620# Recalculating applied gift certificates
1621#
1622 $giftcert_cost = 0;
1623 $applied_giftcerts = array();
1624 if (!empty($cart["applied_giftcerts"])) {
1625 $gc_payed_sum = 0;
1626 $applied_giftcerts = array();
1627 foreach($cart["applied_giftcerts"] as $k=>$v) {
1628 if (($gc_payed_sum + $v["giftcert_cost"]) <= $return["total_cost"]) {
1629 $gc_payed_sum += $v["giftcert_cost"];
1630 $applied_giftcerts[] = $v;
1631 continue;
1632 }
1633 else
1634 db_query("UPDATE $sql_tbl[giftcerts] SET status='A' WHERE gcid='$v[giftcert_id]'");
1635 }
1636 $giftcert_cost = $gc_payed_sum;
1637 }
1638
1639 if ($return["total_cost"] >= $giftcert_cost)
1640 $return["giftcert_discount"] = $giftcert_cost;
1641 else
1642 $return["giftcert_discount"] = $giftcert_cost - $return["total_cost"];
1643
1644 $return["total_cost"] = price_format($return["total_cost"] - $return["giftcert_discount"]);
1645 $return["applied_giftcerts"] = $applied_giftcerts;
1646
1647 if ($single_mode)
1648 $return ["orders"][0]["total_cost"] = $return["total_cost"];
1649#
1650# Apply GC to all orders in cart in single_mode Off
1651#
1652 elseif (is_array($applied_giftcerts)) {
1653 foreach($return["orders"] as $k=>$order) {
1654 $giftcert_discount = 0;
1655 foreach($applied_giftcerts as $k1=>$applied_giftcert) {
1656 if ($applied_giftcert["giftcert_cost"] == 0)
1657 continue;
1658 if ($applied_giftcert["giftcert_cost"] > $order["total_cost"])
1659 $applied_giftcert["giftcert_cost"] = $order["total_cost"];
1660 $giftcert_discount += $applied_giftcert["giftcert_cost"];
1661 $order["total_cost"] = $order["total_cost"] - $giftcert_discount;
1662 $applied_giftcert["giftcert_cost"] = price_format($applied_giftcert["giftcert_cost"]);
1663 $applied_giftcerts[$k1]["giftcert_cost"] -= $applied_giftcert["giftcert_cost"];
1664 $return["orders"][$k]["applied_giftcerts"][] = $applied_giftcert;
1665 $return["orders"][$k]["giftcert_discount"] = price_format($giftcert_discount);
1666 }
1667 $return["orders"][$k]["total_cost"] = price_format($return["orders"][$k]["total_cost"] - $return["orders"][$k]["giftcert_discount"]);
1668 }
1669 }
1670
1671 return $return;
1672}
1673
1674#
1675# This function distributes the discount among the product prices and
1676# decreases the subtotal
1677#
1678function func_distribute_discount($field_name, $products, $discount, $discount_type, $avail_discount_total=0) {
1679 $sum_discount = 0;
1680 if ($discount_type=="absolute" && $avail_discount_total > 0) {
1681 # Distribute absolute discount among the products
1682 foreach ($products as $k=>$product) {
1683 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
1684 if ($field_name == "coupon_discount" || $product["discount_avail"] == "Y") {
1685 $koefficient = $product["price"] / $avail_discount_total;
1686 $products[$k][$field_name] = $discount * $koefficient;
1687 $products[$k]["discounted_price"] = max($products[$k]["discounted_price"] - $products[$k][$field_name], 0.00);
1688 }
1689 }
1690 }
1691 elseif ($discount_type=="percent") {
1692 # Distribute percent discount among the products
1693 foreach ($products as $k=>$product) {
1694 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
1695 if ($field_name == "coupon_discount" || $product["discount_avail"] == "Y") {
1696 $products[$k][$field_name] = price_format($product["discounted_price"] * $discount / 100);
1697 $products[$k]["discounted_price"] = $product["discounted_price"] - $products[$k][$field_name];
1698 }
1699 }
1700 }
1701
1702 foreach($products as $product) {
1703 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
1704 $sum_discount += $product[$field_name]*$product["amount"];
1705 }
1706
1707 $return["products"] = $products;
1708 $return[$field_name] = $sum_discount;
1709 return $return;
1710}
1711
1712#
1713# This function calculates discounts on subtotal
1714#
1715function func_calculate_discounts($membership, $products, $discount_coupon = "", $provider="") {
1716 global $sql_tbl, $config, $active_modules, $single_mode;
1717
1718 #
1719 # Prepare provider condition for discounts gathering
1720 #
1721 $provider_condition = ($single_mode ? "" : "AND provider='$provider'");
1722
1723 #
1724 # Search for subtotal to apply the global discounts
1725 #
1726 $avail_discount_total = 0;
1727 $total = 0;
1728 foreach($products as $k=>$product) {
1729 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
1730 $product["price"] = price_format($product["price"]);
1731 $products[$k]["discount"] = 0;
1732 $products[$k]["coupon_discount"] = 0;
1733 $products[$k]["discounted_price"] = $product["price"];
1734 if ($product["discount_avail"] == "Y")
1735 $avail_discount_total += $product["price"] * $product["amount"];
1736 $total += $product["price"] * $product["amount"];
1737 }
1738
1739 $return = array("discount" => 0,
1740 "coupon_discount" => 0,
1741 "discount_coupon" => $discount_coupon,
1742 "products" => $products);
1743
1744 if ($avail_discount_total > 0) {
1745 #
1746 # Calculate global discount
1747 #
1748 $discount_info = func_query_first("SELECT * FROM $sql_tbl[discounts] WHERE minprice<='$avail_discount_total' $provider_condition AND membership IN ('','$membership') ORDER BY minprice DESC");
1749 if (!empty($discount_info)) {
1750 if ($discount_info["discount_type"]=="absolute")
1751 $return["discount"] += $discount_info["discount"];
1752 elseif ($discount_info["discount_type"]=="percent")
1753 $return["discount"] += price_format($avail_discount_total * $discount_info["discount"] / 100);
1754 #
1755 # Distribute the discount among the products prices
1756 #
1757 $updated = func_distribute_discount("discount", $products, $discount_info["discount"], $discount_info["discount_type"], $avail_discount_total);
1758 #
1759 # $products and $discount are extracted from the array $updated
1760 #
1761 extract($updated);
1762 unset($updated);
1763 $return["products"] = $products;
1764 $return["discount"] = $discount;
1765 }
1766 }
1767
1768 #
1769 # Apply discount coupon
1770 #
1771 if ($active_modules["Discount_Coupons"] and !empty($discount_coupon)) {
1772 #
1773 # Calculate discount value of the discount coupon
1774 #
1775 $coupon_total = 0;
1776 $coupon_amount = 0;
1777
1778 $discount_coupon_data = func_query_first("select * from $sql_tbl[discount_coupons] where coupon='$discount_coupon' $provider_condition");
1779
1780 $return["discount_coupon_data"] = $discount_coupon_data;
1781
1782 if (!$single_mode and ($discount_coupon_data["provider"] != $provider or empty($products)))
1783 $return["discount_coupon"] = $discount_coupon_data = "";
1784
1785 $return["coupon_type"] = $discount_coupon_data["coupon_type"];
1786
1787 if (!empty($discount_coupon_data) and (($discount_coupon_data["coupon_type"] == "absolute") || ($discount_coupon_data["coupon_type"] == "percent"))) {
1788 $coupon_discount = 0;
1789 if ($discount_coupon_data["productid"] > 0) {
1790 #
1791 # Apply coupon to product
1792 #
1793 foreach($products as $k=>$product) {
1794 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
1795 if ($product["productid"] == $discount_coupon_data["productid"]) {
1796 $price = $product["price"] - $product["discount"];
1797 if ($discount_coupon_data["coupon_type"]=="absolute") {
1798 $coupon_discount = price_format($product["amount"] * $discount_coupon_data["discount"]);
1799 $products[$k]["coupon_discount"] = $discount_coupon_data["discount"];
1800 $products[$k]["discounted_price"] = max($price - $products[$k]["coupon_discount"], 0.00);
1801 }
1802 else {
1803 $coupon_discount = price_format(($price * $discount_coupon_data["discount"] / 100 )) * $product["amount"];
1804 $products[$k]["coupon_discount"] = price_format($price * $discount_coupon_data["discount"] / 100);
1805 $products[$k]["discounted_price"] = max($price - $products[$k]["coupon_discount"], 0.00);
1806 }
1807 $return["coupon_discount"] += $coupon_discount;
1808
1809 }
1810 }
1811 }
1812 elseif ($discount_coupon_data["categoryid"] > 0) {
1813 #
1814 # Apply coupon to category (and subcategories)
1815 #
1816 $category_ids[] = $discount_coupon_data["categoryid"];
1817
1818 if ($discount_coupon_data["recursive"] == "Y") {
1819 $categoryid_path = func_query_first_cell("SELECT categoryid_path FROM $sql_tbl[categories] WHERE categoryid='$discount_coupon_data[categoryid]'");
1820 if (!empty($categoryid_path))
1821 $tmp = db_query("SELECT categoryid FROM $sql_tbl[categories] WHERE categoryid_path LIKE '$categoryid_path/%'");
1822 while($row = db_fetch_array($tmp))
1823 $category_ids[] = $row["categoryid"];
1824 }
1825 #
1826 # Apply coupon to one category
1827 #
1828 foreach ($products as $k=>$product) {
1829 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
1830 $product_categories = func_query("SELECT categoryid FROM $sql_tbl[products_categories] WHERE productid='$product[productid]'");
1831 $is_valid_product = false;
1832 foreach ($product_categories as $pc) {
1833 if (in_array($pc["categoryid"], $category_ids)) {
1834 $is_valid_product = true;
1835 break;
1836 }
1837 }
1838 if ($is_valid_product) {
1839 $price = $product["price"] - $product["discount"];
1840 if ($discount_coupon_data["coupon_type"]=="absolute") {
1841 $products[$k]["coupon_discount"] = $discount_coupon_data["discount"];
1842 $products[$k]["discounted_price"] = max($price - $products[$k]["coupon_discount"], 0.00);
1843 $coupon_discount += $product["amount"] * $discount_coupon_data["discount"];
1844 }
1845 else {
1846 $products[$k]["coupon_discount"] = price_format($price * $discount_coupon_data["discount"] / 100);
1847 $products[$k]["discounted_price"] = max($price - $products[$k]["coupon_discount"], 0.00);
1848 $coupon_discount += price_format($price * $discount_coupon_data["discount"] / 100) * $product["amount"];
1849 }
1850 $return["coupon_discount"] = $coupon_discount;
1851 }
1852 }
1853 }
1854 else {
1855 #
1856 # Apply coupon to subtotal
1857 #
1858 if ($discount_coupon_data["coupon_type"]=="absolute")
1859 $return["coupon_discount"] = $discount_coupon_data["discount"];
1860 elseif ($discount_coupon_data["coupon_type"]=="percent")
1861 $return["coupon_discount"] = $total * $discount_coupon_data["discount"] / 100;
1862 $updated = func_distribute_discount("coupon_discount", $products, $discount_coupon_data["discount"], $discount_coupon_data["coupon_type"], $total);
1863 #
1864 # $products and $discount are extracted from the array $updated
1865 #
1866 extract($updated);
1867 unset($updated);
1868
1869 $return["coupon_discount"] = $coupon_discount;
1870
1871 }
1872 }
1873
1874 $return["products"] = $products;
1875 }
1876
1877 return $return;
1878}
1879
1880#
1881# This function calculates delivery cost
1882#
1883# Shipping also calculated based on zones
1884#
1885# Advanced shipping formula:
1886# AMOUNT = amount of ordered products
1887# SUM = total sum of order
1888# TOTAL_WEIGHT = total weight of products
1889#
1890# SHIPPING = rate+TOTAL_WEIGHT*weight_rate+AMOUNT*item_rate+SUM*rate_p/100
1891#
1892function func_calculate_shippings($products, $shipping_id, $customer_info, $provider="") {
1893 global $sql_tbl, $config, $active_modules, $single_mode;
1894
1895 $return = array("shipping_cost" => 0);
1896
1897 #
1898 # Prepare provider condition for shipping rates gathering
1899 #
1900 $provider_condition = ($single_mode ? "" : "AND provider='$provider'");
1901
1902 #
1903 # Initial definitions
1904 #
1905 $total_shipping = 0;
1906 $total_weight_shipping = 0;
1907 $total_ship_items = 0;
1908 $shipping_cost = 0;
1909 $shipping_freight = 0;
1910 $free_shipping_products_cost = 0;
1911
1912 if(!empty($products)) {
1913 foreach($products as $k=>$product) {
1914 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
1915 if ($product["free_shipping"] == "Y" || $product['product_type'] == 'C') {
1916 $free_shipping_products_cost += $product["taxed_price"] * $product["amount"];
1917 continue;
1918 } elseif ($active_modules["Egoods"] && $product["distribution"] != "") {
1919 continue;
1920 } else {
1921 if (!($config["Shipping"]["replace_shipping_with_freight"] == "Y" and $product["shipping_freight"] > 0)) {
1922 $total_shipping += $product["taxed_price"] * $product["amount"];
1923 $total_weight_shipping += $product["weight"] * $product["amount"];
1924 $total_ship_items += $product["amount"];
1925 }
1926 $shipping_freight += $product["shipping_freight"] * $product["amount"];
1927 }
1928 }
1929 }
1930
1931 #
1932 # Nothing to ship
1933 #
1934 if ($total_ship_items == 0 and $shipping_freight == 0)
1935 return $return;
1936
1937 #
1938 # Get defined shipping rates for $shipping_id
1939 #
1940 $total_shipping_abs = $total_shipping;
1941 if ($total_shipping > 0) {
1942 $total_shipping_abs += $free_shipping_products_cost;
1943 }
1944
1945 $customer_zone = func_get_customer_zone_ship($customer_info, $provider,"D");
1946 $shipping = func_query("SELECT * FROM $sql_tbl[shipping_rates] WHERE shippingid='$shipping_id' $provider_condition AND zoneid='$customer_zone' AND maxtotal>='$total_shipping_abs' AND maxweight>='$total_weight_shipping' AND type='D' ORDER BY maxtotal, maxweight");
1947
1948 if ($shipping and $total_ship_items > 0)
1949 $shipping_cost = $shipping[0]["rate"] + ($total_weight_shipping * $shipping[0]["weight_rate"]) + ($total_ship_items * $shipping[0]["item_rate"]) + ($total_shipping * $shipping[0]["rate_p"] / 100);
1950
1951
1952 #
1953 # Get realtime shipping rates
1954 #
1955 $result = func_query_first ("SELECT * FROM $sql_tbl[shipping] WHERE shippingid='$shipping_id' AND code!=''");
1956 if ($config["Shipping"]["realtime_shipping"]=="Y" and $result and $total_ship_items>0) {
1957 $shipping_cost = func_real_shipping($shipping_id);
1958 $customer_zone = func_get_customer_zone_ship($customer_info, $provider,"R");
1959 $shipping_rt = func_query("SELECT * FROM $sql_tbl[shipping_rates] WHERE shippingid='$shipping_id' $provider_condition AND zoneid='$customer_zone' AND maxtotal>=$total_shipping_abs AND maxweight>=$total_weight_shipping AND type='R' ORDER BY maxtotal, maxweight");
1960 if($shipping_rt && $shipping_cost > 0)
1961 $shipping_cost += $shipping_rt[0]["rate"]+$total_weight_shipping*$shipping_rt[0]["weight_rate"]+$total_ship_items*$shipping_rt[0]["item_rate"]+$total_shipping*$shipping_rt[0]["rate_p"]/100;
1962 }
1963
1964 $return["shipping_cost"] = $shipping_cost += $shipping_freight;
1965
1966 return $return;
1967}
1968
1969#
1970# This function calculates taxes
1971#
1972# SUM = total sum of order
1973#
1974# TAX_US = country_tax_flat + SUM*country_tax_percent/100 + state_tax_flat + SUM*state_tax_percent/100;
1975#
1976# TAX_CAN = SUM*gst_tax/100 + SUM*pst_tax/100;
1977#
1978function func_calculate_taxes(&$products, $customer_info, $shipping_cost, $provider="") {
1979 global $sql_tbl, $config, $active_modules, $single_mode, $shop_language;
1980 global $xcart_dir;
1981
1982 $taxes = array();
1983 $taxes["total"] = 0;
1984 $taxes["shipping"] = 0;
1985
1986 $__taxes = array();
1987
1988 foreach($products as $k=>$product) {
1989 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
1990 if ($product["free_tax"] != "Y") {
1991 $product_taxes = func_get_product_taxes($products[$k], $customer_info["login"], true);
1992
1993 if ($config["Taxes"]["display_taxed_order_totals"] =="Y")
1994 $products[$k]["display_price"] = doubleval($product["taxed_price"]);
1995
1996 if (is_array($product_taxes)) {
1997 $formula_data = array();
1998 $formula_data["ST"] = $product["price"] * $product["amount"];
1999 $formula_data["DST"] = $product["discounted_price"] * $product["amount"];
2000 $formula_data["SH"] = 0;
2001
2002 $tax_result = array();
2003
2004 if (empty($shipping_cost)) {
2005 $index = 1;
2006 $tax_result[1] = 0;
2007 }
2008 else
2009 $index = 0;
2010
2011 while ($index < 2) {
2012 $index++;
2013
2014 foreach ($product_taxes as $tax_name=>$v) {
2015 if ($v["skip"])
2016 continue;
2017
2018 if (!isset($taxes["taxes"][$tax_name])) {
2019 $taxes["taxes"][$tax_name] = $v;
2020 $taxes["taxes"][$tax_name]["tax_cost"] = 0;
2021 }
2022
2023 if ($index == 2) {
2024 $formula_data["SH"] = $shipping_cost;
2025
2026 if (!empty($__taxes[$tax_name]))
2027 $formula_data["SH"] = 0;
2028 else
2029 $__taxes[$tax_name] = true;
2030 }
2031
2032 if ($v["rate_type"] == "%") {
2033 $assessment = func_calculate_assessment($v["formula"], $formula_data);
2034 $tax_value = $assessment * $v["rate_value"] / 100;
2035 }
2036 else
2037 $tax_value = $v["rate_value"];
2038
2039 $formula_data[$tax_name] = $tax_value;
2040
2041 $tax_result[$index] += $tax_value;
2042 if ($index == 2) {
2043 $taxes["taxes"][$tax_name]["tax_cost"] += $tax_value;
2044 }
2045
2046 }
2047 }
2048 $taxes["shipping"] += max(0,($tax_result[2] - $tax_result[1]));
2049 }
2050 }
2051 }
2052
2053 if ($shipping_cost == 0)
2054 $taxes["shipping"] = 0;
2055
2056 if (is_array($taxes["taxes"])) {
2057 foreach ($taxes["taxes"] as $tax_name=>$tax) {
2058 $taxes["taxes"][$tax_name]["tax_cost"] = price_format($tax["tax_cost"]);
2059 $taxes["total"] += $taxes["taxes"][$tax_name]["tax_cost"];
2060 }
2061 }
2062
2063 return $taxes;
2064
2065}
2066
2067#
2068# Calculate total products price
2069# 1) calculate total sum,
2070# 2) a) total = total - discount
2071# b) total = total - coupon_discount
2072# 3) calculate shipping
2073# 4) calculate tax
2074# 5) total_cost = total + shipping + tax
2075# 6) total_cost = total_cost + giftcerts_cost
2076#
2077function func_calculate_single($cart, $products, $login, $login_type, $provider_for="") {
2078 global $single_mode;
2079 global $active_modules, $config, $sql_tbl;
2080 global $xcart_dir;
2081
2082 if ($products) {
2083 #
2084 # Set the fields filter to avoid storing too much redundant data
2085 # in the session
2086 #
2087 list($tmp_k, $tmp_v) = each($cart["products"]);
2088 foreach(array_keys($tmp_v) as $k)
2089 $product_keys[] = $k;
2090 unset($tmp_k, $tmp_v);
2091 reset($cart["products"]);
2092 $product_keys[] = "cartid";
2093 $product_keys[] = "product";
2094 $product_keys[] = "productcode";
2095 $product_keys[] = "product_options";
2096 $product_keys[] = "price";
2097 $product_keys[] = "display_price";
2098 $product_keys[] = "display_discounted_price";
2099 $product_keys[] = "display_subtotal";
2100 $product_keys[] = "free_price";
2101 $product_keys[] = "discount";
2102 $product_keys[] = "coupon_discount";
2103 $product_keys[] = "discounted_price";
2104 $product_keys[] = "taxes";
2105 $product_keys[] = "subtotal";
2106 $product_keys[] = "product_type";
2107 $product_keys[] = "options_surcharge";
2108 $product_keys[] = "extra_data"; # Additional data for storing in the DB
2109
2110 if ($active_modules["Wishlist"])
2111 $product_keys[] = "wishlistid";
2112
2113 if ($active_modules["Egoods"])
2114 $product_keys[] = "distribution";
2115
2116 if ($active_modules["Advanced_Order_Management"]) {
2117 $product_keys[] = "deleted";
2118 $product_keys[] = "new";
2119 $product_keys[] = "use_shipping_cost_alt";
2120 $product_keys[] = "shipping_cost_alt";
2121 }
2122
2123 if ($active_modules["Product_Configurator"]) {
2124 $product_keys[] = "hidden";
2125 $product_keys[] = "pconf_price";
2126 $product_keys[] = "pconf_display_price";
2127 $product_keys[] = "pconf_data";
2128 $product_keys[] = "slotid";
2129 $product_keys[] = "price_modifier";
2130 }
2131
2132 if ($active_modules["Subscriptions"]) {
2133 $product_keys[] = "catalogprice";
2134 $product_keys[] = "sub_plan";
2135 $product_keys[] = "sub_days_remain";
2136 $product_keys[] = "sub_onedayprice";
2137 }
2138
2139 if ($active_modules["Special_Offers"]) {
2140 $product_keys[] = "free_amount";
2141 $product_keys[] = "have_offers";
2142 $product_keys[] = "special_price_used";
2143 $product_keys[] = "free_shipping_used";
2144 $product_keys[] = "saved_original_price";
2145 }
2146 }
2147 else
2148 $products = array();
2149
2150 #
2151 # Calculate totals for one provider only or for all ($single_mode=true)
2152 #
2153 $provider_condition=($single_mode?"":"and provider='$provider_for'");
2154
2155 $shipping_id = @$cart["shippingid"];
2156 $giftcerts = @$cart["giftcerts"];
2157 $discount_coupon = @$cart["discount_coupon"];
2158
2159 #
2160 # Get the user information
2161 #
2162 if (!empty($login)) $customer_info = func_userinfo($login,$login_type);
2163
2164 if (!empty($active_modules["Special_Offers"])) {
2165 include $xcart_dir."/modules/Special_Offers/calculate_prepare.php";
2166 include $xcart_dir."/modules/Special_Offers/calculate.php";
2167 }
2168
2169 if (!empty($products)) {
2170 #
2171 # Apply discounts to the products
2172 #
2173 $discounts_ret = func_calculate_discounts($customer_info["membership"], $products, $discount_coupon, $provider_for);
2174 #
2175 # Extract returned variables to global variables set:
2176 # $discount, $coupon_discount, $discount_coupon, $products
2177 #
2178 extract($discounts_ret);
2179 unset($discounts_ret);
2180 }
2181
2182 #
2183 # Initial definitions
2184 #
2185 $subtotal = 0;
2186 $discounted_subtotal = 0;
2187 $shipping_cost = 0;
2188 $total_tax = 0;
2189 $giftcerts_cost = 0;
2190
2191 #
2192 # Update $products array: calculate discounted prices, subtotal and
2193 # discounted subtotal
2194 #
2195 foreach($products as $k=>$product) {
2196
2197 if (@$product["deleted"]) continue; # for Advanced_Order_Management module
2198
2199 if (empty($product["discount"]) and empty($product["coupon_discount"]))
2200 $product["discounted_price"] = $product["price"];
2201
2202 if ($product["product_type"] == "C") {
2203 # Corrections for Product Configurator module
2204 $product["pconf_price"] = $product["price"] = max(doubleval($product["options_surcharge"]), 0);
2205 $product["discounted_price"] = $product["price"];
2206 foreach ($products as $k1=>$v1) {
2207 if ($v1["hidden"] == $product["cartid"]) {
2208 $product["pconf_price"] += price_format($v1["price"]);
2209 }
2210 }
2211 $product["pconf_display_price"] = $product["pconf_price"];
2212 }
2213
2214 $product["subtotal"] = price_format($product["discounted_price"] * $product["amount"]);
2215 $product["display_price"] = price_format($product["price"]);
2216 $product["display_discounted_price"] = $product["discounted_price"];
2217 $product["display_subtotal"] = $product["subtotal"];
2218
2219 $products[$k] = $product;
2220
2221 if (!empty($active_modules["Special_Offers"])) {
2222 include $xcart_dir."/modules/Special_Offers/calculate_subtotal.php";
2223 } else {
2224 $subtotal += price_format($product["price"]) * $product["amount"];
2225 $discounted_subtotal += price_format($product["discounted_price"]) * $product["amount"];
2226 }
2227 }
2228
2229 $total = $subtotal;
2230 $display_subtotal = $subtotal;
2231 $display_discounted_subtotal = $discounted_subtotal;
2232
2233#
2234# Enable shipping and taxes calculation if "apply_default_country" is ticked.
2235#
2236 $calculate_enable_flag = true;
2237
2238 if (empty($login)) {
2239 #
2240 # If user is not logged in
2241 #
2242 if ($config["General"]["apply_default_country"] == "Y") {
2243 $customer_info["s_country"] = $config["General"]["default_country"];
2244 $customer_info["s_state"] = $config["General"]["default_state"];
2245 $customer_info["s_zipcode"] = $config["General"]["default_zipcode"];
2246 $customer_info["s_city"] = $config["General"]["default_city"];
2247 }
2248 else
2249 $calculate_enable_flag = false;
2250 }
2251
2252 if ($config["Shipping"]["disable_shipping"] != "Y" && $calculate_enable_flag || $cart["use_shipping_cost_alt"] == "Y") {
2253 #
2254 # Calculate shipping cost
2255 #
2256 if ($cart["use_shipping_cost_alt"] == "Y")
2257 $shipping_cost = $cart["shipping_cost_alt"];
2258 else {
2259 $shippings_ret = func_calculate_shippings($products, $shipping_id, $customer_info, $provider_for);
2260 #
2261 # Extract returned variables to global variables set:
2262 # $shipping_cost
2263 #
2264 extract($shippings_ret);
2265 unset($shippings_ret);
2266 }
2267
2268 if (!empty($coupon_type) and $coupon_type == "free_ship") {
2269 #
2270 # Apply discount coupon 'Free shipping'
2271 #
2272 if (($single_mode) or ($provider_for == $discount_coupon_data["provider"])) {
2273 $coupon_discount = $shipping_cost;
2274 $shipping_cost = 0;
2275 }
2276 }
2277 }
2278
2279 $display_shipping_cost = $shipping_cost;
2280
2281 if ($calculate_enable_flag) {
2282 #
2283 # Calculate taxes cost
2284 #
2285 $taxes = func_calculate_taxes($products, $customer_info, $shipping_cost, $provider_for);
2286
2287 $total_tax = $taxes["total"];
2288
2289 if ($config["Taxes"]["display_taxed_order_totals"] == "Y") {
2290
2291 $_display_discounted_subtotal_tax = 0;
2292 if (is_array($taxes["taxes"])) {
2293 # Calculate the additional tax value if "display_including_tax"
2294 # option for tax is disabled (for $_display_discounted_subtotal)
2295 foreach ($taxes["taxes"] as $k=>$v)
2296 if ($v["display_including_tax"] != "Y")
2297 $_display_discounted_subtotal_tax += $v["tax_value"];
2298 }
2299
2300 $display_shipping_cost = $shipping_cost + $taxes["shipping"];
2301 $_display_subtotal = 0;
2302 $_display_discounted_subtotal = 0;
2303 if (is_array($products)) {
2304 foreach ($products as $k=>$v) {
2305 $v["display_price"] = $products[$k]["display_price"] = price_format($products[$k]["display_price"]);
2306 if (is_array($v["taxes"])) {
2307 # Correct $_display_subtotal if "display_including_tax"
2308 # option for the tax is disabled
2309 foreach ($v["taxes"] as $tn=>$tv) {
2310 if ($tv["display_including_tax"] == "N")
2311 $_display_subtotal += $tv["tax_value"];
2312 }
2313 }
2314 $_display_subtotal += $v["display_price"] * $v["amount"];
2315 if (!empty($v["discount"]) || !empty($v["coupon_discount"]))
2316 $_taxes = func_tax_price($v["price"], $v["productid"], false, $v["discounted_price"], $customer_info, "", true);
2317 else
2318 $_taxes = func_tax_price($v["price"], $v["productid"], false, 0, $customer_info, "", true);
2319 $products[$k]["display_discounted_price"] = price_format($_taxes["taxed_price"]);
2320 $products[$k]["display_subtotal"] = $products[$k]["display_discounted_price"] * $v["amount"];
2321 $_display_discounted_subtotal += $products[$k]["display_subtotal"];
2322 if ($v["product_type"] == "C") {
2323 # Corrections for Product Configurator module
2324 $products[$k]["display_price"] = $_pconf_display_price = max(doubleval($products[$k]["options_surcharge"]), 0);
2325 $_display_subtotal += ($_pconf_display_price * $products[$k]["amount"]);
2326 $_pconf_taxes = array();
2327 foreach ($products as $k1=>$v1) {
2328 if ($v1["hidden"] == $v["cartid"]) {
2329 $_pconf_display_price += price_format($v1["display_price"]);
2330 if (is_array($v1["taxes"])) {
2331 foreach ($v1["taxes"] as $_tax_name=>$_tax) {
2332 if (!isset($_pconf_taxes[$_tax_name])) {
2333 $_pconf_taxes[$_tax_name] = $_tax;
2334 $_pconf_taxes[$_tax_name]["tax_value"] = 0;
2335 }
2336 $_pconf_taxes[$_tax_name]["tax_value"] += $_tax["tax_value"];
2337 }
2338 }
2339 }
2340 }
2341 $products[$k]["taxes"] = $_pconf_taxes;
2342 $products[$k]["pconf_display_price"] = $_pconf_display_price;
2343 }
2344
2345 }
2346
2347 if ($display_subtotal == $display_discounted_subtotal)
2348 $display_discounted_subtotal = $_display_subtotal;
2349 else
2350 $display_discounted_subtotal = $_display_discounted_subtotal + $_display_discounted_subtotal_tax;
2351
2352 $display_subtotal = $_display_subtotal;
2353 }
2354 }
2355 }
2356
2357 #
2358 # Calculate Gift Certificates cost (purchased giftcerts)
2359 #
2360 if ((($single_mode) or (!$provider_for)) and ($giftcerts)) {
2361 foreach($giftcerts as $giftcert) {
2362 if (@$giftcert["deleted"]) continue; # for Advanced_Order_Management module
2363 $giftcerts_cost+=$giftcert["amount"];
2364 }
2365 }
2366
2367 $subtotal += $giftcerts_cost;
2368 $display_subtotal += $giftcerts_cost;
2369 $discounted_subtotal += $giftcerts_cost;
2370 $display_discounted_subtotal += $giftcerts_cost;
2371
2372 #
2373 # Calculate total
2374 #
2375 if ($config["Taxes"]["display_taxed_order_totals"] == "Y")
2376 $total = $display_discounted_subtotal + $display_shipping_cost;
2377 else
2378 $total = $discounted_subtotal + $shipping_cost + $total_tax;
2379
2380 $_products = array();
2381 foreach($products as $index=>$product) {
2382 foreach($product as $key=>$value)
2383 if (in_array($key, $product_keys))
2384 $_products[$index][$key] = $value;
2385 }
2386
2387 $return = array("total_cost"=>price_format($total),
2388 "shipping_cost"=>price_format($shipping_cost),
2389 "taxes" => $taxes["taxes"],
2390 "tax_cost"=>price_format($taxes["total"]),
2391 "discount"=>price_format($discount),
2392 "coupon"=>$discount_coupon,
2393 "coupon_discount"=>price_format($coupon_discount),
2394 "subtotal"=>price_format($subtotal),
2395 "display_subtotal"=>price_format($display_subtotal),
2396 "discounted_subtotal"=>price_format($discounted_subtotal),
2397 "display_shipping_cost"=>price_format($display_shipping_cost),
2398 "display_discounted_subtotal"=>price_format($display_discounted_subtotal),
2399 "products"=>$_products);
2400
2401 if (!empty($active_modules["Special_Offers"])) {
2402 include $xcart_dir."/modules/Special_Offers/calculate_result.php";
2403 }
2404
2405 return $return;
2406}
2407
2408#
2409# Search for products in products database
2410#
2411function func_search_products($query, $membership, $orderby="", $limit="") {
2412 global $current_area, $user_account;
2413 global $store_language, $sql_tbl;
2414 global $config;
2415 global $cart, $login;
2416 global $active_modules;
2417
2418 #
2419 # Generate ORDER BY rule
2420 #
2421 if (empty($orderby)) {
2422 $orderby = ($config["Appearance"]["products_order"] ? $config["Appearance"]["products_order"] : "orderby");
2423 if($orderby == 'title') {
2424 $orderby = 'product';
2425 } elseif($orderby == 'quantity') {
2426 $orderby = "$sql_tbl[products].avail";
2427 } elseif($orderby == "orderby") {
2428 $orderby = "$sql_tbl[products_categories].orderby";
2429 } elseif($orderby == "quantity") {
2430 $orderby = "$sql_tbl[products].avail";
2431 } elseif($orderby == "price") {
2432 $orderby = "price";
2433 } elseif($orderby == "productcode") {
2434 $orderby = "$sql_tbl[products].productcode";
2435 }
2436 }
2437
2438
2439 #
2440 # Generate membership condition
2441 #
2442 if ($current_area == "C") {
2443 $membership_condition = " AND ($sql_tbl[categories].membership='$membership' OR $sql_tbl[categories].membership='') AND $sql_tbl[products].forsale='Y'";
2444 }
2445 else
2446 $membership_condition = "";
2447
2448 #
2449 # Generate products availability condition
2450 #
2451 if ($config["General"]["unlimited_products"]=="N" && (($current_area == "C" || $current_area == "B") && $config["General"]["disable_outofstock_products"] == "Y"))
2452 $avail_condition = " AND $sql_tbl[products].avail>0 ";
2453 else
2454 $avail_condition = "";
2455
2456 $select_query = "SELECT $sql_tbl[products].productid, $sql_tbl[products].product, $sql_tbl[products].productcode, $sql_tbl[products].avail, MIN($sql_tbl[pricing].price) AS price";
2457
2458 $from_query = " FROM $sql_tbl[products], $sql_tbl[categories], $sql_tbl[products_categories], $sql_tbl[pricing]";
2459
2460 $where_query = " WHERE $sql_tbl[products].productid=$sql_tbl[products_categories].productid AND $sql_tbl[products_categories].categoryid=$sql_tbl[categories].categoryid AND $sql_tbl[products].productid=$sql_tbl[pricing].productid AND $sql_tbl[pricing].quantity=1 AND ($sql_tbl[pricing].membership='$membership' OR $sql_tbl[pricing].membership='') $membership_condition $avail_condition";
2461
2462 if($current_area == 'C' && !empty($active_modules['Product_Options'])) {
2463 $where_query .= " AND ($sql_tbl[pricing].variantid = 0 OR ($sql_tbl[variants].variantid = $sql_tbl[pricing].variantid".(($config["General"]["disable_outofstock_products"] == "Y" && $config["General"]["unlimited_products"] != "Y")?" AND $sql_tbl[variants].avail > 0":"")."))";
2464 } else {
2465 $where_query .= " AND $sql_tbl[pricing].variantid = 0";
2466 }
2467
2468 if ($current_area == 'C' && empty($active_modules['Product_Configurator'])) {
2469 $where_query .= " AND $sql_tbl[products].product_type <> 'C' AND $sql_tbl[products].product_type <> 'B' ";
2470 }
2471
2472 $groupby_query = " GROUP BY $sql_tbl[products].productid";
2473
2474 $orderby_query = " ORDER BY $orderby";
2475
2476 if (!empty($limit))
2477 $limit_query = " LIMIT $limit";
2478
2479 #
2480 # Check if product have prodyct class (Feature comparison)
2481 #
2482 if(!empty($active_modules['Feature_Comparison']) && $current_area == "C") {
2483 global $comparison_list_ids;
2484 $from_query .= " LEFT JOIN $sql_tbl[product_features] ON $sql_tbl[product_features].productid = $sql_tbl[products].productid";
2485 $select_query .= ", $sql_tbl[product_features].fclassid";
2486 if(($config['Feature_Comparison']['fcomparison_show_product_list'] == 'Y') && $config['Feature_Comparison']['fcomparison_max_product_list'] > @count((array)$comparison_list_ids)) {
2487 $select_query .= ", IF($sql_tbl[product_features].fclassid IS NULL || $sql_tbl[product_features].productid IN ('".@implode("','",@array_keys((array)$comparison_list_ids))."'),'','Y') as is_clist";
2488 }
2489 }
2490
2491 #
2492 # Check if product have product options (Product options)
2493 #
2494 if(!empty($active_modules['Product_Options'])) {
2495 $from_query .= " LEFT JOIN $sql_tbl[classes] ON $sql_tbl[classes].productid = $sql_tbl[products].productid LEFT JOIN $sql_tbl[variants] ON $sql_tbl[variants].productid = $sql_tbl[products].productid";
2496 $select_query .= ", IF ($sql_tbl[classes].classid IS NULL,'','Y') as is_product_options, IF($sql_tbl[variants].variantid IS NULL,'','Y') as is_variant";
2497 }
2498
2499 if ($current_area == "C" && $store_language != $config["default_customer_language"])
2500 $from_query .= " LEFT JOIN $sql_tbl[products_lng] ON $sql_tbl[products].productid=$sql_tbl[products_lng].productid";
2501
2502 #
2503 # Generate search query
2504 #
2505 $search_query = $select_query.$from_query.$where_query.$query.$groupby_query.$orderby_query.$limit_query;
2506
2507 $result = func_query($search_query);
2508
2509
2510 if ($result && ($current_area=="C" || $current_area=="B") ) {
2511 #
2512 # Post-process the result products array
2513 #
2514 foreach ($result as $key=>$value) {
2515 if (!empty($cart) and !empty($cart["products"]) && $current_area=="C") {
2516 #
2517 # Update quantity for products that already placed into the cart
2518 #
2519 $in_cart = 0;
2520 foreach ($cart["products"] as $cart_item)
2521 if ($cart_item["productid"] == $value["productid"])
2522 $in_cart += $cart_item["amount"];
2523 $result[$key]["avail"] -= $in_cart;
2524 }
2525
2526 #
2527 # Get thumbnail's URL (uses only if images stored in FS)
2528 #
2529 $result[$key]["tmbn_url"] = func_get_thumbnail_url($result[$key]["productid"]);
2530
2531 if ($current_area == "C") {
2532 $result[$key]["taxes"] = func_get_product_taxes($result[$key], $login);
2533 }
2534
2535 #
2536 # Check if product have product options
2537 #
2538 if(!empty($active_modules['Product_Options'])) {
2539 $result[$key]["product_options"] = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[classes] WHERE productid='".$value["productid"]."'");
2540 }
2541
2542 $int_res = func_query_first("SELECT * FROM $sql_tbl[products_lng] WHERE code='$store_language' AND productid='$value[productid]'");
2543
2544 if (!empty($int_res["product"]))
2545 $result[$key]["product"] = stripslashes($int_res["product"]);
2546
2547 if (!empty($int_res["descr"]))
2548 $result[$key]["descr"] = stripslashes($int_res["descr"]);
2549
2550 if ($result[$key]["descr"] == strip_tags($result[$key]["descr"]))
2551 $result[$key]["descr"] = str_replace("\n", "<BR>", $result[$key]["descr"]);
2552
2553 if (!empty($int_res["full_descr"]))
2554 $result[$key]["full_descr"] = stripslashes($int_res["full_descr"]);
2555
2556 if ($result[$key]["full_descr"] == strip_tags($result[$key]["full_descr"]))
2557 $result[$key]["full_descr"] = str_replace("\n", "<BR>", $result[$key]["full_descr"]);
2558
2559 }
2560 }
2561
2562 return $result;
2563}
2564
2565#
2566# Delete category recursively and all subcategories and products
2567#
2568function func_delete_category($cat) {
2569 global $sql_tbl;
2570
2571 $catpair = func_query_first("SELECT categoryid_path, parentid FROM $sql_tbl[categories] WHERE categoryid='$cat'");
2572 if ($catpair === false) # category is missing
2573 return 0;
2574
2575#
2576# Delete products from subcategories
2577#
2578 $categoryid_path = $catpair["categoryid_path"];
2579 $parent_categoryid = $catpair["parentid"];
2580 $prods = func_query("SELECT $sql_tbl[products_categories].productid FROM $sql_tbl[categories], $sql_tbl[products_categories] WHERE ($sql_tbl[categories].categoryid='$cat' OR $sql_tbl[categories].categoryid_path LIKE '$categoryid_path/%') AND $sql_tbl[products_categories].categoryid=$sql_tbl[categories].categoryid");
2581
2582 if($prods)
2583 while(list($key,$prod)=each($prods))
2584 func_delete_product($prod["productid"],false);
2585#
2586# Delete subcategories
2587#
2588 $subcats = func_query("SELECT categoryid FROM $sql_tbl[categories] WHERE categoryid='$cat' OR categoryid_path LIKE '$categoryid_path/%'");
2589
2590 if (is_array($subcats))
2591 while(list($key,$subcat)=each($subcats)) {
2592 $cat_id=$subcat["categoryid"];
2593 db_query("DELETE FROM $sql_tbl[categories] WHERE categoryid='$cat_id'");
2594 db_query("DELETE FROM $sql_tbl[products_categories] WHERE categoryid='$cat_id'");
2595 db_query("DELETE FROM $sql_tbl[icons] WHERE categoryid='$cat_id'");
2596 }
2597#
2598# Delete associated data
2599#
2600 db_query("DELETE FROM $sql_tbl[icons] WHERE categoryid='$cat'");
2601 db_query("DELETE FROM $sql_tbl[featured_products] WHERE categoryid='$cat'");
2602
2603 $product_categories = func_query("SELECT categoryid FROM $sql_tbl[categories]");
2604 func_recalc_product_count($product_categories);
2605
2606 return $parent_categoryid;
2607
2608}
2609
2610#
2611# Put all product info into $product array
2612#
2613function func_select_product($id, $membership, $redirect_if_error=true, $clear_price=false, $always_select=false) {
2614
2615 global $login, $login_type, $current_area, $single_mode, $cart;
2616 global $store_language, $sql_tbl, $config, $active_modules;
2617
2618 $in_cart = 0;
2619
2620 if ($current_area == "C") {
2621 $membership_condition = " AND ($sql_tbl[categories].membership='$membership' OR $sql_tbl[categories].membership='') ";
2622 }
2623 else {
2624 $membership_condition = "";
2625 }
2626
2627 if ($current_area == "C" and !empty($cart) and !empty($cart["products"])) {
2628 foreach($cart["products"] as $cart_item) {
2629 if ($cart_item["productid"] == $id) {
2630 $in_cart += $cart_item["amount"];
2631 }
2632 }
2633 }
2634
2635 $login_condition = "";
2636 if (!$single_mode)
2637 $login_condition = (($login != "" and $login_type == "P") ? "AND $sql_tbl[products].provider='$login'" : "");
2638 $add_fields = "";
2639 $join = "";
2640 if(!empty($active_modules['Product_Options'])) {
2641 $add_fields .= ", IF($sql_tbl[variants].variantid IS NOT NULL,'Y','') as is_variant";
2642 $join .= "LEFT JOIN $sql_tbl[variants] ON $sql_tbl[variants].productid = $sql_tbl[products].productid";
2643 }
2644
2645 $product = func_query_first("SELECT $sql_tbl[products].*, $sql_tbl[products].avail-$in_cart AS avail, min($sql_tbl[pricing].price) AS price $add_fields FROM $sql_tbl[products], $sql_tbl[pricing] $join WHERE $sql_tbl[products].productid='$id' ".$login_condition." AND $sql_tbl[pricing].productid=$sql_tbl[products].productid AND $sql_tbl[pricing].quantity=1 AND $sql_tbl[pricing].variantid = 0 AND ($sql_tbl[pricing].membership = '$membership' OR $sql_tbl[pricing].membership = '') GROUP BY $sql_tbl[products].productid");
2646
2647 $categoryid = func_query_first_cell("SELECT $sql_tbl[products_categories].categoryid FROM $sql_tbl[products_categories] USE INDEX (cpm), $sql_tbl[categories] WHERE $sql_tbl[products_categories].categoryid=$sql_tbl[categories].categoryid $membeship_condition AND $sql_tbl[products_categories].productid='$id' AND $sql_tbl[products_categories].main='Y'");
2648
2649#
2650# Error handling
2651#
2652 if (!$product || !$categoryid) {
2653 if ($redirect_if_error)
2654 func_header_location("error_message.php?access_denied&id=33");
2655 else
2656 return false;
2657 }
2658
2659 $product["categoryid"] = $categoryid;
2660
2661 if ($current_area == "C" || $current_area == "B") {
2662 #
2663 # Check if product is not available for sale
2664 #
2665 global $pconf;
2666 if ($product["forsale"] == "B" && empty($pconf) && is_array(@$cart["products"])) {
2667 foreach ($cart["products"] as $k=>$v) {
2668 if ($v["productid"] == $product["productid"]) {
2669 $pconf = $product["productid"];
2670 break;
2671 }
2672 }
2673 }
2674
2675 $product['taxed_price'] = $product['price'];
2676
2677 if (!$always_select && ($product["forsale"] == "N" || ($product["forsale"] == "B" && empty($pconf)))) {
2678 if ($redirect_if_error)
2679 func_header_location("error_message.php?product_disabled");
2680 else
2681 return false;
2682 }
2683
2684 if ($current_area == "C") {
2685 #
2686 # Calculate taxes and price including taxes
2687 #
2688 global $login;
2689 $product["taxes"] = func_get_product_taxes($product, $login);
2690
2691 }
2692 }
2693
2694 # Add product features
2695 if (!empty($active_modules['Feature_Comparison'])) {
2696 $product['fclassid'] = func_query_first_cell("SELECT fclassid FROM $sql_tbl[product_features] WHERE productid = '$product[productid]'");
2697 $product['features'] = func_get_product_features($product['productid']);
2698 $product['is_clist'] = func_check_comparison($product['productid']);
2699 }
2700
2701 $int_res = func_query_first ("SELECT * FROM $sql_tbl[products_lng] WHERE code='$store_language' AND productid='$id'");
2702 if ($current_area == "C" and !empty($int_res)) {
2703 if ($int_res["product"])
2704 $product["product"] = stripslashes($int_res["product"]);
2705 if ($int_res["descr"])
2706 $product["descr"] = stripslashes($int_res["descr"]);
2707 if ($int_res["full_descr"])
2708 $product["fulldescr"] = stripslashes($int_res["full_descr"]);
2709 }
2710
2711 $product["producttitle"] = "$product[product] #$product[productid]";
2712
2713 if ($current_area == "C" || $current_area == "B") {
2714 if ($product["descr"] == strip_tags($product["descr"]))
2715 $product["descr"] = str_replace("\n", "<br>", $product["descr"]);
2716
2717 if ($product["fulldescr"] == strip_tags($product["fulldescr"]))
2718 $product["fulldescr"] = str_replace("\n", "<br>", $product["fulldescr"]);
2719 }
2720
2721 #
2722 # Get thumbnail's URL (uses only if images stored in FS)
2723 #
2724 $product["tmbn_url"] = func_get_thumbnail_url($product["productid"]);
2725
2726 #
2727 # Add Manufacturer information
2728 #
2729 if (!empty($active_modules["Manufacturers"]))
2730 $product['manufacturer'] = func_query_first_cell("SELECT manufacturer FROM $sql_tbl[manufacturers] WHERE manufacturerid = '$product[manufacturerid]'");
2731
2732 return $product;
2733
2734}
2735
2736#
2737# Get delivery options by product ID
2738#
2739function func_select_product_delivery($id) {
2740 global $sql_tbl;
2741
2742 return func_query("select $sql_tbl[shipping].*, count($sql_tbl[delivery].productid) as avail from $sql_tbl[shipping] left join $sql_tbl[delivery] on $sql_tbl[delivery].shippingid=$sql_tbl[shipping].shippingid and $sql_tbl[delivery].productid='$id' where $sql_tbl[shipping].active='Y' group by shippingid");
2743}
2744
2745#
2746# Return number of available products
2747#
2748function insert_productsonline() {
2749 global $sql_tbl;
2750
2751 return func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[products] WHERE forsale!='N'");
2752
2753}
2754
2755#
2756# Return number of available items
2757#
2758function insert_itemsonline() {
2759 global $sql_tbl;
2760
2761 return func_query_first_cell("SELECT SUM(avail) FROM $sql_tbl[products] WHERE forsale!='N'");
2762
2763}
2764
2765#
2766# Return string of search
2767#
2768function insert_stripslashes() {
2769 global $substring;
2770
2771 $substring=trim($substring);
2772 while(strstr($substring,"\\")) {
2773 $substring=stripslashes($substring);
2774 }
2775 return $substring;
2776}
2777
2778#
2779# Generate products array in $cart
2780#
2781function func_products_in_cart($cart, $membership) {
2782 if (empty($cart) or empty($cart["products"])) return array();
2783 return func_products_from_scratch($cart["products"], $membership, false);
2784}
2785
2786#
2787# Generate products array from scratch
2788#
2789function func_products_from_scratch($scratch_products, $membership, $persistent_products) {
2790 global $active_modules, $sql_tbl, $config, $xcart_dir;
2791 global $current_area, $store_language;
2792
2793 $products = array();
2794
2795 if ($scratch_products)
2796
2797 foreach($scratch_products as $product_data) {
2798
2799 $productid = $product_data["productid"];
2800 $amount = $product_data["amount"];
2801 if (!is_numeric($amount))
2802 $amount = 0;
2803 $options = $product_data["options"];
2804 $product_options = false;
2805
2806 if(!empty($active_modules['Product_Options']) && $options)
2807 list($variant, $product_options) = func_get_product_options_data($productid, $options, $membership);
2808
2809 $avail_condition = "";
2810
2811 if ($config["General"]["unlimited_products"]=="N" && !$persistent_products && empty($variant))
2812 $avail_condition = "($sql_tbl[products].avail>=".doubleval($amount)." OR $sql_tbl[products].product_type='C') AND ";
2813
2814 if ($current_area == 'C' && empty($active_modules['Product_Configurator'])) {
2815 $avail_condition .= " $sql_tbl[products].product_type <> 'C' AND $sql_tbl[products].product_type <> 'B' AND ";
2816 }
2817
2818 $products_array = func_query_first("select $sql_tbl[products].*, min($sql_tbl[pricing].price) as price from $sql_tbl[products], $sql_tbl[pricing] where $sql_tbl[pricing].productid=$sql_tbl[products].productid and $sql_tbl[products].productid='$productid' and $avail_condition $sql_tbl[pricing].quantity<=$amount and ($sql_tbl[pricing].membership='$membership' or $sql_tbl[pricing].membership='') AND $sql_tbl[pricing].variantid = 0 group by $sql_tbl[products].productid order by $sql_tbl[pricing].quantity desc");
2819
2820 if ($products_array) {
2821 $products_array = func_array_merge($product_data, $products_array);
2822 if(!empty($active_modules['Product_Options']) && $options) {
2823 if(!empty($variant))
2824 $products_array = func_array_merge($products_array, $variant);
2825 if($config["General"]["unlimited_products"]=="N" && !$persistent_products && $products_array['avail'] < $amount && $products_array['product_type'] == '')
2826 continue;
2827 if($product_options === false)
2828 unset($product_options);
2829 else {
2830 if(empty($variant['price']))
2831 $variant['price'] = $products_array['price'];
2832 $products_array['price'] = $variant['price'];
2833 $products_array["options_surcharge"] = 0;
2834 if($product_options)
2835 foreach($product_options as $o)
2836 $products_array["options_surcharge"] += ($o['modifier_type'] == '%'?($products_array['price']*$o['price_modifier']/100):$o['price_modifier']);
2837 }
2838 }
2839#
2840# Get thumbnail's URL (uses only if images stored in FS)
2841#
2842 $products_array["tmbn_url"] = func_get_thumbnail_url($products_array["productid"]);
2843#
2844# If priduct's price is 0 then use customer-defined price
2845#
2846 if ($products_array["price"]==0 && empty($products_array["slotid"])) {
2847 $free_price = true;
2848 $products_array["price"]=price_format($product_data["free_price"]?$product_data["free_price"]:0);
2849 }
2850 else
2851 $free_price = false;
2852
2853 if ($products_array["product_type"] == "C")
2854 $products_array["price"] = $products_array["options_surcharge"];
2855 else
2856 $products_array["price"] += $products_array["options_surcharge"];
2857
2858 if ($current_area == "C" && $products_array["product_type"] != "C") {
2859 #
2860 # Calculate taxes and price including taxes
2861 #
2862 global $login;
2863 $products_array["taxes"] = func_get_product_taxes($products_array, $login);
2864 }
2865
2866 if (!empty($active_modules["Product_Configurator"])) {
2867 include $xcart_dir."/modules/Product_Configurator/pconf_customer_price_modifier.php";
2868 }
2869
2870 $products_array["total"]=price_format($amount*$products_array["price"]);
2871 $products_array["product_options"]=$product_options;
2872 $products_array["options"]=$options;
2873 $products_array["amount"]=$amount;
2874
2875 $int_res = func_query_first ("SELECT * FROM $sql_tbl[products_lng] WHERE code='$store_language' AND productid=$productid");
2876 if (!empty($int_res["product"]))
2877 $products_array["product"] = stripslashes($int_res["product"]);
2878 if (!empty($int_res["descr"]))
2879 $products_array["descr"] = stripslashes($int_res["descr"]);
2880 if (!empty($int_res["full_descr"]))
2881 $products_array["fulldescr"] = stripslashes($int_res["full_descr"]);
2882
2883 if ($products_array["descr"] == strip_tags($products_array["descr"]))
2884 $products_array["descr"] = str_replace("\n", "<br>", $products_array["descr"]);
2885 if ($products_array["fulldescr"] == strip_tags($products_array["fulldescr"]))
2886 $products_array["fulldescr"] = str_replace("\n", "<br>", $products_array["fulldescr"]);
2887
2888 $products[] = $products_array;
2889 }
2890 }
2891
2892 return $products;
2893}
2894
2895#
2896# Calculate total weight of all products in cart
2897#
2898function func_weight_products($products) {
2899
2900 foreach($products as $product)
2901 $total_weight+=$product["weight"]*$product["amount"];
2902
2903 if (!$total_weight)
2904 $total_weight = 1;
2905
2906 return $total_weight;
2907}
2908
2909function func_weight_shipping_products ($products) {
2910 global $active_modules, $config;
2911
2912 $total_weight = 0;
2913
2914 foreach ($products as $product) {
2915 if ($product["free_shipping"] == "Y" or ($active_modules["Egoods"] and $product["distribution"] != "") or ($config["Shipping"]["replace_shipping_with_freight"] == "Y" and $product["shipping_freight"] > 0))
2916 continue;
2917 elseif (@$product["deleted"])
2918 continue;
2919 else
2920 $total_weight += $product["weight"] * $product["amount"];
2921 }
2922
2923 return $total_weight;
2924}
2925
2926#
2927# This function increments product rating
2928#
2929function func_increment_rating($productid) {
2930 global $sql_tbl;
2931
2932 db_query("update $sql_tbl[products] set rating=rating+1 where productid='$productid'");
2933}
2934
2935#
2936# This function creates array with order data
2937#
2938function func_select_order($orderid) {
2939 global $sql_tbl, $config, $merchant_password, $current_area, $active_modules;
2940
2941 $o_date = "date+'".$config["General"]["timezone_offset"]."' as date";
2942 $order = func_query_first("select *, $o_date from $sql_tbl[orders] where $sql_tbl[orders].orderid='$orderid'");
2943
2944 if (empty($order))
2945 return false;
2946
2947 $order["discounted_subtotal"] = $order["subtotal"] - $order["discount"] - $order["coupon_discount"];
2948
2949 if ($order["giftcert_ids"]) {
2950 $order["applied_giftcerts"] = split("\*", $order["giftcert_ids"]);
2951 if ($order["applied_giftcerts"]) {
2952 $tmp = array();
2953 foreach($order["applied_giftcerts"] as $k=>$v) {
2954 if ($v) {
2955 list($arr["giftcert_id"], $arr["giftcert_cost"]) = split(":", $v);
2956 $tmp[] = $arr;
2957 }
2958 }
2959 $order["applied_giftcerts"] = $tmp;
2960 }
2961 }
2962
2963 $shipping = func_query_first("select shipping from $sql_tbl[shipping] where shippingid='".$order["shippingid"]."'");
2964
2965 $order["shipping"] = $shipping["shipping"];
2966
2967 $order["details"]=text_decrypt($order["details"]);
2968 if($order["details"] === false) {
2969 $order["details"] = func_get_langvar_by_name("txt_this_data_encrypted");
2970 }
2971 $order["details"]=stripslashes($order["details"]);
2972 $order["notes"]=stripslashes($order["notes"]);
2973 $order["extra"] = @unserialize($order["extra"]);
2974 $extras = func_query("SELECT khash, value FROM $sql_tbl[order_extras] WHERE orderid = '$orderid'");
2975 if(!empty($extras)) {
2976 foreach($extras as $v)
2977 $order["extra"][$v["khash"]] = $v["value"];
2978 }
2979 if ($current_area != "C" && !empty($active_modules["Stop_List"]))
2980 if(func_ip_exist_slist($order["extra"]["ip"]))
2981 $order["blocked"] = "Y";
2982 if ($order["taxes_applied"])
2983 $order["applied_taxes"] = unserialize($order["taxes_applied"]);
2984
2985 if(preg_match("/NetBanx Reference: ([\w\d]+)/iSs", $order["details"], $preg)) {
2986 $order['netbanx_reference'] = $preg[1];
2987 }
2988
2989 #
2990 # Assign the display_* vars for displaying in the invoice
2991 #
2992 if (@$order["extra"]["tax_info"]["display_taxed_order_totals"] == "Y" && !empty($order["extra"]["tax_info"]["taxed_subtotal"]))
2993 $order["display_subtotal"] = $order["extra"]["tax_info"]["taxed_subtotal"];
2994 else
2995 $order["display_subtotal"] = $order["subtotal"];
2996
2997 if (@$order["extra"]["tax_info"]["display_taxed_order_totals"] == "Y" && !empty($order["extra"]["tax_info"]["taxed_discounted_subtotal"]))
2998 $order["display_discounted_subtotal"] = $order["extra"]["tax_info"]["taxed_discounted_subtotal"];
2999 else
3000 $order["display_discounted_subtotal"] = $order["discounted_subtotal"];
3001
3002 if (@$order["extra"]["tax_info"]["display_taxed_order_totals"] == "Y" && !empty($order["extra"]["tax_info"]["taxed_shipping"]))
3003 $order["display_shipping_cost"] = $order["extra"]["tax_info"]["taxed_shipping"];
3004 else
3005 $order["display_shipping_cost"] = $order["shipping_cost"];
3006
3007 list($order["b_address"], $order["b_address_2"]) = explode("\n", $order["b_address"]);
3008 $order["b_statename"] = func_get_state($order["b_state"], $order["b_country"]);
3009 $order["b_countryname"] = func_get_country($order["b_country"]);
3010 list($order["s_address"], $order["s_address_2"]) = explode("\n", $order["s_address"]);
3011 $order["s_statename"] = func_get_state($order["s_state"], $order["s_country"]);
3012 $order["s_countryname"] = func_get_country($order["s_country"]);
3013
3014 if ($config["General"]["use_counties"] == "Y") {
3015 $order["b_countyname"] = func_get_county($order["b_county"]);
3016 $order["s_countyname"] = func_get_county($order["s_county"]);
3017 }
3018
3019 return $order;
3020}
3021
3022#
3023# This function returns data about specified order ($orderid)
3024#
3025function func_order_data($orderid) {
3026 global $sql_tbl, $config, $smarty, $active_modules, $current_area, $xcart_dir;
3027
3028 $gc_add_date = "add_date+'".$config["General"]["timezone_offset"]."' as add_date";
3029 $o_date = "date+'".$config["General"]["timezone_offset"]."' as date";
3030
3031 if (!empty($active_modules["Egoods"]))
3032 $products = func_query("SELECT $sql_tbl[products].*, $gc_add_date, $sql_tbl[order_details].*, $sql_tbl[download_keys].download_key, $sql_tbl[download_keys].expires FROM $sql_tbl[order_details], $sql_tbl[products] LEFT JOIN $sql_tbl[download_keys] ON $sql_tbl[order_details].itemid=$sql_tbl[download_keys].itemid AND $sql_tbl[download_keys].productid=$sql_tbl[order_details].productid WHERE $sql_tbl[order_details].orderid='$orderid' AND $sql_tbl[order_details].productid=$sql_tbl[products].productid");
3033 else
3034 $products = func_query("SELECT $sql_tbl[products].*, $gc_add_date, $sql_tbl[order_details].* FROM $sql_tbl[order_details], $sql_tbl[products] WHERE $sql_tbl[order_details].orderid='$orderid' AND $sql_tbl[order_details].productid=$sql_tbl[products].productid");
3035 if (!is_array($products)) $products = array();
3036#
3037# If products are not present in products table, but they are present in
3038# order_details, then create fake $products from order_details data
3039#
3040 $tmp = func_query("select productid from $sql_tbl[order_details] where orderid='$orderid'");
3041 if (is_array($tmp) && count($products) != count($tmp)) {
3042 $missing = array();
3043 foreach ($tmp as $v) $missing[$v["productid"]] = 1;
3044
3045 foreach ($products as $v) unset($missing[$v["productid"]]);
3046
3047 $products_2 = func_query("select $sql_tbl[order_details].*, 'PRODUCT (deleted from database)' as product from $sql_tbl[order_details] where $sql_tbl[order_details].orderid='$orderid' and $sql_tbl[order_details].productid in ('".join("','",array_keys($missing))."')");
3048 if (is_array($products_2))
3049 $products = func_array_merge($products, $products_2);
3050 }
3051
3052 $giftcerts = func_query("select *, $gc_add_date from $sql_tbl[giftcerts] where orderid='$orderid'");
3053
3054 $order = func_select_order($orderid);
3055 if (!$order) {
3056 func_header_location("error_message.php?page_not_found");
3057 }
3058
3059 if($current_area == "A" || ($current_area == "P" && !empty($active_modules['Simple_Mode']))) {
3060 if(strpos($order['details'], "Card number:") !== false && file_exists($xcart_dir."/payment/cmpi.php"))
3061 $order['is_cc_payment'] = "Y";
3062 }
3063
3064 if(func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[order_details], $sql_tbl[download_keys] WHERE $sql_tbl[order_details].orderid = '$orderid' AND $sql_tbl[order_details].itemid = $sql_tbl[download_keys].itemid"))
3065 $order['is_egood'] = 'Y';
3066 elseif(func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[order_details], $sql_tbl[products] WHERE $sql_tbl[order_details].orderid = '$orderid' AND $sql_tbl[order_details].productid = $sql_tbl[products].productid AND $sql_tbl[products].distribution != ''"))
3067 $order['is_egood'] = 'E';
3068
3069 $userinfo = func_query_first("select *, $o_date from $sql_tbl[orders] where orderid='$orderid'");
3070 if(isset($order["extra"]['additional_fields'])) {
3071 $userinfo['additional_fields'] = $order["extra"]['additional_fields'];
3072 }
3073 $userinfo = func_array_merge(func_userinfo($userinfo["login"], "C"), $userinfo);
3074
3075 list($userinfo["b_address"], $userinfo["b_address_2"]) = split("[\n\r]+", $userinfo["b_address"]);
3076 list($userinfo["s_address"], $userinfo["s_address_2"]) = split("[\n\r]+", $userinfo["s_address"]);
3077
3078 $userinfo["s_countryname"] = $userinfo["s_country_text"] = func_get_country($userinfo["s_country"]);
3079 $userinfo["s_statename"] = $userinfo["s_state_text"] = func_get_state($userinfo["s_state"], $userinfo["s_country"]);
3080 $userinfo["b_statename"] = func_get_state($userinfo["b_state"], $userinfo["b_country"]);
3081 $userinfo["b_countryname"] = func_get_country($userinfo["b_country"]);
3082 if ($config["General"]["use_counties"] == "Y") {
3083 $userinfo["b_countyname"] = func_get_county($userinfo["b_county"]);
3084 $userinfo["s_countyname"] = func_get_county($userinfo["s_county"]);
3085 }
3086
3087 if (!$products)
3088 $products = array ();
3089
3090 if (preg_match("/(free_ship|percent|absolute)(``)(.+)/", $order["coupon"], $found)) {
3091 $order["coupon"] = $found[3];
3092 $order["coupon_type"] = $found[1];
3093 }
3094
3095 $order["extra"]["tax_info"]["product_tax_name"] = "";
3096 $_product_taxes = array();
3097
3098 foreach ($products as $k=>$v) {
3099
3100 $v['product_options_txt'] = $v['product_options'];
3101 if ($v["extra_data"]) {
3102 $v["extra_data"] = unserialize($v["extra_data"]);
3103 if (is_array(@$v["extra_data"]["display"])) {
3104 foreach ($v["extra_data"]["display"] as $i=>$j) {
3105 $v["display_".$i] = $j;
3106 }
3107 }
3108 if (is_array($v["extra_data"]["taxes"])) {
3109 foreach ($v["extra_data"]["taxes"] as $i=>$j) {
3110 if ($j["tax_value"] > 0)
3111 $_product_taxes[$i] = $j["tax_display_name"];
3112 }
3113 }
3114 }
3115
3116 $v["ordered_price"] = $v["price"];
3117 $v["price_deducted_tax"] = "Y";
3118
3119 #
3120 # Get the original price (current price in the database)
3121 #
3122 $v["original_price"] = func_query_first_cell("SELECT MIN(price) FROM $sql_tbl[pricing] WHERE productid='$v[productid]' AND (membership='' OR membership='$userinfo[membership]') AND quantity <='$v[amount]' AND $sql_tbl[pricing].variantid = 0");
3123 if (!empty($active_modules['Product_Options']) && $v['extra_data']['product_options']) {
3124 list($variant, $product_options) = func_get_product_options_data($v['productid'], $v['extra_data']['product_options'],$userinfo['membership']);
3125 if($product_options === false)
3126 unset($product_options);
3127 else {
3128 if(empty($variant['price']))
3129 $variant['price'] = $v["original_price"];
3130 $v["original_price"] = $variant['price'];
3131 unset($variant['price']);
3132 if($product_options)
3133 foreach($product_options as $o)
3134 $v["original_price"] += ($o['modifier_type'] == '%'?($v["original_price"]*$o['price_modifier']/100):$o['price_modifier']);
3135 $v['product_options'] = $product_options;
3136 if($v['product_options_txt']) {
3137 $flag_txt = false;
3138 foreach($v['product_options'] as $opt) {
3139 $flag_txt = preg_match("/".preg_quote($opt['class'],"/").": ".preg_quote($opt['option_name'], "/")."/Sm", $v['product_options_txt']);
3140 }
3141 if(!$flag_txt)
3142 $v['force_product_options_txt'] = true;
3143 }
3144 if(!empty($variant)) {
3145 $v = func_array_merge($v, $variant);
3146 }
3147 }
3148 }
3149
3150 $products[$k] = $v;
3151
3152 }
3153
3154 if (count($_product_taxes) > 0) {
3155 $order["extra"]["tax_info"]["display_cart_products_tax_rates"] = "Y";
3156 if (count($_product_taxes) == 1)
3157 $order["extra"]["tax_info"]["product_tax_name"] = array_pop($_product_taxes);
3158 }
3159 else
3160 $order["extra"]["tax_info"]["display_cart_products_tax_rates"] = "N";
3161
3162 if ($order["coupon_type"] == "free_ship") {
3163 $order["shipping_cost"] = $order["coupon_discount"];
3164 $order["discounted_subtotal"] += $order["coupon_discount"];
3165 }
3166
3167 return(array("order"=>$order,"products"=>$products,"userinfo"=>$userinfo, "giftcerts"=>$giftcerts));
3168}
3169
3170#
3171# Decrease number of products in stock and increase product rating
3172#
3173function func_decrease_quantity($products) {
3174 foreach ($products as $product) {
3175 func_increment_rating($product["productid"]);
3176 }
3177
3178 func_update_quantity($products, false);
3179}
3180
3181#
3182# This function creates order entry in orders table
3183#
3184function func_place_order($payment_method, $order_status, $order_details, $extra = array(), $extras = array()) {
3185
3186 global $cart, $userinfo, $discount_coupon, $mail_smarty, $config, $active_modules, $single_mode, $partner, $adv_campaignid, $partner_clickid;
3187 global $sql_tbl, $to_customer;
3188 global $wlid;
3189 global $xcart_dir, $REMOTE_ADDR, $PROXY_IP, $CLIENT_IP, $add_to_cart_time;
3190 global $arb_account_used, $arb_account;
3191
3192 $mintime = 10;
3193 #
3194 # Lock place order process
3195 #
3196 $LOCK = func_lock("place_order");
3197
3198 $check_order = func_query_first("SELECT orderid FROM $sql_tbl[orders] WHERE login='".addslashes($userinfo["login"])."' AND '".time()."'-date<'$mintime'");
3199 if ($check_order) {
3200 func_unlock($LOCK);
3201 return false;
3202 }
3203
3204 if (($order_status != "I") && ($order_status != "Q")) {
3205 func_unlock($LOCK);
3206 return false;
3207 }
3208
3209 $userinfo["email"] = addslashes($userinfo["email"]);
3210
3211 $orderids = array ();
3212
3213 #
3214 # REMOTE_ADDR and PROXY_IP
3215 #
3216 $extras['ip'] = $CLIENT_IP;
3217 $extras['proxy_ip'] = $PROXY_IP;
3218 if($add_to_cart_time > 0)
3219 $extras['add_to_cart_time'] = time() - $add_to_cart_time;
3220
3221 $products = func_products_in_cart($cart, $userinfo["membership"]);
3222
3223 func_decrease_quantity($products);
3224
3225 $giftcert_discount = $cart["giftcert_discount"];
3226 if ($cart["applied_giftcerts"]) {
3227 foreach($cart["applied_giftcerts"] as $k=>$v) {
3228 $giftcert_str = join("*", array(@$giftcert_str, "$v[giftcert_id]:$v[giftcert_cost]"));
3229 db_query("UPDATE $sql_tbl[giftcerts] SET status='U' WHERE gcid='$v[giftcert_id]'");
3230 }
3231 }
3232
3233 $giftcert_id = @$cart["giftcert_id"];
3234
3235 $extra = "";
3236 if (!empty($active_modules["Anti_Fraud"]))
3237 include $xcart_dir."/modules/Anti_Fraud/anti_fraud.php";
3238
3239 #
3240 # Store Airborne account information into $order_details
3241 #
3242 x_session_register("arb_account_used");
3243 x_session_register("arb_account");
3244 if ($arb_account_used) {
3245 $_code = func_query_first_cell("SELECT code FROM $sql_tbl[shipping] WHERE shippingid='$cart[shippingid]'");
3246 if ($_code == "ARB")
3247 $order_details = func_get_langvar_by_name("lbl_arb_account").": ".$arb_account."\n".$order_details;
3248 }
3249 $extra['additional_fields'] = $userinfo['additional_fields'];
3250
3251 foreach ($cart["orders"] as $current_order) {
3252
3253 $_extra = $extra;
3254 $_extra["tax_info"] = array (
3255 "display_taxed_order_totals" => $config["Taxes"]["display_taxed_order_totals"],
3256 "display_cart_products_tax_rates" => $config["Taxes"]["display_cart_products_tax_rates"] == "Y",
3257 "taxed_subtotal" => $current_order["display_subtotal"],
3258 "taxed_discounted_subtotal" => $current_order["display_discounted_subtotal"],
3259 "taxed_shipping" => $current_order["display_shipping_cost"]
3260 );
3261
3262 if (!empty($active_modules["Special_Offers"]))
3263 include $xcart_dir."/modules/Special_Offers/place_order_extra.php";
3264
3265 if (!$single_mode) {
3266 $giftcert_discount = $current_order["giftcert_discount"];
3267 $giftcert_str = "";
3268 if ($current_order["applied_giftcerts"]) {
3269 foreach($current_order["applied_giftcerts"] as $k=>$v)
3270 $giftcert_str = join("*", array($giftcert_str, "$v[giftcert_id]:$v[giftcert_cost]"));
3271 }
3272 }
3273
3274 $taxes_applied = addslashes(serialize($current_order["taxes"]));
3275
3276 $discount_coupon = $current_order["coupon"];
3277 if (!empty($current_order["coupon"])) {
3278 $current_order["coupon"] = func_query_first_cell("SELECT coupon_type FROM $sql_tbl[discount_coupons] WHERE coupon='".addslashes($current_order["coupon"])."'")."``".$current_order["coupon"];
3279 }
3280
3281 $save_info = $userinfo;
3282 $userinfo["b_address"] .= "\n".$userinfo["b_address_2"];
3283 $userinfo["s_address"] .= "\n".$userinfo["s_address_2"];
3284
3285#
3286# Insert into orders
3287#
3288 db_query("INSERT INTO $sql_tbl[orders] (login, membership, total, giftcert_discount, giftcert_ids, subtotal, shipping_cost, shippingid, tax, taxes_applied, discount, coupon, coupon_discount, date, status, payment_method, flag, details, title, firstname, lastname, company, b_title, b_firstname, b_lastname, b_address, b_city, b_county, b_state, b_country, b_zipcode, s_title, s_firstname, s_lastname, s_address, s_city, s_county, s_state, s_country, s_zipcode, phone, fax, email, url, clickid, extra) VALUES ('".addslashes($userinfo["login"])."', '".addslashes($userinfo["membership"])."', '$current_order[total_cost]', '$giftcert_discount', '".@$giftcert_str."', '$current_order[subtotal]','$current_order[shipping_cost]', '$cart[shippingid]', '$current_order[tax_cost]', '$taxes_applied', '$current_order[discount]', '".addslashes(@$current_order["coupon"])."', '$current_order[coupon_discount]', '".time()."', '$order_status', '".addslashes($payment_method)."', 'N', '".addslashes(text_crypt($order_details))."', '".addslashes($userinfo["title"])."', '".addslashes($userinfo["firstname"])."', '".addslashes($userinfo["lastname"])."', '".addslashes($userinfo["company"])."', '".addslashes($userinfo["b_title"])."', '".addslashes($userinfo["b_firstname"])."', '".addslashes($userinfo["b_lastname"])."', '".addslashes($userinfo["b_address"])."', '".addslashes($userinfo["b_city"])."', '".addslashes(@$userinfo["b_county"])."', '".addslashes($userinfo["b_state"])."', '".addslashes($userinfo["b_country"])."', '".addslashes(strtoupper($userinfo["b_zipcode"]))."', '".addslashes($userinfo["s_title"])."', '".addslashes($userinfo["s_firstname"])."', '".addslashes($userinfo["s_lastname"])."', '".addslashes($userinfo["s_address"])."', '".addslashes($userinfo["s_city"])."', '".addslashes(@$userinfo["s_county"])."', '".addslashes($userinfo["s_state"])."', '".addslashes($userinfo["s_country"])."', '".addslashes(strtoupper($userinfo["s_zipcode"]))."', '".addslashes($userinfo["phone"])."', '".addslashes($userinfo["fax"])."', '$userinfo[email]', '".addslashes($userinfo["url"])."', '$partner_clickid', '".addslashes(serialize($_extra))."')");
3289
3290 $orderid=db_insert_id();
3291
3292 if(!empty($extras)) {
3293 foreach($extras as $k => $v) {
3294 if(!empty($v))
3295 db_query("INSERT INTO $sql_tbl[order_extras] (orderid, khash, value) VALUES ('$orderid', '".addslashes($k)."', '".addslashes($v)."')");
3296 }
3297 }
3298
3299 $userinfo = $save_info;
3300
3301 $orderids[] = $orderid;
3302 $order=func_select_order($orderid);
3303
3304#
3305# Insert into order details
3306#
3307 foreach($products as $pk => $product) {
3308 if (($single_mode) or ($product["provider"] == $current_order["provider"])) {
3309 $product["price"] = price_format($product["price"]);
3310 $product["extra_data"]["product_options"] = $product["options"];
3311 $product["extra_data"]["taxes"] = $product["taxes"];
3312 $product["extra_data"]["display"]["price"] = price_format($product["display_price"]);
3313 $product["extra_data"]["display"]["discounted_price"] = price_format($product["display_discounted_price"]);
3314 $product["extra_data"]["display"]["subtotal"] = price_format($product["display_subtotal"]);
3315 if(!empty($active_modules['Product_Options']))
3316 $product["product_options"] = func_serialize_options($product["options"]);
3317 db_query("INSERT INTO $sql_tbl[order_details] (orderid, productid, product_options, amount, price, provider, extra_data, productcode) VALUES ('$orderid','$product[productid]','".addslashes($product["product_options"])."','$product[amount]','$product[price]','".addslashes($product["provider"])."','".addslashes(serialize($product["extra_data"]))."','".addslashes($product['productcode'])."')");
3318 $products[$pk]['itemid'] = db_insert_id();
3319
3320#
3321# Insert into subscription_customers table (for subscription products)
3322#
3323 if (!empty($active_modules["Subscriptions"]))
3324 include $xcart_dir."/modules/Subscriptions/subscriptions_cust.php";
3325
3326#
3327# Check if this product is in Wish list
3328#
3329 if (!empty($active_modules["Wishlist"]))
3330 include $xcart_dir."/modules/Wishlist/place_order.php";
3331
3332 if (!empty($active_modules["Recommended_Products"])) {
3333 $rec_counter = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[stats_customers_products] WHERE productid='$product[productid]' AND login='".addslashes($userinfo["login"])."'");
3334 if (!empty($rec_counter))
3335 db_query("UPDATE $sql_tbl[stats_customers_products] SET counter='".($rec_counter+1)."' WHERE productid='$product[productid]' AND login='".addslashes($userinfo["login"])."'");
3336 else
3337 db_query("INSERT INTO $sql_tbl[stats_customers_products] (productid, login, counter) VALUES ('$product[productid]', '".addslashes($userinfo["login"])."', '1')");
3338 }
3339
3340 }
3341 }
3342
3343#
3344# Partner commission
3345#
3346 if ($partner)
3347 include $xcart_dir."/include/partner_commission.php";
3348#
3349# Save link order -> advertising campaign
3350#
3351 if ($adv_campaignid)
3352 include $xcart_dir."/include/adv_campaign_commission.php";
3353
3354if ((($single_mode) or (empty($current_order["provider"]))) and (!empty($cart["giftcerts"]))) {
3355 foreach($cart["giftcerts"] as $giftcert) {
3356
3357 $gcid = strtoupper(md5(uniqid(rand())));
3358#
3359# status == Pending!
3360#
3361 db_query("insert into $sql_tbl[giftcerts] (gcid, orderid, purchaser, recipient, send_via, recipient_email, recipient_firstname, recipient_lastname, recipient_address, recipient_city, recipient_state, recipient_country, recipient_zipcode, recipient_phone, message, amount, debit, status, add_date) values ('$gcid', '$orderid','".addslashes($giftcert["purchaser"])."','".addslashes($giftcert["recipient"])."','$giftcert[send_via]','".@$giftcert["recipient_email"]."','".addslashes(@$giftcert["recipient_firstname"])."','".addslashes(@$giftcert["recipient_lastname"])."','".addslashes(@$giftcert["recipient_address"])."','".addslashes(@$giftcert["recipient_city"])."','".@$giftcert["recipient_state"]."','".@$giftcert["recipient_country"]."','".@$giftcert["recipient_zipcode"]."','".@$giftcert["recipient_phone"]."','".addslashes($giftcert["message"])."','$giftcert[amount]','$giftcert[amount]','P','".time()."')");
3362
3363#
3364# Check if this giftcertificate is in Wish list
3365#
3366 if (!empty($active_modules["Wishlist"]))
3367 include $xcart_dir."/modules/Wishlist/place_order.php";
3368
3369 }
3370}
3371
3372#
3373# Mark discount coupons used
3374#
3375
3376 if ($discount_coupon) {
3377 db_query("update $sql_tbl[discount_coupons] set times_used=times_used+1 where coupon='$discount_coupon'");
3378 db_query("update $sql_tbl[discount_coupons] set status='U' where coupon='$discount_coupon' and times_used=times");
3379 $discount_coupon="";
3380 }
3381
3382#
3383# Mail template processing
3384#
3385
3386 $admin_notify = (($order_status == "Q") || ($order_status == "I" && $config["Email_Note"]["enable_init_order_notif"] == "Y"));
3387 $customer_notify = (($order_status == "Q") || ($order_status == "I" && $config["Email_Note"]["enable_init_order_notif_customer"] == "Y"));
3388
3389 $order_data = func_order_data($orderid);
3390 $mail_smarty->assign("products",$order_data["products"]);
3391 $mail_smarty->assign("giftcerts",$order_data["giftcerts"]);
3392 $mail_smarty->assign("order",$order_data["order"]);
3393 $mail_smarty->assign("userinfo",$order_data["userinfo"]);
3394
3395 $prefix = ($order_status=="I"?"init_":"");
3396
3397 if ($customer_notify) {
3398#
3399# Notify customer by email
3400#
3401 $to_customer = ($userinfo['language']?$userinfo['language']:$config['default_customer_language']);
3402 $mail_smarty->assign("products", func_translate_products($order_data["products"], $to_customer));
3403 func_send_mail($userinfo["email"], "mail/".$prefix."order_customer_subj.tpl", "mail/".$prefix."order_customer.tpl", $config["Company"]["orders_department"], false);
3404 }
3405
3406 $mail_smarty->assign("products",$order_data["products"]);
3407 if ($admin_notify) {
3408#
3409# Notify orders department by email
3410#
3411 $mail_smarty->assign("show_order_details", "Y");
3412 func_send_mail($config["Company"]["orders_department"], "mail/".$prefix."order_notification_subj.tpl", "mail/order_notification_admin.tpl", $userinfo["email"], true, true);
3413 $mail_smarty->assign("show_order_details", "");
3414
3415#
3416# Notify provider (or providers) by email
3417#
3418 if ((!$single_mode) and ($current_order["provider"])) {
3419 $pr_result = func_query_first ("SELECT email, language FROM $sql_tbl[customers] WHERE login='$current_order[provider]'");
3420 $prov_email = $pr_result ["email"];
3421 if ($prov_email != $config["Company"]["orders_department"]) {
3422 $to_customer = $pr_result['language'];
3423 if(empty($to_customer))
3424 $to_customer = $config['default_admin_language'];
3425 func_send_mail($prov_email, "mail/".$prefix."order_notification_subj.tpl", "mail/order_notification.tpl", $userinfo["email"], false);
3426 }
3427 }
3428 elseif ($config["Email_Note"]["send_notifications_to_provider"] == "Y") {
3429 $providers = array();
3430 foreach($products as $product) {
3431 $pr_result = func_query_first("select email, language from $sql_tbl[customers] where login='$product[provider]'");
3432 if ($pr_result["email"])
3433 $providers[$product['provider']] = $pr_result;
3434 }
3435
3436 if ($providers) {
3437 foreach($providers as $prov_data)
3438 if ($prov_data['email'] != $config["Company"]["orders_department"]) {
3439 $to_customer = $prov_data['language'];
3440 if(empty($to_customer))
3441 $to_customer = $config['default_admin_language'];
3442 func_send_mail($prov_data['email'], "mail/".$prefix."order_notification_subj.tpl", "mail/order_notification.tpl", $userinfo["email"], false);
3443 }
3444 }
3445 }
3446 }
3447}
3448
3449#
3450# Send notifications to orders department and providers when product amount in stock is low
3451#
3452 if ($config["General"]["unlimited_products"]!="Y")
3453 foreach($order_data["products"] as $product) {
3454
3455 if (!empty($product["distribution"]) && $active_modules["Egoods"])
3456 continue;
3457
3458 if ($product['product_type'] == 'C' && !empty($active_modules['Product_Configurator']))
3459 continue;
3460
3461 if($active_modules['Product_Options'] && $product['extra_data']['product_options']) {
3462 $avail_now = func_get_options_amount($product['extra_data']['product_options'], $product['productid']);
3463 } else {
3464 $avail_now = func_query_first_cell("SELECT avail FROM $sql_tbl[products] WHERE productid=".$product["productid"]);
3465 }
3466 if ($product['low_avail_limit'] >= $avail_now && $config['Email_Note']['eml_lowlimit_warning'] == 'Y') {
3467#
3468# Mail template processing
3469#
3470 $product['avail'] = $avail_now;
3471 $mail_smarty->assign("product", $product);
3472
3473 func_send_mail($config["Company"]["orders_department"], "mail/lowlimit_warning_notification_subj.tpl", "mail/lowlimit_warning_notification_admin.tpl", $config["Company"]["orders_department"], true);
3474
3475 $pr_result = func_query_first ("SELECT email, language FROM $sql_tbl[customers] WHERE login='".$product["provider"]."'");
3476 if((!$single_mode) and ($pr_result["email"]!=$config["Company"]["orders_department"]) && $config['Email_Note']['eml_lowlimit_warning_provider'] == 'Y') {
3477 $to_customer = $pr_result['language'];
3478 if(empty($to_customer))
3479 $to_customer = $config['default_admin_language'];
3480 func_send_mail($pr_result["email"], "mail/lowlimit_warning_notification_subj.tpl", "mail/lowlimit_warning_notification_admin.tpl", $config["Company"]["orders_department"], false);
3481 }
3482 }
3483 }
3484
3485 #
3486 # Release previously created lock
3487 #
3488 func_unlock($LOCK);
3489
3490 return $orderids;
3491}
3492
3493
3494#
3495# This function change order status in orders table
3496#
3497function func_change_order_status($orderids, $status, $advinfo="")
3498{
3499 global $config, $mail_smarty, $active_modules, $current_area;
3500 global $sql_tbl;
3501 global $session_failed_transaction;
3502
3503 if(!is_array($orderids))$orderids = array($orderids);
3504
3505 foreach($orderids as $orderid) {
3506 $order_data = func_order_data($orderid);
3507 $order=$order_data["order"];
3508
3509 if($advinfo)
3510 $info = addslashes(text_crypt($order["details"]."\n--- Advanced info ---\n".$advinfo));
3511
3512 db_query("update $sql_tbl[orders] set status='$status'".(($advinfo)? ", details='".$info."'" : "")." where orderid='$orderid'");
3513
3514 if($status == "P" && $order["status"] != "P") {
3515 func_process_order($orderid);
3516 if($order["status"] == 'I' && !empty($active_modules["Anti_Fraud"]) && $config['Modules']['anti_fraud_license'] && ($current_area != 'A' && $current_area != 'P')) {
3517 $total_trust_score = $order['Anti_Fraud']['total_trust_score'];
3518 $available_request = $order['Anti_Fraud']['available_request'];
3519 $used_request = $order['Anti_Fraud']['used_request'];
3520 if($order['Anti_Fraud']['total_trust_score'] > $config['Modules']['anti_fraud_limit'] || ($available_request <= $used_request && $available_request > 0)) {
3521 db_query("UPDATE $sql_tbl[orders] set status='Q' WHERE orderid='$orderid'");
3522 }
3523 }
3524 }
3525 elseif($status == "D" && $order["status"] != "D" && $order["status"] != "F") {
3526 func_decline_order($orderid, $status);
3527 }
3528 elseif($status == "F" && $order["status"] != "F" && $order["status"] != "D") {
3529 func_update_quantity($order_data["products"]);
3530 if($current_area == 'C')
3531 $session_failed_transaction++;
3532 }
3533 elseif ($status == "C" && $order["status"] != "C") {
3534 func_complete_order($orderid);
3535 }
3536 #
3537 # Decrease quantity in stock when "declined" or "failed" order is became "completed", "processed" or "queued"
3538 #
3539 if ($status != $order["status"] && strpos("DF",$order["status"])!==false && strpos("CPQ",$status)!==false) {
3540 func_update_quantity($order_data["products"],false);
3541 }
3542 }
3543}
3544
3545
3546#
3547# This function performs activities needed when order is processed
3548#
3549function func_process_order($orderids) {
3550
3551 global $config, $mail_smarty, $active_modules;
3552 global $sql_tbl, $partner, $to_customer;
3553 global $single_mode;
3554 global $xcart_dir;
3555
3556 if (empty($orderids))
3557 return false;
3558
3559 if (!is_array($orderids))
3560 $orderids = array($orderids);
3561
3562 foreach($orderids as $orderid) {
3563
3564 if (empty($orderid))
3565 continue;
3566
3567 $order_data = func_order_data($orderid);
3568
3569 $order = $order_data["order"];
3570 $userinfo = $order_data["userinfo"];
3571 $products = $order_data["products"];
3572 $giftcerts = $order_data["giftcerts"];
3573
3574 $mail_smarty->assign("customer",$userinfo);
3575 $mail_smarty->assign("products",$products);
3576 $mail_smarty->assign("giftcerts",$giftcerts);
3577 $mail_smarty->assign("order",$order);
3578
3579#
3580# Order processing routine
3581# Send gift certificates
3582#
3583 if ($order["applied_giftcerts"]) {
3584 #
3585 # Search for enabled to applying GC
3586 #
3587 $flag = true;
3588 foreach($order["applied_giftcerts"] as $k=>$v) {
3589 $res = func_query_first("SELECT gcid FROM $sql_tbl[giftcerts] WHERE gcid='$v[giftcert_id]' AND debit>='$v[giftcert_cost]'");
3590 if (!$res["gcid"]) {
3591 $flag = false;
3592 break;
3593 }
3594 }
3595 #
3596 # Decrease debit for applied GC
3597 #
3598 if ($flag)
3599 foreach($order["applied_giftcerts"] as $k=>$v) {
3600 db_query("UPDATE $sql_tbl[giftcerts] SET debit=debit-'$v[giftcert_cost]' WHERE gcid='$v[giftcert_id]'");
3601 db_query("UPDATE $sql_tbl[giftcerts] SET status='A' WHERE debit>0 AND gcid='$v[giftcert_id]'");
3602 db_query("UPDATE $sql_tbl[giftcerts] SET status='U' WHERE debit<=0 AND gcid='$v[giftcert_id]'");
3603 }
3604 else
3605 return false;
3606 }
3607
3608
3609 if ($giftcerts)
3610 foreach($giftcerts as $giftcert) {
3611 db_query("update $sql_tbl[giftcerts] set status='A' where gcid='$giftcert[gcid]'");
3612 if ($giftcert["send_via"] == "E")
3613 func_send_gc($userinfo["email"], $giftcert, $userinfo['login']);
3614 }
3615
3616 #
3617 # Send mail notifications
3618 #
3619 if (!$single_mode) {
3620 $providers= func_query("select provider from $sql_tbl[order_details] where $sql_tbl[order_details].orderid='$orderid' group by provider");
3621
3622 if ($providers && $config['Email_Note']['eml_order_p_notif_provider'] == 'Y') {
3623 foreach($providers as $provider) {
3624 $email_pro = func_query_first_cell("SELECT email FROM $sql_tbl[customers] WHERE login='$provider[provider]'");
3625 if (!empty($email_pro) && $email_pro != $config["Company"]["orders_department"]) {
3626 $to_customer = func_query_first_cell ("SELECT language FROM $sql_tbl[customers] WHERE login='$provider[provider]'");
3627 if(empty($to_customer))
3628 $to_customer = $config['default_admin_language'];
3629 func_send_mail($email_pro, "mail/order_notification_subj.tpl", "mail/order_notification.tpl", $config["Company"]["orders_department"], false);
3630 }
3631 }
3632 }
3633 }
3634 $to_customer = func_query_first_cell ("SELECT language FROM $sql_tbl[customers] WHERE login='$userinfo[login]'");
3635 if(empty($to_customer))
3636 $to_customer = $config['default_customer_language'];
3637 if($config['Email_Note']['eml_order_p_notif_customer'] == 'Y') {
3638 $mail_smarty->assign("products", func_translate_products($products, $to_customer));
3639 func_send_mail($userinfo["email"], "mail/order_cust_processed_subj.tpl", "mail/order_customer_processed.tpl", $config["Company"]["orders_department"], false);
3640 }
3641 $mail_smarty->assign("products",$products);
3642 $mail_smarty->assign("show_order_details", "Y");
3643 if($config['Email_Note']['eml_order_p_notif_admin'] == 'Y') {
3644 func_send_mail($config["Company"]["orders_department"], "mail/order_notification_subj.tpl", "mail/order_notification_admin.tpl", $config["Company"]["orders_department"], true, true);
3645 }
3646 # SPM added below to send CSV order email
3647 func_send_csv_mail($order,$products);
3648 $mail_smarty->assign("show_order_details", "");
3649
3650 #
3651 # Send E-goods download keys
3652 #
3653 if(!empty($active_modules["Egoods"]))
3654 include $xcart_dir."/modules/Egoods/send_keys.php";
3655
3656 #
3657 # Update statistics for sold products
3658 #
3659 if ($active_modules["Advanced_Statistics"]) {
3660 include $xcart_dir."/modules/Advanced_Statistics/prod_sold.php";
3661 }
3662
3663 }
3664}
3665
3666#
3667# This function performs activities needed when order is complete
3668#
3669function func_complete_order($orderid) {
3670 global $config, $mail_smarty, $active_modules;
3671 global $sql_tbl, $to_customer;
3672 global $xcart_dir;
3673
3674 $order_data = func_order_data($orderid);
3675
3676 $order = $order_data["order"];
3677 $userinfo = $order_data["userinfo"];
3678 $products = $order_data["products"];
3679 $giftcerts = $order_data["giftcerts"];
3680
3681 $mail_smarty->assign("customer",$userinfo);
3682 $mail_smarty->assign("products",$products);
3683 $mail_smarty->assign("giftcerts",$giftcerts);
3684 $mail_smarty->assign("order",$order);
3685
3686 if (!empty($active_modules["Special_Offers"])) {
3687 include $xcart_dir."/modules/Special_Offers/complete_order.php";
3688 }
3689
3690 #
3691 # Send mail notifications
3692 #
3693 if ($config['Email_Note']['eml_order_c_notif_customer'] == 'Y') {
3694 $to_customer = func_query_first_cell ("SELECT language FROM $sql_tbl[customers] WHERE login='$userinfo[login]'");
3695 if(empty($to_customer))
3696 $to_customer = $config['default_customer_language'];
3697 $mail_smarty->assign("products", func_translate_products($products, $to_customer));
3698 func_send_mail($userinfo["email"], "mail/order_cust_complete_subj.tpl", "mail/order_customer_complete.tpl", $config["Company"]["orders_department"], false);
3699 }
3700
3701 if (!empty($active_modules["SnS_connector"])) {
3702 func_generate_sns_action("Order", $orderid);
3703 }
3704}
3705
3706#
3707# This function joins order_id's and urlencodes 'em
3708#
3709function func_get_urlencoded_orderids ($orderids) {
3710 if (is_array($orderids))
3711 return urlencode (join (",", $orderids));
3712}
3713
3714#
3715# This function performs activities nedded when order is declined
3716# status may be assign (D)ecline or (F)ail
3717# (D)ecline order sent mail to customer, (F)ail - not
3718#
3719function func_decline_order($orderids, $status = "D") {
3720
3721 global $config, $mail_smarty;
3722 global $sql_tbl, $to_customer;
3723
3724 if(($status != "D") && ($status != "F")) return;
3725
3726 if(!is_array($orderids))$orderids = array($orderids);
3727
3728 foreach($orderids as $orderid)
3729 {
3730#
3731# Order decline routine
3732#
3733 $order_data = func_order_data($orderid);
3734
3735 $order = $order_data["order"];
3736 $userinfo = $order_data["userinfo"];
3737 $products = $order_data["products"];
3738 $giftcerts = $order_data["giftcerts"];
3739
3740 # Send mail notifications
3741 if($status == "D")
3742 {
3743 $mail_smarty->assign("customer",$userinfo);
3744 $mail_smarty->assign("products",$products);
3745 $mail_smarty->assign("giftcerts",$giftcerts);
3746 $mail_smarty->assign("order",$order);
3747
3748 if($config['Email_Note']['eml_order_d_notif_customer'] == 'Y') {
3749 $to_customer = func_query_first_cell ("SELECT language FROM $sql_tbl[customers] WHERE login='$userinfo[login]'");
3750 if(empty($to_customer))
3751 $to_customer = $config['default_customer_language'];
3752 $mail_smarty->assign("products", func_translate_products($products, $to_customer));
3753 func_send_mail($userinfo["email"], "mail/decline_notification_subj.tpl","mail/decline_notification.tpl", $config["Company"]["orders_department"], false);
3754 }
3755 }
3756
3757#
3758# Discount restoring
3759#
3760 $discount_coupon = $order["coupon"];
3761 if ($discount_coupon) {
3762 db_query("update $sql_tbl[discount_coupons] set status='A' where coupon='$discount_coupon' and times_used=times");
3763 db_query("update $sql_tbl[discount_coupons] set times_used=times_used-1 where coupon='$discount_coupon'");
3764 $discount_coupon="";
3765 }
3766
3767#
3768# Increase debit for declined GC
3769#
3770 if ($order["applied_giftcerts"])
3771 foreach($order["applied_giftcerts"] as $k=>$v)
3772 {
3773 if($order["status"]=="P" || $order["status"]=="C") {
3774 db_query("UPDATE $sql_tbl[giftcerts] SET debit=debit+'$v[giftcert_cost]' WHERE gcid='$v[giftcert_id]'");
3775 }
3776 db_query("UPDATE $sql_tbl[giftcerts] SET status='A' WHERE debit>0 and gcid='$v[giftcert_id]'");
3777 }
3778
3779
3780
3781# Set GC's status to 'D'
3782 if ($giftcerts)
3783 foreach($giftcerts as $giftcert)
3784 {
3785 db_query("update $sql_tbl[giftcerts] set status='D' where gcid='$giftcert[gcid]'");
3786 }
3787
3788 if ($config["General"]["unlimited_products"] != "Y")
3789 func_update_quantity ($products);
3790
3791 }
3792}
3793
3794#
3795# This function returns true if $cart is empty
3796#
3797function func_is_cart_empty($cart) {
3798 return (empty($cart) or !(@$cart["products"] || @$cart["giftcerts"]));
3799}
3800
3801#
3802# This function sends GC emails (called from func_place_order
3803# and provider/order.php"
3804#
3805function func_send_gc($from_email, $giftcert, $from_login = '') {
3806 global $mail_smarty, $config, $to_customer, $sql_tbl;
3807
3808 $giftcert["purchaser_email"] = $from_email;
3809 $mail_smarty->assign("giftcert", $giftcert);
3810
3811#
3812# Send notifs to $orders_department & purchaser
3813#
3814 if($config['Email_Note']['eml_giftcert_notif_purchaser'] == 'Y') {
3815 if(!empty($from_login)) {
3816 $to_customer = func_query_first_cell("SELECT language FROM $sql_tbl[customers] WHERE login = '$from_login'");
3817 if(empty($to_customer))
3818 $to_customer = $config['default_customer_language'];
3819 }
3820 func_send_mail($from_email, "mail/giftcert_notification_subj.tpl", "mail/giftcert_notification.tpl", $config["Company"]["orders_department"], false);
3821 }
3822 if($config['Email_Note']['eml_giftcert_notif_admin'] == 'Y') {
3823 func_send_mail($config["Company"]["orders_department"], "mail/giftcert_notification_subj.tpl", "mail/giftcert_notification.tpl", $from_email, true);
3824 }
3825#
3826# Send GC to recipient
3827#
3828 $to_customer = '';
3829 func_send_mail($giftcert["recipient_email"], "mail/giftcert_subj.tpl", "mail/giftcert.tpl", $from_email, false);
3830}
3831
3832function func_pgp_encrypt($message) {
3833 global $config;
3834
3835 if(!$config['Security']['crypt_method']) {
3836 return $message;
3837 }
3838 $fn = func_temp_store($message);
3839 $gfile = func_temp_store("");
3840 if($config['Security']['crypt_method'] == 'G') {
3841 putenv("GNUPGHOME=".$config["GnuPG"]["gpg_home_dir"]);
3842
3843 $gpg_prog = func_shellquote($config["GnuPG"]["gpg_prog"]);
3844 $gpg_key = $config["GnuPG"]["gpg_key"];
3845
3846 @exec($gpg_prog.' --always-trust -a --batch --yes --recipient "'.$gpg_key.'" --encrypt '.func_shellquote($fn)." 2>".func_shellquote($gfile));
3847 } else {
3848 putenv("PGPPATH=".$config["PGP"]["pgp_home_dir"]);
3849 putenv("PGPHOME=".$config["PGP"]["pgp_home_dir"]);
3850
3851 $pgp_prog = func_shellquote($config["PGP"]["pgp_prog"]);
3852 $pgp_key = $config["PGP"]["pgp_key"];
3853
3854 if ($config["PGP"]["use_pgp6"] == "Y") {
3855 @exec($pgp_prog." +batchmode +force -ea ".func_shellquote($fn)." \"$pgp_key\" 2>".func_shellquote($gfile));
3856 } else {
3857 @exec($pgp_prog.' +batchmode +force -fea "'.$pgp_key.'" < '.func_shellquote($fn).' > '.func_shellquote($fn).".asc 2>".func_shellquote($gfile));
3858 }
3859 }
3860 $af = preg_replace('!\.[^\\\/]+$!', '', $fn).".asc";
3861 $message = func_temp_read($af, true);
3862 $config["PGP_output"] = func_temp_read($gfile, true);
3863 @unlink($fn);
3864 return $message;
3865}
3866
3867#
3868# Move products back to the inventory
3869#
3870function func_update_quantity($products,$increase=true) {
3871 global $config, $sql_tbl, $active_modules;
3872
3873 $symbol = ($increase?"+":"-");
3874 if ($config["General"]["unlimited_products"] != "Y" && is_array($products)) {
3875 foreach ($products as $product) {
3876 if ($product['product_type'] == 'C' && !empty($active_modules['Product_Configurator']))
3877 continue;
3878
3879 $variantid = "";
3880 if(!empty($active_modules['Product_Options']) && (!empty($product['extra_data']['product_options']) || !empty($product['options']))) {
3881 $options = (!empty($product['extra_data']['product_options'])?$product['extra_data']['product_options']:$product['options']);
3882 $variantid = func_get_variantid($options);
3883 }
3884 if(!empty($variantid)) {
3885 db_query("UPDATE $sql_tbl[variants] SET avail=avail$symbol'$product[amount]' WHERE variantid = '$variantid'");
3886 func_set_product_by_variants($product['productid']);
3887 } else {
3888 $egoods_cond = $active_modules["Egoods"]?" AND distribution=''":"";
3889 db_query("UPDATE $sql_tbl[products] SET avail=avail$symbol'$product[amount]' WHERE productid='$product[productid]'".$egoods_cond);
3890 }
3891 }
3892 }
3893}
3894
3895function func_pgp_remove_key() {
3896 global $config;
3897
3898 if(!$config['Security']['crypt_method']) {
3899 return false;
3900 }
3901
3902 if($config['Security']['crypt_method'] == 'G') {
3903 putenv("GNUPGHOME=".$config["GnuPG"]["gpg_home_dir"]);
3904
3905 $gpg_prog = func_shellquote($config["GnuPG"]["gpg_prog"]);
3906 $gpg_key = $config["GnuPG"]["gpg_key"];
3907
3908 @exec($gpg_prog." --batch --yes --delete-key '$gpg_key'");
3909 } else {
3910 putenv("PGPPATH=".$config["PGP"]["pgp_home_dir"]);
3911 putenv("PGPHOME=".$config["PGP"]["pgp_home_dir"]);
3912
3913 $pgp_prog = func_shellquote($config["PGP"]["pgp_prog"]);
3914 $pgp_key = $config["PGP"]["pgp_key"];
3915
3916 if ($config["PGP"]["use_pgp6"] == "Y") {
3917 @exec($pgp_prog." -kr +force +batchmode '$pgp_key'");
3918 } else {
3919 @exec($pgp_prog." -kr +force '$pgp_key'");
3920 }
3921 }
3922}
3923
3924function func_pgp_add_key() {
3925 global $config;
3926
3927 if(!$config['Security']['crypt_method']) {
3928 return false;
3929 }
3930
3931 if($config['Security']['crypt_method'] == 'G') {
3932 putenv("GNUPGHOME=".$config["GnuPG"]["gpg_home_dir"]);
3933
3934 $gpg_prog = func_shellquote($config["GnuPG"]["gpg_prog"]);
3935 $gpg_key = $config["GnuPG"]["gpg_key"];
3936
3937 $fn = func_temp_store($config["GnuPG"]["gpg_public_key"]);
3938 chmod($fn, 0666);
3939
3940 @exec($gpg_prog.' --batch --yes --import '.func_shellquote($fn));
3941 } else {
3942 putenv("PGPPATH=".$config["PGP"]["pgp_home_dir"]);
3943 putenv("PGPHOME=".$config["PGP"]["pgp_home_dir"]);
3944
3945 $fn = func_temp_store( $config["PGP"]["pgp_public_key"]);
3946
3947 $pgp_prog = func_shellquote($config["PGP"]["pgp_prog"]);
3948 $pgp_key = $config["PGP"]["pgp_key"];
3949
3950 $ftmp = func_temp_store('');
3951 if ($config["PGP"]["use_pgp6"] == "Y") {
3952 @exec($pgp_prog.' +batchmode -ka '.func_shellquote($fn).' 2> '.func_shellquote($ftmp));
3953 @exec($pgp_prog.' +batchmode -ks "'.$pgp_key.'"');
3954 } else {
3955 @exec($pgp_prog.' -ka +force +batchmode '.func_shellquote($fn).' 2> '.func_shellquote($ftmp));
3956 @exec($pgp_prog.' +batchmode -ks "'.$pgp_key.'"');
3957 }
3958 unlink($ftmp);
3959 }
3960 unlink($fn);
3961}
3962
3963function func_update_pgp() {
3964 global $config;
3965
3966 func_pgp_remove_key();
3967 func_pgp_add_key();
3968}
3969
3970#
3971# Get value of language variable by its name and usertype
3972#
3973function func_get_langvar_by_name($lang_name, $replace_to=NULL, $force_code = '') {
3974 global $sql_tbl, $current_area, $config, $shop_language;
3975 global $smarty, $user_agent;
3976 global $predefined_lng_variables;
3977
3978 $language_code = $shop_language;
3979
3980 if(!empty($force_code))
3981 $language_code = $force_code;
3982
3983 $result = func_query_first_cell("SELECT value FROM $sql_tbl[languages] WHERE code='$language_code' AND name='$lang_name'");
3984 if(empty($result)) {
3985 $language_code = ($current_area == "C" ? $config["default_customer_language"] : $config["default_admin_language"]);
3986 $result = func_query_first_cell("SELECT value FROM $sql_tbl[languages] WHERE code='$language_code' AND name='$lang_name'");
3987 if(empty($result))
3988 $result = func_query_first_cell("SELECT value FROM $sql_tbl[languages] WHERE code='US' AND name='$lang_name'");
3989 }
3990
3991 $predefined_lng_variables[] = $lang_name;
3992
3993 if (is_array($replace_to))
3994 foreach ($replace_to as $k=>$v)
3995 $result = str_replace("{{".$k."}}", $v, $result);
3996 if ($smarty->webmaster_mode)
3997 $result = func_webmaster_label($user_agent, $lang_name, $result);
3998
3999 return $result;
4000}
4001
4002function func_parse_cookie_array(&$http_header, $cookies) {
4003 $deleted = array();
4004 $valid = array();
4005 foreach ($cookies as $line) {
4006 if (preg_match_all('!^\s*([^\n\r=]+)=([^\r\n; ]+)?!S', $line, $m)) {
4007 if (!empty($m[1]) && is_array($m[1])) {
4008 foreach ($m[1] as $k=>$v) {
4009 if ($m[2][$k] == 'deleted') {
4010 $deleted[$v] = true;
4011 if (isset($valid[$v])) unset($valid[$v]);
4012 }
4013 else {
4014 $valid[$v] = $m[2][$k];
4015 if (isset($deleted[$v])) unset($deleted[$v]);
4016 }
4017 }
4018 }
4019 }
4020 }
4021
4022 $http_header['cookies_deleted'] = $deleted;
4023 $http_header['cookies'] = $valid;
4024}
4025
4026function func_http_get_request($host, $post_url, $post_str, $post_cookies=array()) {
4027 $hp = explode(':',$host);
4028
4029 $cookie = "";
4030
4031 $result = "";
4032 $header_passed = false;
4033
4034 if( !isset($hp[1]) || !is_numeric($hp[1]) ) $hp[1] = 80;
4035 $host = implode(':', $hp);
4036
4037 $fp = fsockopen($hp[0], $hp[1], $errno, $errstr, 30);
4038 if (!$fp) {
4039 return array ("", "");
4040 } else {
4041 fputs ($fp, "GET $post_url?$post_str HTTP/1.0\r\n");
4042 fputs ($fp, "Host: $host\r\n");
4043 fputs ($fp, "User-Agent: Mozilla/4.5 [en]\r\n");
4044 if (!empty($post_cookies))
4045 fputs ($fp, "Cookie: ".join('; ',$post_cookies)."\r\n");
4046 fputs ($fp,"\r\n");
4047
4048 $http_header = array ();
4049 $http_header["ERROR"] = chop(fgets($fp,4096));
4050 $cookies = array ();
4051
4052 while (!feof($fp)) {
4053 if (!$header_passed)
4054 $line = fgets($fp, 4096);
4055 else
4056 $result .= fread($fp, 65536);
4057
4058 if ($header_passed == false && ($line == "\n" || $line == "\r\n")) {
4059 $header_passed = true;
4060 continue;
4061 }
4062
4063 if ($header_passed == false) {
4064 $header_line = explode(": ", $line, 2);
4065 $header_line[0] = strtoupper($header_line[0]);
4066 $http_header[$header_line[0]] = chop($header_line[1]);
4067
4068 if ($header_line[0] == 'SET-COOKIE')
4069 array_push($cookies, chop($header_line[1]));
4070 }
4071 }
4072
4073 fclose($fp);
4074 }
4075
4076 func_parse_cookie_array($http_header, $cookies);
4077
4078 return array($http_header, $result);
4079}
4080
4081function func_http_post_request($host, $post_url, $post_str, $cook = "") {
4082 $hp = explode(':',$host);
4083
4084 $result = "";
4085 $header_passed = false;
4086
4087 if( !isset($hp[1]) || !is_numeric($hp[1]) ) $hp[1] = 80;
4088 $host = implode(':', $hp);
4089
4090 $fp = fsockopen($hp[0], $hp[1], $errno, $errstr, 30);
4091 if (!$fp) {
4092 #die("Cant connect ($errno)<br>\n");
4093 return array ("", "");
4094 } else {
4095 #fputs ($fp, "POST $post_url HTTP/1.0\r\n");
4096 fputs($fp, "POST http://$host$post_url HTTP/1.0\r\n");
4097 fputs($fp, "Host: $host\r\n");
4098
4099 if (!empty($cook))
4100 fputs($fp, "Cookie: ".$cook."\r\n");
4101
4102 fputs($fp, "User-Agent: Mozilla/4.5 [en]\r\n");
4103 fputs($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
4104 fputs($fp, "Content-Length: ".strlen($post_str)."\r\n");
4105 fputs($fp, "\r\n");
4106 fputs($fp, $post_str."\r\n\r\n");
4107
4108 $http_header = array();
4109 $http_header["ERROR"] = chop(fgets($fp,4096));
4110
4111 $cookies = array();
4112 while (!feof($fp)) {
4113 $line = fgets($fp,4096);
4114
4115 if ($header_passed == false && ($line == "\n" || $line == "\r\n")) {
4116 $header_passed = true;
4117 continue;
4118 }
4119
4120 if ($header_passed == false) {
4121 $header_line = explode(": ", $line, 2);
4122 $header_line[0] = strtoupper($header_line[0]);
4123 $http_header[$header_line[0]] = chop($header_line[1]);
4124
4125 if ($header_line[0] == 'SET-COOKIE')
4126 array_push($cookies, chop($header_line[1]));
4127 continue;
4128 }
4129 $result .= $line;
4130 }
4131
4132 fclose ($fp);
4133 }
4134
4135 func_parse_cookie_array($http_header, $cookies);
4136
4137 return array($http_header, $result, $cookies);
4138}
4139
4140#
4141# This function compare file extension with disallowed extensions list
4142#
4143function func_is_allowed_file($file) {
4144 global $config;
4145 $disallowed_file_extensions = split('[ ,]+',$config["Security"]["disallowed_file_exts"]);
4146 $disallowed_file_extensions = func_array_map('strtolower', $disallowed_file_extensions);
4147 $disallowed_file_extensions = array_flip($disallowed_file_extensions);
4148 unset($disallowed_file_extensions[""]);
4149 $info = pathinfo($file);
4150 return !isset($disallowed_file_extensions[strtolower($info["extension"])]);
4151}
4152
4153#
4154# Checking that posted image is exist
4155#
4156function func_check_image_posted($file_upload_data, $type) {
4157
4158 global $config;
4159
4160 $return = false;
4161
4162 if ($file_upload_data["imtype"] != $type)
4163 return false;
4164
4165 if (!func_allow_file($file_upload_data["file_path"], true))
4166 return false;
4167
4168 if ($file_upload_data["source"] == "U") {
4169 if ($fd = func_fopen($file_upload_data["file_path"], "rb", true)) {
4170 fclose($fd);
4171 $return = true;
4172 }
4173 }
4174 else
4175 $return = file_exists($file_upload_data["file_path"]);
4176
4177 if ($return) {
4178 switch ($file_upload_data["imtype"]) {
4179 case "C":
4180 $return = ($file_upload_data["file_size"] <= $config["Images"]["icons_size_limit"] || $config["Images"]["icons_size_limit"]=="0");
4181 break;
4182 case "T":
4183 $return = ($file_upload_data["file_size"] <= $config["Images"]["thumbnails_size_limit"] || $config["Images"]["thumbnails_size_limit"]=="0");
4184 break;
4185 case "D":
4186 $return = ($file_upload_data["file_size"] <= $config["Images"]["det_images_size_limit"] || $config["Images"]["det_images_size_limit"]=="0");
4187 break;
4188 case "W":
4189 $return = ($file_upload_data["file_size"] <= $config["Images"]["pcicons_size_limit"] || $config["Images"]["pcicons_size_limit"]=="0");
4190 }
4191 }
4192 return $return;
4193}
4194
4195
4196function createThumbnail($srcPath,$dstPath,$max_width,$max_height,$fileType){
4197 $size = GetImageSize($srcPath);
4198 $width = $size[0];
4199 $height = $size[1];
4200
4201 $x_ratio = $max_width / $width;
4202 $y_ratio = $max_height / $height;
4203
4204 if ( ($width <= $max_width) && ($height <= $max_height) ) {
4205 $tn_width = $width;
4206 $tn_height = $height;
4207 }
4208 else if (($x_ratio * $height) < $max_height) {
4209 $tn_height = ceil($x_ratio * $height);
4210 $tn_width = $max_width;
4211 }
4212 else {
4213 $tn_width = ceil($y_ratio * $width);
4214 $tn_height = $max_height;
4215 }
4216 if($fileType=="image/jpeg" || $fileType=="image/pjpeg"){
4217 if($width >= $max_width || $height >= $max_height){
4218 $srcImg = imagecreatefromjpeg($srcPath);
4219 $dstImg = imagecreatetruecolor($tn_width,$tn_height);
4220 imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $tn_width,$tn_height,$width,$height);
4221 imagejpeg($dstImg, $dstPath);
4222 imagedestroy($dstImg);
4223 imagedestroy($srcImg);
4224 }else{
4225 # image is already smaller than max size so just copy it to the specified path
4226 copy($srcPath,$dstPath);
4227 }
4228 }elseif($fileType=="image/gif"){
4229 if($width >= $max_width || $height >= $max_height){
4230 $srcImg = imagecreatefromgif($srcPath);
4231 $dstImg = imagecreate($tn_width,$tn_height);
4232 imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $tn_width,$tn_height,$width,$height);
4233 imagegif($dstImg, $dstPath);
4234 imagedestroy($dstImg);
4235 imagedestroy($srcImg);
4236 }else{
4237 # image is already smaller than max size so just copy it to the specified path
4238 copy($srcPath,$dstPath);
4239 }
4240 }elseif($fileType=="image/png"){
4241 if($width >= $max_width || $height >= $max_height){
4242 $srcImg = imagecreatefrompng($srcPath);
4243 $dstImg = imagecreatetruecolor($tn_width,$tn_height);
4244 imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $tn_width,$tn_height,$width,$height);
4245 imagepng($dstImg, $dstPath);
4246 imagedestroy($dstImg);
4247 imagedestroy($srcImg);
4248 }else{
4249 # image is already smaller than max size so just copy it to the specified path
4250 copy($srcPath,$dstPath);
4251 }
4252 }
4253
4254}
4255
4256
4257#
4258# Get image content function
4259#
4260function func_get_image_content($file_upload_data, $id) {
4261
4262 global $config, $active_modules;
4263
4264 $file_aliases_count_max = 99;
4265
4266 switch($file_upload_data["imtype"]) {
4267 case "P":
4268 $config_data["location"] = "/var/www/shop/panel_images/";
4269 break;
4270 case "C":
4271 $config_data["location"] = $config["Images"]["icons_location"];
4272 break;
4273 case "W":
4274 $config_data["location"] = $config["Images"]["pcicons_location"];
4275 break;
4276 case "T":
4277 $config_data["location"] = $config["Images"]["thumbnails_location"];
4278 break;
4279 case "D":
4280 $config_data["location"] = $config["Images"]["det_images_location"];
4281 break;
4282 case "F":
4283 if(empty($active_modules['Feature_Comparison']))
4284 return false;
4285 $config_data["location"] = $config["Images"]["feature_images_location"];
4286 break;
4287 default:
4288 return false;
4289 }
4290
4291 if ($file_upload_data["source"] == "U")
4292 $file_path = $file_upload_data["file_path"];
4293 else
4294 $file_path = func_realpath($file_upload_data["file_path"]);
4295
4296 if ($fd = func_fopen($file_path, "rb", true)) {
4297
4298 if ($config_data["location"] == "FS") {
4299#
4300# ...else image is path to file
4301#
4302 $image = $file_path;
4303 }
4304 else
4305 {
4306#
4307# If image should be stored in the database, get image content from file
4308#
4309 if ($file_upload_data["source"] == "U") {
4310 $image = "";
4311 do {
4312 $tmpdata = fread($fd, 8192);
4313 if (strlen($tmpdata) == 0) break;
4314 $image .= $tmpdata;
4315 } while(true);
4316 }
4317 else
4318 $image = fread($fd, filesize($file_path));
4319
4320 $image = addslashes($image);
4321 }
4322 fclose($fd);
4323
4324 if ($file_upload_data["source"] == "L" && !empty($file_upload_data["dir_upload"])) {
4325
4326 if ($config_data["location"] == "FS") {
4327#
4328# For FS storing. If image has been uploaded, move it to specified directory
4329#
4330 $file_name = ($file_upload_data["imtype"]=="W"?"w_$id":($file_upload_data["imtype"]=="C"?"c_$id":($file_upload_data["imtype"]=="T"?"t_$id":"d_$id")));
4331 $file_type = (strstr($file_path,"gif")?"gif":(strstr($file_path,"png")?"png":"jpg"));
4332
4333#
4334# Check the existing file
4335#
4336
4337# SPM removed file name counter feature
4338
4339 //$counter = 1;
4340 //$file_name_tmp = $file_name;
4341
4342 //while (file_exists($file_upload_data["dir_upload"].DIRECTORY_SEPARATOR.$file_name_tmp.".".$file_type) && $counter<$file_aliases_count_max) {
4343 // $file_name_tmp = $file_name."_".sprintf("%02d", $counter);
4344 // $counter++;
4345 //}
4346 //$file_name = $file_name_tmp;
4347
4348 $image = $file_upload_data["dir_upload"].DIRECTORY_SEPARATOR.$file_name.".".$file_type;
4349 copy($file_path, $image);
4350 @chmod($image, 0666);
4351 }
4352#
4353# Delete temporary file
4354#
4355 @unlink($file_path);
4356 }
4357
4358 }
4359
4360 if($file_upload_data["imtype"] == 'D') {
4361 if($config_data["location"] == "FS") {
4362 $fp = fopen($image, "rb");
4363 if($fp) {
4364 $i = "";
4365 $s = "";
4366 while($s = fread($fp, 8192)) {
4367 $i .= $s;
4368 }
4369 $md5 = md5($i);
4370 fclose($fp);
4371 }
4372 } else
4373 $md5 = md5($image);
4374 }
4375
4376 return array("image"=>$image, "image_type"=>$file_upload_data["image_type"], "image_x"=>$file_upload_data["image_x"], "image_y"=>$file_upload_data["image_y"], "file_size"=>$file_upload_data["file_size"], "md5" => $md5);
4377}
4378
4379function func_weight_in_grams($weight) {
4380 global $config;
4381 return $weight*$config["General"]["weight_symbol_grams"];
4382}
4383
4384#
4385# This module generates download key which is sent to customer
4386# and inserts this key into database
4387#
4388function keygen($productid, $key_TTL, $itemid) {
4389 global $sql_tbl;
4390 $key = md5(uniqid(rand()));
4391 $expires = time() + $key_TTL*3600;
4392 db_query("REPLACE INTO $sql_tbl[download_keys] (download_key, expires, productid, itemid) VALUES('$key', '$expires', '$productid', '$itemid')");
4393 return $key;
4394}
4395
4396#
4397# Flush output
4398#
4399function func_flush() {
4400 if (preg_match("/Apache(.*)Win/", getenv("SERVER_SOFTWARE")))
4401 echo str_repeat(" ", 2500);
4402 elseif (preg_match("/(.*)MSIE(.*)\)$/", getenv("HTTP_USER_AGENT")))
4403 echo str_repeat(" ", 256);
4404 ob_end_flush();
4405 flush();
4406}
4407
4408#
4409# For testing purpose: outputs contents of requested variables
4410# example:
4411# func_print_r($categories,$cart,$userinfo,$GLOBALS);
4412#
4413function func_print_r() {
4414 static $count = 0;
4415 $args = func_get_args();
4416 if (!empty($args)) {
4417 ?><DIV align=LEFT><PRE><FONT><?php
4418 foreach($args as $index=>$variable_content){
4419 ?><B>Debug [<?php echo $index."/".$count;?>]:</B> <?php
4420 ob_start();
4421 print_r($variable_content);
4422 $data = ob_get_contents(); ob_end_clean();
4423 echo htmlspecialchars($data);
4424 echo "\n";
4425 }
4426 ?></FONT></PRE></DIV><?php
4427 }
4428 $count++;
4429}
4430
4431#
4432# For testing purpose: outputs contents of requested global variables
4433# example:
4434# global $categories, $cart, $userinfo;
4435# func_print_d("categories","cart","userinfo","GLOBALS");
4436#
4437function func_print_d() {
4438 $varnames = func_get_args();
4439 ?><DIV align=LEFT><PRE><FONT><?php
4440 if (!empty($varnames)) {
4441 foreach($varnames as $variable_name){
4442 if( !is_string($variable_name) || empty($variable_name) ){
4443 ?><B>Debug notice:</B> try to use func_print_d("varname1","varname2") instead of func_print_d($varname1,$varname2); <?php
4444 }
4445 else {
4446 echo "<B>$variable_name</B> = ";
4447 ob_start();
4448 if ($variable_name == 'GLOBALS')
4449 print_r($GLOBALS);
4450 else {
4451 if (!@isset($GLOBALS[$variable_name])) {
4452 echo "is unset!";
4453 }
4454 else
4455 print_r($GLOBALS[$variable_name]);
4456 }
4457 $data = ob_get_contents(); ob_end_clean();
4458 echo htmlspecialchars($data);
4459 }
4460 echo "\n";
4461 }
4462 }
4463 else {
4464 ?><B>Debug notice:</B> try to use func_print_d("varname1","varname2") instead of func_print_d($varname1,$varname2); <?php
4465 }
4466 ?></FONT></PRE></DIV><?php
4467}
4468
4469#
4470# Emulator for the is_executable function if it doesn't exists (f.e. under windows)
4471#
4472function func_is_executable($file) {
4473 if( function_exists("is_executable") ) return @is_executable($file);
4474 return @is_readable($file);
4475}
4476
4477#
4478# Executable lookup
4479# Check prefered file first, then do search in PATH environment variable.
4480# Will return false if no executable is found.
4481#
4482function func_find_executable($filename, $prefered_file = false)
4483{
4484 global $xcart_dir;
4485
4486 if (ini_get("open_basedir") != "" && !empty($prefered_file))
4487 return $prefered_file;
4488
4489 $path_sep = X_DEF_OS_WINDOWS ? ';' : ':';
4490
4491 if ($prefered_file) {
4492 if (!X_DEF_OS_WINDOWS && func_is_executable($prefered_file)) return $prefered_file;
4493 if (X_DEF_OS_WINDOWS) {
4494 $info = pathinfo($prefered_file);
4495 if (empty($info["extension"])) $prefered_file .= ".exe";
4496 if (func_is_executable($prefered_file)) return $prefered_file;
4497 }
4498 }
4499
4500 $directories = split($path_sep, getenv("PATH"));
4501 array_unshift($directories, $xcart_dir.DIRECTORY_SEPARATOR."payment");
4502
4503 foreach($directories as $dir){
4504 $file = $dir.DIRECTORY_SEPARATOR.$filename;
4505 if (!X_DEF_OS_WINDOWS && func_is_executable($file) ) return $file;
4506 if (X_DEF_OS_WINDOWS && func_is_executable($file.".exe") ) return $file.".exe";
4507 }
4508 return false;
4509}
4510
4511#
4512# Get thumbnail URL (if images are stored on the FS only)
4513#
4514function func_get_thumbnail_url($productid) {
4515 global $config, $sql_tbl, $xcart_dir, $current_location;
4516
4517 if ($config["Images"]["thumbnails_location"] == "FS") {
4518#
4519# Thumbnail data
4520#
4521 $thumbnail_info = func_query_first("SELECT image_path, image_type FROM $sql_tbl[thumbnails] WHERE productid='$productid'");
4522 if (eregi("^(http|ftp)://", $thumbnail_info["image_path"]))
4523 # image_path is an URL
4524 return $thumbnail_info["image_path"];
4525 elseif (!strncmp($xcart_dir, $thumbnail_info["image_path"], strlen($xcart_dir))) {
4526 # image_path is an locally placed image
4527 $url = $current_location.str_replace("\\", "/", substr($thumbnail_info["image_path"], strlen($xcart_dir)));
4528 return $url;
4529 }
4530 }
4531 return false;
4532
4533}
4534
4535#
4536# This function removes orders and related info from the database
4537# $orders can be: 1) orderid; 2) orders array with orderid keys
4538function func_delete_order($orders) {
4539 global $sql_tbl, $xcart_dir;
4540
4541 $_orders = array();
4542
4543 if (is_array($orders)) {
4544 foreach($orders as $order)
4545 if (!empty($order["orderid"]))
4546 $_orders[] = $order["orderid"];
4547 }
4548 elseif (is_numeric($orders))
4549 $_orders[] = $orders;
4550
4551#
4552# Update quantity of products
4553#
4554 foreach($_orders as $orderid) {
4555 $order_data = func_order_data($orderid);
4556 if (strpos("IQ",$order_data["order"]["status"]) !== false) {
4557 func_update_quantity($order_data["products"]);
4558 }
4559 }
4560
4561#
4562# Delete orders from the database
4563#
4564 $xaff = (func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[modules] WHERE module_name='XAffiliate'") > 0);
4565 $xrma = (func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[modules] WHERE module_name='RMA'") > 0);
4566 if($xaff && !isset($sql_tbl['partner_payment'])) {
4567 @include_once $xcart_dir."/modules/XAffiliate/config.php";
4568 }
4569 if($xrma && !isset($sql_tbl['returns'])) {
4570 @include_once $xcart_dir."/modules/RMA/config.php";
4571 }
4572 db_query("LOCK TABLES $sql_tbl[orders] WRITE, $sql_tbl[order_details] WRITE, $sql_tbl[order_extras] WRITE, $sql_tbl[giftcerts] WRITE, $sql_tbl[subscription_customers] WRITE".(@$xaff?", $sql_tbl[partner_payment] WRITE, $sql_tbl[partner_product_commissions] WRITE, $sql_tbl[partner_adv_orders] WRITE":"").(@$xrma?", $sql_tbl[returns] WRITE":""));
4573
4574 foreach($_orders as $orderid) {
4575 $itemids = func_query("SELECT itemid FROM $sql_tbl[order_details] WHERE orderid='$orderid'");
4576 if(!empty($itemids)) {
4577 foreach($itemids as $k => $v) {
4578 $itemids[$k] = $v['itemid'];
4579 }
4580 }
4581 db_query("DELETE FROM $sql_tbl[orders] WHERE orderid='$orderid'");
4582 db_query("DELETE FROM $sql_tbl[order_details] WHERE orderid='$orderid'");
4583 db_query("DELETE FROM $sql_tbl[order_extras] WHERE orderid='$orderid'");
4584 db_query("DELETE FROM $sql_tbl[giftcerts] WHERE orderid='$orderid'");
4585 if (@$xaff) {
4586 db_query("DELETE FROM $sql_tbl[partner_payment] WHERE orderid='$orderid'");
4587 db_query("DELETE FROM $sql_tbl[partner_product_commissions] WHERE orderid='$orderid'");
4588 db_query("DELETE FROM $sql_tbl[partner_adv_orders] WHERE orderid='$orderid'");
4589 }
4590 if (@$xrma && !empty($itemids)) {
4591 db_query("DELETE FROM $sql_tbl[returns] WHERE itemid IN ('".implode("','", $itemids)."')");
4592 }
4593 db_query("DELETE FROM $sql_tbl[subscription_customers] WHERE orderid='$orderid'");
4594 }
4595#
4596# Check if no orders in the database
4597#
4598 $total_orders = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[orders]");
4599 if ($total_orders == 0) {
4600#
4601# Clear Order ID counter (auto increment field in the xcart_orders table)
4602#
4603 db_query("DELETE FROM $sql_tbl[orders]");
4604 db_query("DELETE FROM $sql_tbl[order_details]");
4605 if (@$xaff)
4606 db_query("DELETE FROM $sql_tbl[partner_payment]");
4607 db_query("DELETE FROM $sql_tbl[subscription_customers]");
4608
4609 }
4610 db_query("UNLOCK TABLES");
4611}
4612
4613#
4614# Get information about directory:
4615# - how many files does directory contain
4616# - what size does directory have
4617#
4618function func_get_dir_status( $directory ) {
4619 $result = array("files"=>0, "size"=>0);
4620 $dp = opendir ($directory);
4621 while ($file = readdir ($dp)) {
4622 if( $file == "." || $file == ".." ) continue;
4623 $path = $directory.DIRECTORY_SEPARATOR.$file;
4624
4625 if( is_file( $path ) ) {
4626 $result["files"] ++;
4627 $result["size"] += filesize($path);
4628 }
4629 else {
4630 $temp = func_get_dir_status($path);
4631 $result["files"] += $temp["files"];
4632 $result["size"] += $temp["size"];
4633 }
4634 }
4635 closedir($dp);
4636
4637 return $result;
4638}
4639
4640#
4641# This function added the ability to redirect a user to another page using HTML meta tags
4642# (without using header() function or Javascript)
4643#
4644function func_html_location($url, $time=3) {
4645 x_session_save();
4646 echo "<BR><BR>".func_get_langvar_by_name("txt_header_location_note", array("time" => $time, "location" => $url));
4647 echo "<META http-equiv=\"Refresh\" content=\"$time;URL=$url\">";
4648 func_flush();
4649 exit;
4650}
4651
4652#
4653# This function generates the unique cartid number
4654#
4655function func_generate_cartid($cart_products) {
4656 global $cart;
4657
4658 if (empty($cart["max_cartid"]))
4659 $cart["max_cartid"] = 0;
4660
4661 $cart["max_cartid"]++;
4662 return $cart["max_cartid"];
4663}
4664
4665
4666#
4667# This function determine the files location for current user
4668#
4669function func_get_files_location () {
4670 global $login, $current_area, $active_modules, $single_mode, $files_dir_name;
4671
4672 if ($single_mode || $current_area=="A" || ($active_modules["Simple_Mode"] && $current_area=="P"))
4673 return $files_dir_name;
4674
4675 return $files_dir_name.DIRECTORY_SEPARATOR.$login;
4676}
4677
4678#
4679# This function updates/inserts the language variable into 'languages_alt'
4680#
4681function func_languages_alt_insert($name, $value, $code="") {
4682 global $sql_tbl, $all_languages;
4683
4684 $result = true;
4685
4686 if (is_array($all_languages)) {
4687 if (empty($code)) {
4688 #
4689 # For empty code update/insert variables for all languages
4690 #
4691 foreach($all_languages as $k=>$v) {
4692 if (func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[languages_alt] WHERE code='$v[code]' AND name='$name'") == 0)
4693 db_query("INSERT INTO $sql_tbl[languages_alt] (code,name,value) VALUES ('$v[code]', '$name', '$value')");
4694 else
4695 db_query("UPDATE $sql_tbl[languages_alt] SET value='$value' WHERE code='$v[code]' AND name='$name'");
4696 }
4697 }
4698 else {
4699 #
4700 # For not empty $code...
4701 #
4702 $result = false;
4703 #
4704 # Check if $code is valid
4705 #
4706 foreach($all_languages as $k=>$v) {
4707 if ($code == $v["code"]) {
4708 $result = true;
4709 break;
4710 }
4711 }
4712 if (!$result)
4713 return false;
4714 #
4715 # Update/insert variable for $code
4716 #
4717 if (func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[languages_alt] WHERE code='$code' AND name='$name'") == 0)
4718 db_query("INSERT INTO $sql_tbl[languages_alt] (code,name,value) VALUES ('$code', '$name', '$value')");
4719 else
4720 db_query("UPDATE $sql_tbl[languages_alt] SET value='$value' WHERE code='$code' AND name='$name'");
4721 }
4722 }
4723 else
4724 $result = false;
4725
4726 return $result;
4727}
4728
4729#
4730# This function returns the language variable value by name and language code
4731#
4732function func_get_languages_alt($name, $lng_code) {
4733 global $sql_tbl;
4734 return func_query_first_cell("SELECT value FROM $sql_tbl[languages_alt] WHERE code='$lng_code' AND name='$name'");
4735}
4736
4737#
4738# This function creates a temporary file and store some data in it
4739# It will return filename if successful and "false" if it fails.
4740#
4741function func_temp_store($data) {
4742 global $file_temp_dir;
4743 $tmpfile = @tempnam($file_temp_dir,"xctmp");
4744 if (empty($tmpfile)) return false;
4745
4746 $fp = @fopen($tmpfile,"w");
4747 if (!$fp) {
4748 @unlink($tmpfile);
4749 return false;
4750 }
4751
4752 fwrite($fp,$data);
4753 fclose($fp);
4754
4755 return $tmpfile;
4756}
4757
4758#
4759# This function validate accordance a county ID to a state and country code
4760#
4761function func_check_county($countyid, $statecode, $countrycode) {
4762 global $sql_tbl;
4763
4764 $return = true;
4765 if (is_numeric($countyid)) {
4766 if(func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[states] WHERE code='$statecode' AND country_code='$countrycode'") > 0) {
4767 $return = (func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[counties], $sql_tbl[states] WHERE $sql_tbl[counties].stateid=$sql_tbl[states].stateid AND $sql_tbl[counties].countyid='$countyid' AND $sql_tbl[states].code='$statecode' AND $sql_tbl[states].country_code='$countrycode'") == 1);
4768 }
4769 }
4770
4771 return $return;
4772}
4773
4774#
4775# This function validate accordance a state code to a country code
4776#
4777function func_check_state($states, $statecode, $countrycode) {
4778 $country_flag = $state_flag = $state_flag2 = false;
4779 $return = true;
4780 foreach ($states as $val) {
4781 if ($val["country_code"] == $countrycode) {
4782 $country_flag = true;
4783 if ($val["state_code"] == $statecode)
4784 $state_flag = true;
4785 }
4786 if ($val["state_code"] == $statecode)
4787 $state_flag2 = true;
4788 }
4789
4790 if (($country_flag && !$state_flag) ||(!$country_flag && $state_flag2))
4791 $return = false;
4792
4793 return $return;
4794}
4795
4796#
4797# This function quotes arguments for shell command according
4798# to the host operation system
4799#
4800function func_shellquote() {
4801 static $win_s = '!([\t \&\<\>\?]+)!S';
4802 static $win_r = '"\\1"';
4803 $result = "";
4804 $args = func_get_args();
4805 foreach ($args as $idx=>$arg)
4806 $args[$idx] = X_DEF_OS_WINDOWS ? (preg_replace($win_s,$win_r,$arg)) : (escapeshellarg($arg));
4807
4808 return implode(' ', $args);
4809}
4810
4811#
4812# realpath() wrapper
4813#
4814function func_realpath($path) {
4815 if (empty($path)) return false;
4816
4817 $path = preg_replace("/[\\\\\/]+/S",DIRECTORY_SEPARATOR,$path);
4818
4819 $dir = dirname($path); if ($dir != "\\") $dir .= DIRECTORY_SEPARATOR;
4820 $dir = realpath($dir);
4821
4822 if (empty($dir) || $dir[strlen($dir)-1] != DIRECTORY_SEPARATOR) $dir .= DIRECTORY_SEPARATOR;
4823 $path = $dir.basename($path);
4824
4825 return $path;
4826}
4827
4828#
4829# This function decide to allow/deny to use path for files
4830# Returns: full path for the file if path is allowed,
4831# 'false', if path is not allowed to use.
4832#
4833function func_allowed_path($allowed_path, $path) {
4834 if (empty($allowed_path) || empty($path)) return false;
4835
4836 if (X_DEF_OS_WINDOWS) {
4837 $allowed_path = strtolower($allowed_path);
4838 $path = strtolower($path);
4839 }
4840
4841 $allowed_path = func_realpath($allowed_path);
4842 if (empty($allowed_path)) return false;
4843
4844 # absolute path
4845 if ( (X_DEF_OS_WINDOWS && preg_match("/^(\\\\)|(\w:)/S",$path)) || !X_DEF_OS_WINDOWS && $path[0] == '/') {
4846 $path = func_realpath($path);
4847 }
4848 else {
4849 $path = func_realpath($allowed_path.DIRECTORY_SEPARATOR.$path);
4850 }
4851
4852 if ($allowed_path == $path) return $allowed_path;
4853
4854 if ($allowed_path[strlen($allowed_path)-1] != DIRECTORY_SEPARATOR)
4855 $allowed_path .= DIRECTORY_SEPARATOR;
4856
4857 if (!strncmp($path, $allowed_path, strlen($allowed_path)))
4858 return $path;
4859
4860 return false;
4861}
4862
4863function func_check_webinput($check_php=1)
4864{
4865 global $config,$sql_tbl,$HTTP_SERVER_VARS;
4866
4867 $php = $HTTP_SERVER_VARS["PHP_SELF"];
4868 $allow_php = array();
4869 $list = func_query("select c.processor from $sql_tbl[ccprocessors] as c, $sql_tbl[payment_methods] as m where m.active='Y' and m.paymentid=c.paymentid and c.background!='Y'");
4870 if($list)
4871 foreach($list as $a)
4872 switch(array_pop($a))
4873 {
4874 case "cc_epdq.php":
4875 $allow_php[] = "cc_epdq_result.php"; break;
4876 case "cc_smartpag.php":
4877 $allow_php[] = "cc_smartpag_final.php"; break;
4878 case "cc_payzip.php":
4879 $allow_php[] = "cc_payzip_result.php"; break;
4880 case "cc_verisignl.php":
4881 $allow_php[] = "cc_verisignl_result.php"; break;
4882 case "cc_hsbc.php":
4883 $allow_php[] = "cc_hsbc_result.php"; break;
4884 case "cc_ogoneweb.php":
4885 $allow_php[] = "cc_ogoneweb_result.php"; break;
4886 case "cc_pswbill.php":
4887 $allow_php[] = "cc_pswbill_result.php"; break;
4888 case "cc_triple.php":
4889 $allow_php[] = "cc_triple_result.php"; break;
4890 case "cc_paybox.php":
4891 $allow_php[] = "cc_paybox_result.php"; break;
4892 case "cc_pp3.php":
4893 $allow_php[] = "ebank_ok.php";
4894 $allow_php[] = "ebank_nok.php"; break;
4895
4896 default: $allow_php[] = $a["processor"]; break;
4897 }
4898
4899 #$allow_php[] = "payment_cc.php";
4900
4901 $ip = $HTTP_SERVER_VARS["REMOTE_ADDR"];
4902 $allow_ip = $config["Security"]["allow_ips"];
4903
4904 $not_found=1;
4905 if($check_php && $allow_php)
4906 foreach($allow_php as $allow)
4907 if(preg_match("/".$allow."$/",$php))
4908 {$not_found=0;break;}
4909 if($not_found)
4910 { header("Location: ../"); die("Access denied"); }
4911
4912 if($allow_ip)
4913 {
4914 $not_found=1;
4915 $a = split(",",$allow_ip);
4916 foreach($a as $v)
4917 {
4918 list($aip,$amsk) = split("/",trim($v));
4919 $amsk = 4294967296 - ($amsk ? pow(2,(32-$amsk)) : 1);
4920
4921 if((ip2long($ip) & $amsk) == ip2long($aip))
4922 {$not_found=0;break;}
4923 }
4924 return ($not_found ? "err" : "pass");
4925 }
4926 else
4927 return "pass";
4928
4929}
4930
4931#
4932# This function recrypts data with the Blowfish method.
4933#
4934
4935function func_data_recrypt() {
4936 global $sql_tbl, $merchant_password, $current_area, $active_modules, $config;
4937
4938 if(!$merchant_password || !($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"])) || $config['Security']['blowfish_enabled'] != 'Y') {
4939 return false;
4940 }
4941 $orders = func_query("SELECT orderid, details FROM $sql_tbl[orders] WHERE details NOT LIKE 'B%'");
4942 if($orders) {
4943 $cnt = 0;
4944 set_time_limit(86400);
4945 foreach($orders as $order) {
4946 if(++$cnt / 100 == 0 && $cnt) {
4947 echo ".";
4948 if($cnt / 5000 == 0) {
4949 echo "<br>\n";
4950 }
4951 func_flush();
4952 }
4953 $details = text_decrypt($order['details']);
4954 $details = text_crypt($details, true);
4955 db_query("UPDATE $sql_tbl[orders] SET details = '".addslashes($details)."' WHERE orderid = '$order[orderid]'");
4956 }
4957 }
4958 return true;
4959}
4960
4961#
4962# This function decrypts data Blowfish method -> Standart method.
4963#
4964
4965function func_data_decrypt() {
4966 global $sql_tbl, $merchant_password, $current_area, $active_modules;
4967
4968 if(!$merchant_password || !($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"]))) {
4969 return false;
4970 }
4971 $orders = func_query("SELECT orderid, details FROM $sql_tbl[orders] WHERE details LIKE 'B%'");
4972 if($orders) {
4973 $cnt = 0;
4974 set_time_limit(86400);
4975 foreach($orders as $order) {
4976 if(++$cnt / 100 == 0 && $cnt) {
4977 echo ".";
4978 if($cnt / 5000 == 0) {
4979 echo "<BR>\n";
4980 }
4981 func_flush();
4982 }
4983 $details = text_decrypt($order['details']);
4984 $details = text_crypt($details);
4985 db_query("UPDATE $sql_tbl[orders] SET details = '".addslashes($details)."' WHERE orderid = '$order[orderid]'");
4986 }
4987 }
4988 return true;
4989}
4990
4991#
4992# This function recrypts Blowfish-crypted data with new password
4993# where:
4994# old_password - old Merchant password
4995
4996function func_change_mpassword_recrypt($old_password) {
4997 global $sql_tbl, $merchant_password, $current_area, $active_modules, $blowfish;
4998
4999 if(!$old_password || !$merchant_password || !($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"]))) {
5000 return false;
5001 }
5002
5003 $orders = func_query("SELECT orderid, details FROM $sql_tbl[orders] WHERE details LIKE 'B%'");
5004 if($orders) {
5005 $_merchant_password = $merchant_password;
5006 $cnt = 0;
5007 set_time_limit(86400);
5008 foreach($orders as $order) {
5009 if(++$cnt / 100 == 0 && $cnt) {
5010 echo ".";
5011 if($cnt / 5000 == 0) {
5012 echo "<BR>\n";
5013 }
5014 func_flush();
5015 }
5016 $merchant_password = $old_password;
5017 $details = text_decrypt($order['details']);
5018 $merchant_password = $_merchant_password;
5019 $details = text_crypt($details, true);
5020 db_query("UPDATE $sql_tbl[orders] SET details = '".addslashes($details)."' WHERE orderid = '$order[orderid]'");
5021 }
5022 $merchant_password = $_merchant_password;
5023 }
5024
5025 return true;
5026}
5027
5028#
5029# Java script redirect
5030#
5031
5032function func_js_redirect($location) {
5033 global $http_location;
5034 x_session_save();
5035 echo "<script>self.location='$location';</script>".func_get_langvar_by_name("txt_no_js_redirect_1")." ".$http_location."/".$location." ".func_get_langvar_by_name("txt_no_js_redirect_2")." <a href='$location'>".func_get_langvar_by_name("txt_no_js_redirect_3")."</a>";
5036 exit;
5037}
5038
5039#
5040# Get CRC32 as 4-symbols
5041#
5042
5043function func_crc32($str) {
5044 $int = crc32($str);
5045 return chr($int >> 24).chr(($int >> 16) & 0xff). chr(($int >> 8) & 0xff).chr($int & 0xff);
5046}
5047
5048#
5049# Insert array data to table
5050#
5051
5052function func_array2insert ($tbl, $arr, $is_replace = false) {
5053 global $sql_tbl;
5054 if($sql_tbl[$tbl])
5055 $tbl = $sql_tbl[$tbl];
5056 if(db_query(($is_replace?"REPLACE":"INSERT")." INTO $tbl (" . implode(", ", array_keys($arr)) . ") VALUES ('" . implode("', '", $arr) . "')")) {
5057 return db_insert_id();
5058 } else {
5059 return false;
5060 }
5061}
5062
5063#
5064# Update array data to table + where statament
5065#
5066function func_array2update ($tbl, $arr, $where = '') {
5067 global $sql_tbl;
5068 if($sql_tbl[$tbl])
5069 $tbl = $sql_tbl[$tbl];
5070 foreach($arr as $k => $v) {
5071 $r .= ($r ? ", " : "") . $k . "='" . $v . "'";
5072 }
5073 return db_query("UPDATE $tbl SET $r" . ($where ? " WHERE " . $where : ""));
5074}
5075
5076#
5077# Check filename for present in X-Cart directory
5078#
5079function func_allow_file($file, $is_root = false) {
5080 global $xcart_dir, $login, $single_mode, $current_area, $active_modules, $files_dir_name;
5081
5082 if (empty($file) || !func_is_allowed_file($file))
5083 return false;
5084
5085 $dir = $xcart_dir;
5086
5087 if (strncasecmp($file, "http://", 7) && strncasecmp($file, "ftp://", 6) && strncasecmp($file, "https://", 8)) {
5088 if (!$is_root) {
5089 if ($current_area=="A" || (($active_modules["Simple_Mode"] || $single_mode)&& $current_area=="P"))
5090 $dir = $files_dir_name;
5091 elseif ($current_area=="P" || $current_area == 'A')
5092 $dir = $files_dir_name.DIRECTORY_SEPARATOR.$login;
5093 else
5094 $dir = $files_dir_name;
5095 }
5096 $file = func_allowed_path($dir, $file);
5097 }
5098 return $file;
5099}
5100
5101#
5102# Get default field's name
5103#
5104function func_get_default_field($name) {
5105 $suffix = str_replace("name", "_name", preg_replace("/^(s_|b_)(.+)$/S", "\\2", $name));
5106 if ($suffix == "zipcode")
5107 $suffix = "zip_code";
5108 return func_get_langvar_by_name("lbl_".$suffix);
5109
5110}
5111#
5112# fopen() wrapper
5113#
5114function func_fopen($file, $perm = 'r', $is_root = false) {
5115 $file = func_allow_file($file, $is_root);
5116 if ($file === false)
5117 return false;
5118 return @fopen($file, $perm);
5119}
5120
5121#
5122# fopen + fread wrapper
5123#
5124function func_file_get($file, $is_root = false) {
5125 $fp = func_fopen($file, 'rb', $is_root);
5126
5127 if ($fp === false) return false;
5128
5129 while (strlen($str = fread($fp, 8192)) > 0 )
5130 $data .= $str;
5131
5132 fclose($fp);
5133 return $data;
5134}
5135
5136#
5137# readfile() wrapper
5138#
5139function func_readfile($file, $is_root = false) {
5140 $file = func_allow_file($file, $is_root);
5141 if ($file === false) return false;
5142 return readfile($file);
5143}
5144
5145#
5146# Get tmpfile content
5147#
5148function func_temp_read($tmpfile, $delete = false) {
5149 if (empty($tmpfile))
5150 return false;
5151
5152 $fp = @fopen($tmpfile,"rb");
5153 if(!$fp)
5154 return false;
5155
5156 while (strlen($str = fread($fp, 4096)) > 0 )
5157 $data .= $str;
5158 fclose($fp);
5159
5160 if ($delete) {
5161 @unlink($tmpfile);
5162 }
5163
5164 return $data;
5165}
5166
5167#
5168# move_uploaded_file() wrapper
5169#
5170function func_move_uploaded_file($file) {
5171 global $HTTP_POST_FILES, $file_temp_dir;
5172
5173 if(empty($file) || !isset($HTTP_POST_FILES[$file]))
5174 return false;
5175
5176 $path = func_allow_file(tempnam($file_temp_dir,preg_replace('/^.*[\/\\\]/S', '', $HTTP_POST_FILES[$file]['name'])), true);
5177 if ($path === false)
5178 return false;
5179
5180 if (move_uploaded_file($HTTP_POST_FILES[$file]['tmp_name'],$path))
5181 return $path;
5182
5183 chmod($path, 0644);
5184 return false;
5185}
5186
5187#
5188# file() wrapper
5189#
5190function func_file($file, $is_root = false) {
5191 $file = func_allow_file($file, $is_root);
5192 if ($file === false) return array();
5193
5194 return file($file);
5195}
5196
5197#
5198# This function checks if email is valid
5199#
5200function func_check_email($email) {
5201#
5202# Simplified checking
5203#
5204 $email_regular_expression = "^([-\d\w][-.\d\w]*)?[-\d\w]@([-!#\$%&*+\\/=?\w\d^_`{|}~]+\.)+[a-zA-Z]{2,6}$";
5205
5206#
5207# Full checking according to RFC 822
5208# Uncomment the line below to use it (change also check_email_script.tpl)
5209# $email_regular_expression = "^[^.]{1}([-!#\$%&'*+.\\/0-9=?A-Z^_`a-z{|}~])+[^.]{1}@([-!#\$%&'*+\\/0-9=?A-Z^_`a-z{|}~]+\\.)+[a-zA-Z]{2,6}$";
5210
5211 return preg_match("/".$email_regular_expression."/i", stripslashes($email));
5212}
5213
5214#
5215# Hash table for func_lock & func_unlock
5216#
5217function & func_lock_hash_tbl() {
5218 static $hash = array();
5219
5220 return $hash;
5221}
5222
5223#
5224# This function create file lock in temporaly directory
5225# It will return file descriptor, or false.
5226#
5227function func_lock($lockname) {
5228 global $file_temp_dir;
5229 if (empty($lockname)) return false;
5230
5231 $fname = $file_temp_dir.DIRECTORY_SEPARATOR.$lockname;
5232 $fp = fopen($fname, "w+");
5233 if (!$fp) return false;
5234
5235 $attempts = 3;
5236 while ($attempts > 0) {
5237 if (flock($fp, LOCK_EX)) {
5238 $hash =& func_lock_hash_tbl();
5239 $hash[$fp] = $fname;
5240 return $fp;
5241 }
5242 sleep(5);
5243 $attempts--;
5244 }
5245
5246 return false;
5247}
5248
5249#
5250# This function releases file lock which is previously created by func_lock
5251#
5252function func_unlock($fp) {
5253 global $file_temp_dir;
5254 $hash =& func_lock_hash_tbl();
5255
5256 if ($fp === false || empty($hash[$fp])) return false;
5257
5258 $fname = $hash[$fp];
5259 unset($hash[$fp]);
5260
5261 @fclose($fp);
5262 @unlink($fname);
5263
5264 return true;
5265}
5266
5267#
5268# Get additional register fields settings
5269#
5270function func_get_additional_fields($area = '', $user = '') {
5271 global $sql_tbl, $shop_language;
5272
5273 if($area)
5274 $fields = func_query("SELECT $sql_tbl[register_fields].*, IF($sql_tbl[register_fields].avail LIKE '%$area%', 'Y', '') as avail, IF($sql_tbl[register_fields].required LIKE '%$area%', 'Y', '') as required, $sql_tbl[register_field_values].value FROM $sql_tbl[register_fields] LEFT JOIN $sql_tbl[register_field_values] ON $sql_tbl[register_fields].fieldid = $sql_tbl[register_field_values].fieldid AND $sql_tbl[register_field_values].login = '$user' ORDER BY $sql_tbl[register_fields].section, $sql_tbl[register_fields].orderby");
5275 else
5276 $fields = func_query("SELECT * FROM $sql_tbl[register_fields] ORDER BY section, orderby");
5277 if($fields) {
5278 foreach($fields as $k => $v) {
5279 $fields[$k]['title'] = func_get_languages_alt("lbl_register_field_".$v['fieldid'], $shop_language);
5280 if(!$area) {
5281 $fields[$k]['avail'] = func_keys2hash($v['avail']);
5282 $fields[$k]['required'] = func_keys2hash($v['required']);
5283 } elseif($v['type'] == 'S' && $v['variants'])
5284 $fields[$k]['variants'] = @explode(";", $v['variants']);
5285 }
5286 }
5287 return $fields;
5288}
5289
5290#
5291# Get additional register fields settings
5292#
5293function func_get_add_contact_fields($area = '', $user = '') {
5294 global $sql_tbl, $current_language, $store_language;
5295
5296 if($area)
5297 $fields = func_query("SELECT $sql_tbl[contact_fields].*, IF($sql_tbl[contact_fields].avail LIKE '%$area%', 'Y', '') as avail, IF($sql_tbl[contact_fields].required LIKE '%$area%', 'Y', '') as required, $sql_tbl[contact_field_values].value FROM $sql_tbl[contact_fields] LEFT JOIN $sql_tbl[contact_field_values] ON $sql_tbl[contact_fields].fieldid = $sql_tbl[contact_field_values].fieldid AND $sql_tbl[contact_field_values].login = '$user' ORDER BY $sql_tbl[contact_fields].orderby");
5298 else
5299 $fields = func_query("SELECT * FROM $sql_tbl[contact_fields] ORDER BY orderby");
5300 if($fields) {
5301 foreach($fields as $k => $v) {
5302 $fields[$k]['title'] = func_get_languages_alt("lbl_contact_field_".$v['fieldid'], ($current_language?$current_language:$store_language));
5303 if(!$area) {
5304 $fields[$k]['avail'] = func_keys2hash($v['avail']);
5305 $fields[$k]['required'] = func_keys2hash($v['required']);
5306 } elseif($v['type'] == 'S' && $v['variants'])
5307 $fields[$k]['variants'] = @explode(";", $v['variants']);
5308 }
5309 }
5310 return $fields;
5311}
5312
5313#
5314# Transform key string to hash-array
5315#
5316function func_keys2hash($arr) {
5317 if(!$arr)
5318 return array();
5319 for($x = 0; $x < strlen($arr); $x++)
5320 $tmp[$arr[$x]] = 'Y';
5321 return $tmp;
5322}
5323
5324#
5325# Callback function: determination of empty field
5326#
5327function func_callback_empty($value) {
5328 return !empty($value);
5329}
5330
5331#
5332# Get language variables name from templates chain
5333#
5334function func_get_lng_chain($name, &$templater) {
5335 global $sql_tbl, $config, $shop_language, $current_area;
5336 global $override_lng_code, $predefined_lng_variables;
5337
5338
5339 $debug = $templater->debugging;
5340 $templater->debugging = true;
5341 $templater->fetch($name);
5342 $templater->debugging = $debug;
5343 if (!$templater->_smarty_debug_info)
5344 return false;
5345 $files = array();
5346 if(!empty($predefined_lng_variables) && is_array($predefined_lng_variables))
5347 $variables = $predefined_lng_variables;
5348 else
5349 $variables = array();
5350 $exist = array();
5351 foreach($templater->_smarty_debug_info as $v) {
5352 if ($v['type'] != 'template' || $exist[$v['filename']])
5353 continue;
5354 $fp = @fopen($templater->template_dir."/".$v['filename'], "r");
5355 if (!$fp)
5356 continue;
5357 $body = fread($fp, filesize($templater->template_dir."/".$v['filename']));
5358 fclose($fp);
5359 if (preg_match_all('/\$lng\.([\w\d_]+)[\}\s`\|]/US', $body, $preg))
5360 $variables = array_merge($variables, $preg[1]);
5361 $exist[$v['filename']] = true;
5362 }
5363 $page_content = $templater->get_template_vars("page_content");
5364 if (!empty($page_content)) {
5365 if (preg_match_all('/\$lng\.([\w\d_]+)[\}\s`\|]/US', $page_content, $preg))
5366 $variables = array_merge($variables, $preg[1]);
5367 }
5368 unset($exist);
5369 $lng = array();
5370 if (!empty($variables)) {
5371 $variables = array_flip($variables);
5372
5373 $lng_code = $override_lng_code;
5374 if (empty($override_lng_code)) {
5375 $lng_code = $shop_language;
5376 }
5377
5378 func_get_lang_vars($lng_code, $variables, $lng);
5379 if (!empty($variables)) {
5380 func_get_lang_vars(($current_area == 'C'?$config['default_customer_language']:$config['default_admin_language']), $variables, $lng);
5381 if (!empty($variables))
5382 func_get_lang_vars('US', $variables, $lng);
5383 }
5384
5385 if ($templater->webmaster_mode) {
5386 func_webmaster_convert_labels($lng);
5387 }
5388 }
5389 $templater->assign("lng", $lng);
5390 unset($lng);
5391 # clear info
5392 $templater->_smarty_debug_info = array();
5393 return true;
5394}
5395
5396#
5397# Subroutine for the func_get_lng_chain()
5398#
5399function func_get_lang_vars($code, &$variables, &$lng) {
5400 global $sql_tbl;
5401
5402 $labels = db_query("SELECT name, value FROM $sql_tbl[languages] WHERE code = '$code' AND name IN ('".implode("','", array_keys($variables))."')");
5403 if ($labels) {
5404 while ($v = db_fetch_array($labels)) {
5405 $lng[$v['name']] = $v['value'];
5406 unset($variables[$v['name']]);
5407 }
5408 db_free_result($labels);
5409 }
5410}
5411
5412#
5413# This function checks the user passwords with default values
5414#
5415function func_check_default_passwords($uname=false) {
5416 global $sql_tbl, $active_modules;
5417
5418 $default_accounts["A"] = array("admin");
5419 $default_accounts["P"] = array("provider", "master", "root");
5420
5421 if (!empty($active_modules["Simple_Mode"]))
5422 unset($default_accounts["A"]);
5423
5424 $return = array();
5425
5426 if (!empty($uname)) {
5427 #
5428 # Check password security for specified user name
5429 #
5430 $account = func_query_first("SELECT login, password FROM $sql_tbl[customers] WHERE login='$uname'");
5431 if ($account["login"] == text_decrypt($account["password"]))
5432 $return[] = $account["login"];
5433 }
5434 else {
5435 #
5436 # Check password security for all default user names
5437 #
5438 foreach ($default_accounts as $usertype=>$accounts) {
5439 foreach ($accounts as $login_) {
5440 if (!empty($uname) and $uname != $login_)
5441 continue;
5442 $account = func_query_first("SELECT login, password FROM $sql_tbl[customers] WHERE login='$login_' AND usertype='$usertype'");
5443 if (!empty($account)) {
5444 if ($account["login"] == text_decrypt($account["password"]))
5445 $return[] = $account["login"];
5446 }
5447 }
5448 }
5449 }
5450
5451 return $return;
5452}
5453
5454#
5455# Smarty->display wrapper
5456#
5457function func_display($tpl, &$templater, $to_display = true) {
5458
5459 func_get_lng_chain($tpl, $templater);
5460 if($to_display == true) {
5461 $templater->display($tpl);
5462 if(defined("START_TIME")) {
5463 global $__sql_time;
5464 $all_time = func_microtime()-START_TIME;
5465 echo '<!--<TIME all="'.$all_time.'" sql="'.$__sql_time.'" php="'.($all_time-$__sql_time).'">-->';
5466 }
5467 } else
5468 return $templater->fetch($tpl);
5469}
5470
5471#
5472# Check CC processor's transaction type
5473#
5474function func_check_cc_trans_type($module_name, $type, $hash = array("P" => "P", "C" => "C", "R" => "R")) {
5475 global $sql_tbl;
5476
5477 $return = false;
5478
5479 if(empty($type) || $type == 'P')
5480 $return = $hash['P'];
5481 elseif($type == 'C')
5482 if(func_query_firest_cell("SELECT is_check FROM $sql_tbl[ccprocessors] WHERE module_name = '$module_name'"))
5483 $return = $hash['C'];
5484 elseif($type == 'R')
5485 if(func_query_firest_cell("SELECT is_refund FROM $sql_tbl[ccprocessors] WHERE module_name = '$module_name'"))
5486 $return = $hash['R'];
5487
5488 if(empty($return) && $return !== false)
5489 $return = false;
5490
5491 return $return;
5492}
5493
5494#
5495# Check CC processor's transaction type
5496#
5497function func_check_cc_trans ($module_name, $type, $hash = array()) {
5498 global $sql_tbl;
5499
5500 $return = false;
5501 if(empty($hash) && is_array($hash))
5502 $hash = array("P" => "P", "C" => "C", "R" => "R");
5503 if(empty($type))
5504 $type = 'P';
5505
5506 if( $type == 'P') {
5507 $return = $hash[$type];
5508 } elseif($type == 'C') {
5509 if(func_query_first_cell("SELECT is_check FROM $sql_tbl[ccprocessors] WHERE module_name = '$module_name'"))
5510 $return = $hash[$type];
5511 } elseif($type == 'R') {
5512 if(func_query_first_cell("SELECT is_refund FROM $sql_tbl[ccprocessors] WHERE module_name = '$module_name'"))
5513 $return = $hash[$type];
5514 }
5515
5516 if(empty($return) && $return !== false)
5517 $return = false;
5518
5519 return $return;
5520}
5521
5522#
5523# Copy key field to hash key
5524#
5525function func_create_hash_keys($array, $key) {
5526 if(empty($array) || empty($key) || !is_array($array))
5527 return $array;
5528 $return = array();
5529 foreach($array as $v)
5530 $return[$v[$key]] = $v;
5531 return $return;
5532}
5533
5534#
5535# Recalculate product count in Categories table and Categories counts table
5536#
5537function func_recalc_product_count($categoryid) {
5538 global $sql_tbl, $config;
5539
5540 if(!is_array($categoryid))
5541 $categoryid = array($categoryid);
5542 if(empty($categoryid))
5543 return false;
5544 foreach($categoryid as $c) {
5545 if(is_array($c))
5546 $c = $c['categoryid'];
5547 $product_count = func_query_first_cell ("SELECT COUNT(*) FROM $sql_tbl[products], $sql_tbl[products_categories] WHERE $sql_tbl[products].productid=$sql_tbl[products_categories].productid AND $sql_tbl[products].forsale='Y' AND $sql_tbl[products_categories].categoryid='$c'");
5548 db_query("UPDATE $sql_tbl[categories] SET product_count='$product_count' WHERE categoryid='$c'");
5549 $lvls = $config['membership_levels'];
5550 $lvls[] = array("usertype" => "C", "membership" => "");
5551 foreach($lvls as $m) {
5552 if($m['usertype'] == 'C') {
5553 $m['membership'] = addslashes($m['membership']);
5554 if(func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[categories_subcount] WHERE categoryid = '$c' AND membership = '$m[membership]'")) {
5555 db_query("UPDATE $sql_tbl[categories_subcount] SET product_count = '$product_count' WHERE categoryid = '$c' AND membership = '$m[membership]'");
5556 } else {
5557 db_query("INSERT INTO $sql_tbl[categories_subcount] (categoryid,membership,product_count) VALUES ('$c','$m[membership]','$product_count')");
5558 }
5559 }
5560 }
5561 }
5562 return true;
5563}
5564
5565#
5566# Recalculate child categories count in Categories counts table
5567#
5568function func_recalc_subcat_count($categoryid) {
5569 global $sql_tbl, $config;
5570
5571 if(!is_array($categoryid))
5572 $categoryid = array($categoryid);
5573 if(empty($categoryid))
5574 return false;
5575 foreach($categoryid as $c) {
5576 if(is_array($c))
5577 $c = $c['categoryid'];
5578 $path = func_query_first_cell("SELECT categoryid_path FROM $sql_tbl[categories] WHERE categoryid = '$c'")."/%";
5579 $subcat_count = func_query_first_cell ("SELECT COUNT(*) FROM $sql_tbl[categories] USE INDEX (pam) WHERE categoryid_path LIKE '$path' AND avail = 'Y' AND membership = ''");
5580 $lvls = $config['membership_levels'];
5581 $lvls[] = array("usertype" => "C", "membership" => "");
5582 foreach($lvls as $m) {
5583 if($m['usertype'] == 'C') {
5584 $m['membership'] = addslashes($m['membership']);
5585 $subcat_count = func_query_first_cell ("SELECT COUNT(*) FROM $sql_tbl[categories] WHERE categoryid_path LIKE '$path' AND avail = 'Y' AND membership = '$m[membership]'");
5586 db_query("REPLACE INTO $sql_tbl[categories_subcount] (categoryid,subcategory_count,membership) VALUES ('$c','$subcat_count','$m[membership]')");
5587 }
5588 }
5589 func_recalc_product_count($c);
5590 }
5591 return true;
5592}
5593
5594#
5595# This function gathers the product taxes information
5596#
5597function func_get_product_taxes(&$product, $login, $calculate_discounted_price=false, $taxes="") {
5598
5599 global $sql_tbl, $config, $active_modules;
5600
5601 if ($calculate_discounted_price && isset($product["discounted_price"]))
5602 $price = $product["discounted_price"];
5603 else
5604 $price = $product["price"];
5605
5606 $amount = (isset($product["amount"]) ? $product["amount"] : 1);
5607
5608 if (empty($taxes))
5609 $taxes = func_get_product_tax_rates($product, $login);
5610
5611 foreach ($taxes as $k=>$tax_rate) {
5612 if ($tax_rate["price_includes_tax"] != "Y" or $product["price_deducted_tax"] == "Y")
5613 continue;
5614 if ($tax_rate["rate_type"] == "%") {
5615 $_tax_value = $price - $price*100/($tax_rate["rate_value"] + 100);
5616 $price = $price - $_tax_value;
5617 }
5618 else
5619 $price = $price - $tax_rate["rate_value"];
5620
5621 $product["price"] = $price;
5622 $product["price_deducted_tax"] = "Y";
5623 }
5624
5625 $taxed_price = $price;
5626
5627 $formula_data["ST"] = $price;
5628
5629 foreach ($taxes as $k=>$tax_rate) {
5630 #
5631 # Calculate the tax value
5632 #
5633 if (!empty($tax_rate["skip"]) or (empty($login) and $config["General"]["apply_default_country"] != "Y"))
5634 continue;
5635
5636 $assessment = func_calculate_assessment($tax_rate["formula"], $formula_data);
5637
5638 if ($tax_rate["rate_type"] == "%") {
5639 $tax_rate["tax_value_precise"] = $assessment * $tax_rate["rate_value"] / 100;
5640 $tax_rate["tax_value"] = price_format($tax_rate["tax_value_precise"]);
5641 }
5642 else
5643 $tax_rate["tax_value"] = $tax_rate["tax_value_precise"] = $tax_rate["rate_value"];
5644
5645 $tax_rate["taxed_price"] = $price + $tax_rate["tax_value"];
5646
5647 if ($tax_rate["display_including_tax"] == "Y")
5648 $taxed_price += $tax_rate["tax_value"];
5649
5650 $taxes[$k] = $tax_rate;
5651
5652 $formula_data[$k] = $tax_rate["tax_value"];
5653 }
5654
5655 if (is_array($taxes)) {
5656 foreach ($taxes as $k=>$v) {
5657 $taxes[$k]["tax_value"] = $v["tax_value_precise"] * $amount;
5658 }
5659 }
5660
5661 $product["taxed_price"] = price_format($taxed_price);
5662
5663 //print_r($taxes);
5664 return $taxes;
5665
5666
5667}
5668
5669#
5670# This function generate the product tax rates array
5671#
5672function func_get_product_tax_rates($product, $login) {
5673 global $sql_tbl, $shop_language;
5674 global $user_account;
5675
5676 $productid = $product["productid"];
5677
5678 $tax_rates = array();
5679
5680 #
5681 # Gather all taxes defined for store
5682 #
5683 $taxes = func_query("SELECT $sql_tbl[taxes].* FROM $sql_tbl[taxes], $sql_tbl[product_taxes] WHERE $sql_tbl[taxes].taxid=$sql_tbl[product_taxes].taxid AND $sql_tbl[product_taxes].productid='$productid' AND $sql_tbl[taxes].active='Y' ORDER BY $sql_tbl[taxes].priority");
5684
5685 if (is_array($taxes)) {
5686 #
5687 # Generate tax rates array
5688 #
5689 $membership = $user_account["membership"];
5690
5691 foreach ($taxes as $k=>$v) {
5692 if (!isset($address_zones[$v["address_type"]]))
5693 if (defined('XAOM')) {
5694 $address_zones[$v["address_type"]] = func_get_customer_zones_avail($user_account, $product["provider"], $v["address_type"]);
5695 }
5696 else {
5697 $address_zones[$v["address_type"]] = func_get_customer_zones_avail($login, $product["provider"], $v["address_type"]);
5698 }
5699 $zones = $address_zones[$v["address_type"]];
5700
5701 $tax_rate = "";
5702 foreach ($zones as $zoneid=>$p) {
5703 $tax_rate = func_query_first("SELECT taxid, formula, rate_value, rate_type FROM $sql_tbl[tax_rates] WHERE taxid='$v[taxid]' AND zoneid='$zoneid' AND (membership='$membership' OR membership='') ORDER BY membership DESC");
5704 if (!empty($tax_rate))
5705 break;
5706 }
5707
5708 if (empty($tax_rate)) {
5709 if ($v["price_includes_tax"] != "Y")
5710 continue;
5711 $tax_rate = func_query_first("SELECT taxid, formula, rate_value, rate_type FROM $sql_tbl[tax_rates] WHERE taxid='$v[taxid]' ORDER BY rate_value DESC LIMIT 1");
5712 $tax_rate["skip"] = true;
5713 }
5714
5715 if (empty($tax_rate["formula"]))
5716 $tax_rate["formula"] = $v["formula"];
5717
5718 $tax_rate["rate_value"] *= 1;
5719 $tax_rate["tax_display_name"] = func_get_languages_alt("tax_".$v["taxid"], $shop_language);
5720
5721 $tax_rate = func_array_merge($v, $tax_rate);
5722
5723 $tax_rates[$v["tax_name"]] = $tax_rate;
5724 }
5725 }
5726
5727 return $tax_rates;
5728
5729}
5730
5731#
5732# This function get the taxed price
5733#
5734function func_tax_price($price, $productid=0, $disable_abs=false, $discounted_price=0, $customer_info="", $taxes="", $price_deducted_tax=false) {
5735 global $sql_tbl, $config, $active_modules, $shop_language;
5736
5737 if (empty($customer_info)) {
5738 global $login;
5739 $customer_info["login"] = $login;
5740 }
5741
5742 $return_taxes = array();
5743
5744 if ($discounted_price == 0)
5745 $discounted_price = $price;
5746
5747 if ($productid > 0) {
5748 #
5749 # Get product taxes
5750 #
5751 $product = func_query_first("SELECT productid, provider, free_shipping, shipping_freight, distribution, '$price' as price FROM $sql_tbl[products] WHERE productid='$productid'");
5752
5753 $taxes = func_get_product_tax_rates($product, $customer_info["login"]);
5754 }
5755
5756 if (is_array($taxes)) {
5757 #
5758 # Calculate price and tax_value
5759 #
5760
5761 foreach ($taxes as $k=>$tax_rate) {
5762 if ($tax_rate["price_includes_tax"] != "Y" or $price_deducted_tax)
5763 continue;
5764 if ($tax_rate["rate_type"] == "%") {
5765 $_tax_value = $price - $price*100/($tax_rate["rate_value"] + 100);
5766 $price -= $_tax_value;
5767 if ($discounted_price > 0)
5768 $_tax_value = $discounted_price - $discounted_price*100/($tax_rate["rate_value"] + 100);
5769 $discounted_price -= $_tax_value;
5770
5771 }
5772 else {
5773 $price -= $tax_rate["rate_value"];
5774 $discounted_price -= $tax_rate["rate_value"];
5775 }
5776 }
5777
5778 $taxed_price = $discounted_price;
5779
5780 $formula_data["ST"] = $price;
5781 $formula_data["DST"] = $discounted_price;
5782
5783 foreach ($taxes as $k=>$v) {
5784 if (!empty($v["skip"]))
5785 continue;
5786
5787 if ($v["display_including_tax"] != "Y")
5788 continue;
5789 if ($v["rate_type"] == "%") {
5790 $assessment = func_calculate_assessment($v["formula"], $formula_data);
5791 $tax_value = price_format($assessment * $v["rate_value"] / 100);
5792 }
5793 elseif (!$disable_abs)
5794 $tax_value = $v["rate_value"];
5795
5796 $formula_data[$v["tax_name"]] = $tax_value;
5797
5798 $taxed_price += $tax_value;
5799
5800 $return_taxes["taxes"][$v["taxid"]] = $tax_value;
5801 }
5802 }
5803
5804 $return_taxes["taxed_price"] = $taxed_price;
5805
5806 return $return_taxes;
5807}
5808
5809#
5810# This function cacluate the assessment according to the formula string
5811#
5812function func_calculate_assessment($formula, $formula_data) {
5813 $return = 0;
5814 if (is_array($formula_data)) {
5815 # Correct the default values...
5816 if (empty($formula_data["DST"]))
5817 $formula_data["DST"] = $formula_data["ST"];
5818 if (empty($formula_data["SH"]))
5819 $formula_data["SH"] = 0;
5820
5821 # Preparing math expression...
5822 $_formula = $formula;
5823 foreach ($formula_data as $unit=>$value) {
5824 if (!is_numeric($value))
5825 $value = 0;
5826 $_formula = preg_replace("/\b".preg_quote($unit)."\b/", $value, $_formula);
5827 }
5828 $to_eval = "\$return = $_formula;";
5829 # Perform math expression...
5830 eval($to_eval);
5831 }
5832 return $return;
5833}
5834
5835#
5836# Search images in message body and return message body and images array
5837#
5838function func_attach_images($message) {
5839 global $http_location, $xcart_web_dir, $xcart_dir, $current_location;
5840
5841 # Get images location
5842 $hash = array();
5843 if(preg_match_all("/\s(?:src=|background=|(?:style=['\"].*url\())['\"]([^'\"]+)['\"]/SsUi", $message, $preg))
5844 $hash = $preg[1];
5845 if(empty($hash))
5846 return array($message, array());
5847
5848 # Get images data
5849 $names = array();
5850 $images = array();
5851 foreach($hash as $v) {
5852 $orig_name = $v;
5853 $parse = parse_url($v);
5854 $data = "";
5855 $file_path = "";
5856 if(empty($parse['scheme'])) {
5857 $v = str_replace($xcart_web_dir, "", $parse['path']);
5858 $file_path = $xcart_dir.str_replace("/", DIRECTORY_SEPARATOR, $v);
5859 $v = $http_location.$v;
5860 } elseif(strpos($v, $current_location) === 0) {
5861 $file_path = $xcart_dir.str_replace("/", DIRECTORY_SEPARATOR,substr($v, strlen($current_location)));
5862 }
5863
5864 if(file_exists($file_path) && is_readable($file_path)) {
5865 $fp = @fopen($file_path, "rb");
5866 if($fp) {
5867 $data = fread($fp, filesize($file_path));
5868 fclose($fp);
5869 }
5870 }
5871
5872 if(!empty($images[$v])) {
5873 continue;
5874 }
5875
5876 $tmp = array("name" => basename($v), "url" => $v, "data" => $data);
5877 if($names[$tmp['name']]) {
5878 $cnt = 1;
5879 $name = $tmp['name'];
5880 while ($names[$tmp['name']]) {
5881 $tmp['name'] = $name.$cnt++;
5882 }
5883 }
5884
5885 $names[$tmp['name']] = true;
5886 if (empty($tmp['data'])) {
5887 if ($fp = @fopen($tmp['url'], "rb")) {
5888 do {
5889 $tmpdata = fread($fp, 8192);
5890 if (strlen($tmpdata) == 0) {
5891 break;
5892 }
5893 $tmp['data'] .= $tmpdata;
5894 } while (true);
5895 fclose($fp);
5896 } else {
5897 continue;
5898 }
5899 }
5900 list($tmp1, $tmp2, $tmp3, $tmp['type']) = func_get_image_size(empty($data)?$tmp['url']:$file_path);
5901 $message = preg_replace("/(['\"])".str_replace("/", "\/", preg_quote($orig_name))."(['\"])/Ss", "\\1cid:".$tmp['name']."\\2", $message);
5902 $images[$tmp['url']] = $tmp;
5903 }
5904
5905 return array($message, $images);
5906}
5907
5908#
5909# Normalize path: remove "../", "./" and duplicated slashes
5910#
5911function func_normalize_path($path, $separator=DIRECTORY_SEPARATOR) {
5912 $qs = preg_quote($separator);
5913 $path = preg_replace("/[\\\\\/]+/S",$separator,$path);
5914 $path = preg_replace("!".$qs."\.".$qs."!S", $separator, $path);
5915
5916 $regexp = "!".$qs."[^".$qs."]+".$qs."\.\.".$qs."!S";
5917 for ($old="", $prev="1"; $old != $path; $path = preg_replace($regexp, $separator, $path)) {
5918 $old = $path;
5919 }
5920 return $path;
5921}
5922
5923#
5924# Get MD5 hash files data
5925#
5926function func_md5_hash_files_data($filename) {
5927 global $xcart_dir;
5928
5929 $fp = @fopen($filename, 'r');
5930 if(!$fp)
5931 return false;
5932
5933 $return = array();
5934 while($arr = fgetcsv($fp, 1024, "=")) {
5935 $name = $xcart_dir."/".$arr[0];
5936 $md5 = @md5_file($name);
5937 $falg = true;
5938 if($md5 != $arr[1])
5939 $flag = false;
5940 $return[] = array("file" => $arr[0], "orig_md5" => $arr[1], "md5" => $md5, "equal" => $flag);
5941 }
5942 return $return;
5943}
5944
5945#
5946# Translate products names to local product names
5947#
5948function func_translate_products($products, $code) {
5949 global $sql_tbl;
5950
5951 if(!is_array($products) || empty($products) || empty($code))
5952 return $products;
5953
5954 $hash = array();
5955 foreach($products as $k => $p) {
5956 $hash[$p['productid']][] = $k;
5957 }
5958 if(!empty($hash)) {
5959 foreach($hash as $pid => $keys) {
5960 $local = func_query_first("SELECT product, descr, full_descr as fulldescr FROM $sql_tbl[products_lng] WHERE productid = '$pid' AND code = '$code'");
5961 if(!empty($local)) {
5962 foreach($keys as $k) {
5963 $products[$k] = func_array_merge($products[$k], $local);
5964 }
5965 }
5966 }
5967 }
5968 return $products;
5969}
5970
5971#
5972# Remove parameters from QUERY_STRING by name
5973#
5974function func_qs_remove($qs, $param_name) {
5975 $pn = preg_quote($param_name,"!")."(\[[^&]*\])?";
5976 $qs = preg_replace("!(&?)(".$pn.")=\w*!S", "", $qs);
5977 $qs = preg_replace("!^&!S", "", $qs);
5978 return $qs;
5979}
5980
5981#
5982# Detectd ESD product(s) in cart
5983#
5984function func_esd_in_cart($cart) {
5985 if(!empty($cart['products'])) {
5986 foreach($cart['products'] as $p) {
5987 if(!empty($p['distribution'])) {
5988 return true;
5989 }
5990 }
5991 }
5992 return false;
5993}
5994
5995#
5996# Covert XML string to hash array
5997#
5998function func_xml2hash($str) {
5999 $str = (string)$str;
6000 $hash = array();
6001 for($x = 0; $x < strlen($str); $x++) {
6002 if ($str[$x] == '<') {
6003 $x++;
6004 if($str[$x] == "?") {
6005 $x = strpos(substr($str, $x), ">");
6006 continue;
6007 }
6008 $tmp = substr($str, $x);
6009 $c_name = substr($tmp, 0, strpos($tmp, ">"));
6010 $sub_data = array();
6011 $x += strlen($c_name)+1;
6012 $is_single = false;
6013 if (strpos($c_name, " ") !== false) {
6014 if(substr($c_name, -1) == '/') {
6015 $c_name = substr($c_name, 0, -1);
6016 $is_single = true;
6017 }
6018 $sub_data = explode(" ", $c_name);
6019 $c_name = trim(array_shift($sub_data));
6020 }
6021 if(empty($c_name))
6022 return false;
6023 $tmp = substr($str, $x);
6024 if(preg_match("/^(.*)<\/".preg_quote($c_name).">/USs", $tmp, $data)) {
6025 $hash[$c_name] = func_xml2hash($data[1]);
6026 $x += strlen($data[1])+2+strlen($c_name);
6027 } elseif(!$is_single) {
6028 return false;
6029 } elseif($sub_data) {
6030 foreach($sub_data as $sd) {
6031 list($key, $value) = explode("=", trim($sd));
6032 $hash[$c_name][][$key] = preg_replace("/^['\"](.+)['\"]$/S", "\\1", $value);
6033 }
6034 }
6035 }
6036 }
6037 if(empty($hash))
6038 $hash = $str;
6039 return $hash;
6040}
6041
6042#
6043# Convert hash array to XML string
6044#
6045function func_hash2xml($hash, $level = 0) {
6046 if(!is_array($hash) || empty($hash))
6047 return $hash;
6048
6049 foreach($hash as $k => $v) {
6050 $xml .= str_repeat("\t", $level)."<$k>".func_hash2xml($v, $level+1)."</$k>\n";
6051 }
6052 if($level > 0) {
6053 $xml = "\n".$xml."\n".str_repeat("\t", $level);;
6054 }
6055 return $xml;
6056}
6057
6058#
6059# Convert array to suitable-for-search string
6060#
6061function func_sql_serialize($arr) {
6062 if(empty($arr) || !is_array($arr))
6063 return $arr;
6064 return "|".implode("||", $arr)."|";
6065}
6066
6067#
6068# Convert suitable-for-search string to array
6069#
6070function func_sql_unserialize($str) {
6071 if(empty($str) || is_array($str))
6072 return $str;
6073 return explode("||", substr($str, 1, -1));
6074}
6075
6076#
6077# Function to get backtrace for debugging
6078#
6079function func_get_backtrace($skip=0) {
6080 $result = array();
6081 if (!function_exists('debug_backtrace')) {
6082 $result[] = '[func_get_backtrace() is supported only for PHP version 4.3.0 or better]';
6083 return $result;
6084 }
6085 $trace = debug_backtrace();
6086
6087 if (is_array($trace) && !empty($trace)) {
6088 if ($skip>0) {
6089 if ($skip < count($trace))
6090 $trace = array_splice($trace, $skip);
6091 else
6092 $trace = array();
6093 }
6094
6095 foreach ($trace as $item) {
6096 $result[] = $item['file'].':'.$item['line'];
6097 }
6098 }
6099
6100 if (empty($result)) {
6101 $result[] = '[empty backtrace]';
6102 }
6103
6104 return $result;
6105}
6106
6107?>