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