php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #21023 Out Put Error from United Parcel Service Rate/Service CGI File
Submitted: 2002-12-14 22:52 UTC Modified: 2003-01-02 18:48 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: webmaster at crescentart dot com Assigned:
Status: No Feedback Package: Output Control
PHP Version: 4.3.0RC3 OS: Red Hat Linux 7.1
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: webmaster at crescentart dot com
New email:
PHP Version: OS:

 

 [2002-12-14 22:52 UTC] webmaster at crescentart dot com
I have create a php script that generates a shipping cost from a United Parcel Service host. The script has worked fine on all on all PHP releases prior to version 4.3.0RC2.


Example Script:
##########################START###########################
<?
/*
This is a UPS Shipping Program created with PHP (http://www.php.net). This program is design to be flexiable have the ability to perform several task including:
(1) Generate live shippping rates from a UPS server.
(2) Add the retail item cost per distributor if the retailer uses multiple distributors.
(3) Add the whole sale cost per item while categorizing the whole sales cost per distributor.
(4) Add the item weight per item while catagorizing the item weight per distributor.
(5) Add any applicable distributor handling fees to the final shipping cost.
(6) Seperate the UPS shipping fee(s), distributor handling fee(s), per item whole sale cost and per item retal cost of CHECK OUT ITEMS and Pre-Order items.

REQUIRMENTS:
(1) MYSQL 3.x or later.
(2) PHP 4.x (version 4.3.0RC2 is not compatable)or later compilled with MYSQL and BCMATH. 
(3) A Web Server.

Special Note(s): 
(1) The Check Out Items and Pre-Orders Items scripts are on seperate files to reduce the number of lines of code.
(2) The PHP code uses objects. There fore a MYSQL Table will be needed with columns named as shown in the code bellow.
(3) The mysql_fetch_object names ($string->string) names can be changed but changing any other codeing will cause this program to error out.
(4) To simplify the file to file linking the following (INCLUDE/REQUIRE functions) codes are located on a seperate file.

//Set the bcmath scale to two digits aftr the decimal point.
bcscale(2);

//Decode shoping cart, check out subtotal and pre-order sub totlal strings for later use.
$decode_basket = base64_decode($basket);

//Explode the shop cart string into an array for use in the shipping calculators bellow.
$percent_sym = explode("%","$decode_basket");

//Shipping calculator.
if($check_out_sub_total != ""){
	include "../check_out_items_shipping.php";
	$decode_check_out_sub_total = base64_decode($check_out_sub_total);
}
if($pre_order_sub_total != ""){
	include "../pre_order_items_shipping.php";
	$decode_pre_order_sub_total = base64_decode($pre_order_sub_total);
}
*/

	//Arrays for use in the $post_codes array_push function.
	$check_out_postal_codes = array();
	$check_out_dist_handle_fee_array = array();
	
	//A loop to seperate the basket string and extract the DB table name, item number and purchase quantity
	foreach($check_out_percent_syms as $items){
		//Seperate the basket string into speices to determine which table to target and perform various DB selects. 
		$carot = explode("^", "$items");
		$asterk = explode("*", "$carot[1]");
		$get_shipping_info = mysql_query("select * from $carot[0] where item_num = '$asterk[0]'");
		$shipper_info = mysql_fetch_object($get_shipping_info);
		
		//An if statment to isolate the check out items from the pre-order items.	
		if($shipper_info->availability !== "pre-order"){
			
			//Push the postal codes into an array.
			array_push($check_out_postal_codes, $shipper_info->shipper_postal_code);
			
			//Multiply the retail and whole sale items by their perspective quantities.	
			$check_out_retail_cost[$shipper_info->distributor] += "$shipper_info->retail_price" * "$asterk[1]";
			$check_out_wholesale_cost[$shipper_info->distributor] += "$shipper_info->wholesale_price" * "$asterk[1]";
			$check_out_distributor_weight[$shipper_info->distributor] += "$shipper_info->box_weight" * "$asterk[1]";
						
			/*If there are duplicate postal codes and handling fees the items are probalby from the same distributor and duplicate shipping fees should not be applicable.	
			The folowing PHP functions array_unique removes duplicate postal codes.*/
			$check_out_duplicate_postal_codes = array_values(array_unique($check_out_postal_codes));
			
			//Strings for the shipping calculator.	
			$first_codes = "POST /using/services/rave/qcost_dss.cgi HTTP/1.0\n";
			$first_codes .= "Content-type: application/x-www-form-urlencoded\n";
			//Notice that the content length is inside of a loop bellow.
			$second_codes = "AppVersion=1.2&";
			$second_codes .= "AcceptUPSLicenseAgreement=YES&";
			$second_codes .= "ResponseType=application/x-ups-rss&";
			$second_codes .= "ActionCode=3&";
			$second_codes .= "ServiceLevelCode=$ship_method&";
			$second_codes .= "RateChart=Regular+Daily+Pickup&";
			//Notice that the shipper postal code is inside of a loop bellow.
			$third_codes = "ConsigneePostalCode=$ship_postal_code&";
			$third_codes .= "ConsigneeCountry=$ship_country&";
			//Notice that the weight is inside of a loop bellow.
		
			//In a previous page I have a company text field to determine if the shipping destination is residential or commercial.
			if($ship_company != "") {
				$fourth_codes = "ResidentialInd=0&";
			}		
			else{$fourth_codes .= "ResidentialInd=1&";}
	
			$fourth_codes .= "PackagingType=00\n\n";
		
		}//END FIRST FOREACH LOOP.
	}//END FIRST IF STATEMENT	
					
		
	//A SECOND IF STATEMENT TO DETERMINE IF GENERATING A SHIPPING RATE IS NECESSARY.
	if(isset($check_out_duplicate_postal_codes)){
		foreach($check_out_duplicate_postal_codes as $check_out_postal_code){
			$get_dist_info = mysql_query("select * from distributors where dist_ship_postal_code = '$check_out_postal_code'");
			$dist_info = mysql_fetch_object($get_dist_info);
			mysql_free_result($get_dist_info);
		
			//The list function is used inside of a if statement to determin if multile distributors are present and to
			//extract the weight per distribtor. The $value variable is the actual weight.
			if(count($check_out_distributor_weight) <= "1"){
				$value = $check_out_distributor_weight[$dist_info->dist_code];
			}
			elseif(count($check_out_distributor_weight) > "1" ){			
				list(,$value) = each($check_out_distributor_weight);
			}
			
			//A series of ifelse statments for use with the contentlengt. The starting lavue of 265 is an educated guess of a begining contentlength.
			if(strlen($value) == "1"){
				$length = "265"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "2"){
				$length = "266"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "3"){
				$length = "267"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "4"){
				$length = "268"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "5"){
				$length = "269"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "6"){
				$length = "270"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "7"){
				$length = "271"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "8"){
				$length = "272"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "9"){
				$length = "273"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "10"){
				$length = "274"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "11"){
				$length = "275"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "12"){
				$length = "276"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "13"){
				$length = "277"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "14"){
				$length = "278"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "15"){
				$length = "279"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "16"){
				$length = "280"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "17"){
				$length = "281"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "18"){
				$length = "82"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "19"){
				$length = "283"+(strlen($ship_postal_code));
			}
			elseif(strlen($value) == "20"){
				$length = "284"+(strlen($ship_postal_code));
			}
			
			//All of the above codes are joined together. The $all_codes variable will be POSTED to the www.ups.com/using/services/rave/qcost_dss.cgi file.
			$all_codes = "$first_codes"."Content-length: $length\n\n"."$second_codes"."ShipperPostalCode=$dist_info->dist_ship_postal_code&"."$third_codes"."PackageActualWeight=$value&"."$fourth_codes";
			
			//Open a socket to ups.com to get shipping rates.
			$open_sock = fsockopen("www.ups.com",80, $errno, $errstr,30);
			if(!($open_sock)){
				die(header("location: http://$none_secured_domain/shipping_error.php?ship_method=$ship_method&ups=false"));
			} 
			else {
				while(!(feof($open_sock))){
				fputs($open_sock, $all_codes);
				while($line = fgets($open_sock, 1000)){ 
					$contents .= $line;
					$check_out_find_rate = explode("%", $contents);
					break;
						}					
					}
				}
				
			//if the shipping rate can not be found the script dies and directs the user to a error page.
			if($check_out_find_rate[14] == false){
				fclose($open_sock);
				mysql_close($connect);
				die(header("location: http://$none_secured_domain/shipping_error.php?ship_method=$ship_method"));
				}
			
			//Use this variable string to store the shipping cost for each distcode in a $key. 
			//Example: $check_out_dist_ups_rates[abc] will print $0.00.	
			$check_out_dist_ups_rates[$dist_info->dist_code] += "$check_out_find_rate[14]";
		
			//Increment the ups rate to add all of the UPS shipping charges.
			$check_out_ship_rate += $check_out_find_rate[14];
		
			//This script has problems with not over writting $contents so the unset function is used to clear out the $contents variable.
			unset($contents);
			fclose($open_sock);
					
		}//END FOREACH LOOP
			
			//Loop through each wholesale price to determine if a handling fee is applicable and to obtain the per item 
			//wholesale cost and per distributor handling fee(s).
			//The $value variable represents a Distributors minmum order dollare amount that will be aplied unless
			//a order oabove the minimum. Example: Techdata charges $5.00 per customer address unless the order excedds $500.00.
			while(list($key, $value) = each ($check_out_wholesale_cost)){
				$check_out_wholesale .= "$key"."_"."$value"."%";
				$get_handling_fee_minimum = mysql_query("select * from distributors where dist_code = '$key'");
				$handling_fee = mysql_fetch_object($get_handling_fee_minimum);
				mysql_free_result($get_handling_fee_minimum);
				if("$value" < "$handling_fee->dist_shipp_minimum"){
					$check_out_ship_fee += "$handling_fee->dist_shipp_fee";
				}
			}
			//Cut the last percent character off of the strings above.
			//$check_out_dist_handle_fee_string = substr("$check_out_dist_handle_fee", 0, strlen($check_out_dist_handle_fee)-1);
			$check_out_wholesale_items_cost_string = substr("$check_out_wholesale", 0, strlen($wholesale)-1);
		
			//Loop through each retail price to extract the retail cost per item.	
			while(list($key, $value) = each ($check_out_retail_cost)){
				$check_out_retail .= "$key"."_"."$value"."%";
			}
			//Cut the last percent character off of the $check_out_retail above.	
			$check_out_retail_items_cost_string = substr("$check_out_retail", 0, strlen($retail)-1);
		
		//Loop throught the UPS rates to extract the UPS shipping rates per distributor and to assemble
		//string to represent the distributor handling fees.
		while(list($key, $value) = each ($check_out_dist_ups_rates)){
			$check_out_ups .= "$key"."_"."$value"."%";
			$get_dist_check_out_handle_fee = mysql_query("select * from distributors where dist_code = '$key'") or die(mysql_error());
			$check_out_dist_handle_fee = mysql_fetch_object($get_dist_check_out_handle_fee);
			$check_out_dist_handle_fee_string .= "$key"."_"."$check_out_dist_handle_fee->dist_shipp_fee"."%";
			mysql_free_result($get_dist_check_out_handle_fee);
		}
		
		//Cut the last percent character off.
		$check_out_items_ups_dist_rates = substr("$check_out_ups", 0, strlen($check_out_ups)-1);
	
	//Add the DISTRIBUTOR HANDLING FEE(S) and the UPS SHIPPING RATE(S) to calculate a complete SHIPING & HANDLING CHARGE for the customer. This charge is for CHECK OUT ITEMS only.
	$complete_check_out_items_shipping_handling_charge = bcadd($check_out_ship_rate, $check_out_ship_fee);
}//END IF STATEMENT
?>

#########################END###########################


The way the script works is that the scipt contacts a www.ups.com/using/services/rave/qcost_dss.cgi server which outputs text like the one bellow:


#########################START############################
HTTP/1.1 200 OK
Server: Netscape-Enterprise/6.0
Date: Sun, 15 Dec 2002 04:21:03 GMT
Content-type: multipart/mixed;boundary=UPSBOUNDARY
Content-length: 267
Connection: close

POST /using/services/rave/qcost_dss.cgi HTTP/1.0
Content-type: application/x-www-form-urlencoded
Content-length: 270

AppVersion=1.2&AcceptUPSLicenseAgreement=YES&ResponseType=application/x-ups-rss&ActionCode=3&ServiceLevelCode=GND&RateChart=Regular+Daily+Pickup&ShipperPostalCode=55428&ConsigneePostalCode=48235&ConsigneeCountry=US&PackageActualWeight=2&ResidentialInd=0&PackagingType=00

<HTML>
<BODY>
</BODY>
</HTML>


--UPSBOUNDARY
Content-type: application/x-ups-rss
Content-length: 78

UPSOnLine%1.2%0000%0000Success%3%GND%55428%US%48235%US%004%2%3.92%0.00%3.92%-1

--UPSBOUNDARY--
###########################END##############################


The script will then join(.=) the text into an array which is exploded by a % symbol in this case the rate is 3.92 as indicated by $var[14].

Unfortunatly PHP version 4.3.0RC2 only outputes the folowing line:

##############################START#########################
HTTP/1.1 200 OK
##############################END###########################

 

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-12-14 23:38 UTC] iliaa@php.net
Shorter & to the point please :)
 [2003-01-02 18:48 UTC] sniper@php.net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Open". Thank you.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 04:01:28 2024 UTC