Help with modifying script to use cURL vs fopen

apps

#1

Hello,

I’ve been reading through the wiki and these forums regarding using cURL instead of fopen, but modifying this is a little over my head. I get the idea, just don’t quite have my head wrapped around the cURL options/syntax. I already have a custom php.ini setup running but would like to maintain security best practices by modifying this script instead of enabling fopen.

Here is the relevant portion of the script… any direction in switching it to use cURL is very much appreciated!

function getQuote(){
$upsAction = “3”; // You want 3. Don’t change unless you are sure.
$url = join("&",
array(“http://www.ups.com/using/services/rave/qcostcgi.cgi?accept_UPS_license_agreement=yes”,
“10_action=$upsAction”,
“13_product=$this->upsProductCode”,
“14_origCountry=$this->originCountryCode”,
“15_origPostal=$this->originPostalCode”,
“19_destPostal=$this->destPostalCode”,
“22_destCountry=$this->destCountryCode”,
“23_weight=$this->packageWeight”,
“47_rateChart=$this->rateCode”,
“48_container=$this->containerCode”,
“49_residential=$this->resComCode”
)
);

$fp = fopen($url, “r”);
while(!feof($fp)){
$result = fgets($fp, 500);

if(ereg(“Origin postal code must have five digits”,$result)){
echo “Origin postal code must have five digits to use UPS. Please update this in the module settings.”;
exit;
} elseif(ereg(“Unsupported country specified”,$result)){
echo “Unsupported country specified to use UPS. Please update this in the general settings.”;
exit;
}

$result = explode("%", $result);
$errcode = substr($result[0], -1);
switch($errcode){
case 3:
$returnval = $result[8];
break;
case 4:
$returnval = $result[8];
break;
case 5:
$returnval = $result[1];
break;
case 6:
$returnval = $result[1];
break;
}
}

fclose($fp);
if(! $returnval) { $returnval = “error”; }
return $returnval;
}
}


#2

Okay. Let me give this a try for you:

function getQuote() { $upsAction = "3"; // You want 3. Don't change unless you are sure. $url_array = array("http://www.ups.com/using/services/rave/qcostcgi.cgi?accept_UPS_license_agreement=yes", "10_action=$upsAction", "13_product=$this->upsProductCode", "14_origCountry=$this->originCountryCode", "15_origPostal=$this->originPostalCode", "19_destPostal=$this->destPostalCode", "22_destCountry=$this->destCountryCode", "23_weight=$this->packageWeight", "47_rateChart=$this->rateCode", "48_container=$this->containerCode", "49_residential=$this->resComCode"); $url = implode("&", $url_array); $ch = curl_init(); $timeout = 5; // set to zero for no timeout curl_setopt ($ch, CURLOPT_URL, $url); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $file_contents = curl_exec($ch); curl_close($ch); $lines = array(); $lines = explode("n", $file_contents); $result = $lines[500]; if(ereg("Origin postal code must have five digits",$result)) { echo "Origin postal code must have five digits to use UPS. Please update this in the module settings."; exit; } elseif(ereg("Unsupported country specified",$result)) { echo "Unsupported country specified to use UPS. Please update this in the general settings."; exit; } $result = explode("%", $result); $errcode = substr($result[0], -1); switch($errcode) { case 3: $returnval = $result[8]; break; case 4: $returnval = $result[8]; break; case 5: $returnval = $result[1]; break; case 6: $returnval = $result[1]; break; } if(!$returnval) { $returnval = "error"; } return $returnval; } }I noticed that there seemed to be an extra curly brace after the switch statement, and I moved that to the bottom to close the function after it had returned its value. I may have misunderstood that, so you should check it. I broke the array out of the implode() function (formerly join) for readability. The original script appears to use fgets to access line 500. The new version grabs the entire resource from UPS, and then reads the 500th line of the result.

I’m not sure if this is correct, but it should point you in the right direction.


Simon Jessey | Keystone Websites
Save $97 on yearly plans with promo code [color=#CC0000]SCJESSEY97[/color]


#3

Thank you very much, I’ll play with this a bit. The breakdown you provided at the end is helpful. It was precisely the fgets and handling the array that I wasn’t sure how to approach (I know a little, mostly just enough to be dangerous and mess myself up). :wink:

The curly brace after the switch statement belonged to:

while(!feof($fp)){

Thanks for getting me pointed in the right direction, I’ll report back here after I have a chance to test it later.


#4

Awesome, that did indeed get me pointed in the right direction.

I got it working when I input the string to UPS by hand and saw what the bit that cURL was grabbing was (just a single % delimited line to read into the $result array)… then I looked up fgets and saw that the 500 was just a byte limit for it reading the file (not a line number).

So I removed the $lines bit and set $result = $file_contents; at that point instead, and all works perfectly.

Thanks again!


#5

Really? Can you post your updated script here for me? I’d love to run some tests of my own and incorporate the findings in the wiki article.


Simon Jessey | Keystone Websites
Save $97 on yearly plans with promo code [color=#CC0000]SCJESSEY97[/color]


#6

sure… here is the portion we were going over (fyi it’s from within the UPS shipping module that is incorporated in CubeCart - www.cubecart.com). Let me know if you want to see the whole thing.

[code] function getQuote(){
$upsAction = “3”; // You want 3. Don’t change unless you are sure.
$url_array = array(“http://www.ups.com/using/services/rave/qcostcgi.cgi?accept_UPS_license_agreement=yes”,
“10_action=$upsAction”,
“13_product=$this->upsProductCode”,
“14_origCountry=$this->originCountryCode”,
“15_origPostal=$this->originPostalCode”,
“19_destPostal=$this->destPostalCode”,
“22_destCountry=$this->destCountryCode”,
“23_weight=$this->packageWeight”,
“47_rateChart=$this->rateCode”,
“48_container=$this->containerCode”,
“49_residential=$this->resComCode”);
$url = implode("&", $url_array);
$ch = curl_init();
$timeout = 5; // set to zero for no timeout
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
$result = $file_contents;
if(ereg(“Origin postal code must have five digits”,$result)) {
echo “Origin postal code must have five digits to use UPS. Please update this in the module settings.”;
exit;
} elseif(ereg(“Unsupported country specified”,$result)) {
echo “Unsupported country specified to use UPS. Please update this in the general settings.”;
exit;
}
$result = explode("%", $result);
$errcode = substr($result[0], -1);
switch($errcode) {
case 3:
$returnval = $result[8];
break;
case 4:
$returnval = $result[8];
break;
case 5:
$returnval = $result[1];
break;
case 6:
$returnval = $result[1];
break;
}
if(!$returnval) {
$returnval = “error”;
}
return $returnval;
}

[/code]


#7

That’s just fine, thank you. I’m glad it worked out :slight_smile:


Simon Jessey | Keystone Websites
Save $97 on yearly plans with promo code [color=#CC0000]SCJESSEY97[/color]


#8

for some reason my dreamhost server has had dns issues specifically when resolving www.ups.com, so curl would error out with:

[quote]curl exit code: 6
curl: (6) Couldn’t resolve host

[/quote]

in case anyone else runs into this issue, this simple workaround seems to work. Just get the ip address for ups.com and replace the domain name in the url string:

function getQuote(){
$hostname = gethostbyname('www.ups.com');

$upsAction = "3"; // You want 3.  Don't change unless you are sure.
$url_array = array("http://$hostname/using/services/rave/qcostcgi.cgi?accept_UPS_license_agreement=yes",
"10_action=$upsAction",
"13_product=$this->upsProductCode",
"14_origCountry=$this->originCountryCode",
"15_origPostal=$this->originPostalCode",
"19_destPostal=$this->destPostalCode",
"22_destCountry=$this->destCountryCode",
"23_weight=$this->packageWeight",
"47_rateChart=$this->rateCode",
"48_container=$this->containerCode",
"49_residential=$this->resComCode");
$url = implode("&", $url_array);
$ch = curl_init();
$timeout = 0; // set to zero for no timeout
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
$result = $file_contents;
if(ereg("Origin postal code must have five digits",$result)) {
echo "Origin postal code must have five digits to use UPS. Please update this in the module settings.";
exit;
} elseif(ereg("Unsupported country specified",$result)) {
echo "Unsupported country specified to use UPS. Please update this in the general settings.";
exit;
}
$result = explode("%", $result);
$errcode = substr($result[0], -1);
switch($errcode) {
case 3:
$returnval = $result[8];
break;
case 4:
$returnval = $result[8];
break;
case 5:
$returnval = $result[1];
break;
case 6:
$returnval = $result[1];
break;
}
if(!$returnval) {
$returnval = "error";
}
return $returnval;
}

#9

That’s a very useful post, and I’m sure will turn out to be helpful to many at onetime or another.

Thanks for taking the time to post it! :slight_smile:

–rlparker


#10

You. Absolutely. Rock.

Seriously, I couldn’t figure out why UPS abruptly stopped working. This solved it right off. I’m going to remember to add this as a common step in any future scripts, much smarter to have the url resolved first. Think I’ll wrap it with an error and toggle for debugging too.

Thanks again, I was looking at the wrong side of things… used to dedicated boxes where I’m aware of any server changes so I didn’t even think to check from the server point of view and tried to find the problem in the cart software instead.