function cw_fedex_get_meter_number($userinfo, &$error)
{
    global $config;
    // FedEx host
    $fedex_host = $config['shipping_fedex']['is_test_mode'] == 'Y' ? 'gatewaybeta.fedex.com/GatewayDC' : 'gateway.fedex.com/GatewayDC';
    $xml_contact_fields = array();
    $xml_address_fields = array();
    $userinfo = array_map('htmlspecialchars', $userinfo);
    if (!empty($userinfo['company_name'])) {
        $xml_contact_fields[] = "<CompanyName>{$userinfo['company_name']}</CompanyName>";
    }
    if (!empty($userinfo['pager_number'])) {
        $xml_contact_fields[] = "<PagerNumber>{$userinfo['pager_number']}</PagerNumber>";
    }
    if (!empty($userinfo['fax_number'])) {
        $xml_contact_fields[] = "<FaxNumber>{$userinfo['fax_number']}</FaxNumber>";
    }
    if (!empty($userinfo['email'])) {
        $xml_contact_fields[] = "<E-MailAddress>{$userinfo['email']}</E-MailAddress>";
    }
    if (!empty($userinfo['address_2'])) {
        $xml_address_fields[] = "<Line2>{$userinfo['address_2']}</Line2>";
    }
    $xml_contact_fields_str = implode("\n\t\t", $xml_contact_fields);
    $xml_address_fields_str = implode("\n\t\t", $xml_address_fields);
    if (!empty($userinfo['state']) && in_array($userinfo['country'], array("US", "CA", "PR"))) {
        $state = "<StateOrProvinceCode>{$userinfo['state']}</StateOrProvinceCode>";
    } else {
        $state = '';
    }
    $xml_query = <<<OUT
<?xml version="1.0" encoding="UTF-8" ?>
<FDXSubscriptionRequest xmlns:api="http://www.fedex.com/fsmapi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FDXSubscriptionRequest.xsd">
    <RequestHeader>
        <CustomerTransactionIdentifier>1</CustomerTransactionIdentifier>
        <AccountNumber>{$config['shipping_fedex']['account_number']}</AccountNumber>
    </RequestHeader>
    <Contact>
        <PersonName>{$userinfo['person_name']}</PersonName>
        <PhoneNumber>{$userinfo['phone_number']}</PhoneNumber>
{$xml_contact_fields_str}
    </Contact>
    <Address>
        <Line1>{$userinfo['address_1']}</Line1>
{$xml_address_fields_str}
        <City>{$userinfo['city']}</City>
        {$state}
        <PostalCode>{$userinfo['zipcode']}</PostalCode>
        <CountryCode>{$userinfo['country']}</CountryCode>
    </Address>
</FDXSubscriptionRequest>
OUT;
    $data = explode("\n", $xml_query);
    $host = "https://" . $fedex_host;
    list($header, $result) = cw_https_request('POST', $host, $data, '', '', 'text/xml');
    $parse_error = false;
    $options = array('XML_OPTION_CASE_FOLDING' => 1, 'XML_OPTION_TARGET_ENCODING' => 'UTF-8');
    $parsed = cw_xml_parse($result, $parse_error, $options);
    $error = array();
    if (empty($parsed)) {
        $error['msg'] = cw_get_langvar_by_name("msg_fedex_meter_number_incorrect_data_err");
        return false;
    }
    $type = key($parsed);
    $meter_number = cw_array_path($parsed, $type . "/METERNUMBER/0/#");
    if (empty($meter_number)) {
        $error['code'] = cw_array_path($parsed, $type . "/ERROR/CODE/0/#");
        $error['msg'] = cw_array_path($parsed, $type . "/ERROR/MESSAGE/0/#");
        if (empty($error['code'])) {
            $error['code'] = cw_array_path($parsed, "ERROR/CODE/0/#");
            $error['msg'] = cw_array_path($parsed, "ERROR/MESSAGE/0/#");
        }
        if (!empty($error['code'])) {
            $error['msg'] = "FedEx addon error: [{$error['code']}] {$error['msg']}";
        } else {
            $error['msg'] = cw_get_langvar_by_name("msg_fedex_meter_number_empty_err");
        }
        return false;
    }
    return $meter_number;
}
function cw_shipper($weight, $address, $debug = "N", $cart = false)
{
    global $allowed_shipping_methods, $rates;
    global $tables;
    global $config;
    $__intershipper_userinfo = $address;
    $rates = array();
    $intershipper_countries = array('IE' => 'IR', 'VA' => 'IT', 'FX' => 'FR', 'PR' => 'US');
    #
    # Intershipper depends on XML parser (EXPAT extension)
    #
    if (test_expat() == "") {
        return;
    }
    if (empty($address)) {
        if ($config['General']['apply_default_country'] == "Y" || $debug == "Y") {
            $__intershipper_userinfo = cw_user_get_default_address();
        } else {
            return array();
        }
    }
    $pounds = cw_weight_in_grams($weight) / 453;
    $pounds = sprintf("%.2f", round((double) $pounds + 9.999999999999999E-12, 2));
    if ($pounds < 0.1) {
        $pounds = 0.1;
    }
    $servername = "www.intershipper.com";
    $scriptname = "/Shipping/Intershipper/XML/v2.0/HTTP.jsp";
    $username = $config['Shipping']['intershipper_username'];
    $password = $config['Shipping']['intershipper_password'];
    $delivery = $params['param00'];
    $shipmethod = $params['param01'];
    $CO = $config['Company']['country'];
    $ZO = urlencode($config['Company']['zipcode']);
    $CD = $__intershipper_userinfo['country'];
    $ZD = urlencode($__intershipper_userinfo['zipcode']);
    if (!empty($intershipper_countries[$CD])) {
        $CD = $intershipper_countries[$CD];
    }
    if (!empty($intershipper_countries[$CO])) {
        $CO = $intershipper_countries[$CO];
    }
    $__intershipper_userinfo['country'] = $CD;
    $config['Company']['country'] = $CO;
    $length = (double) $params['param02'];
    $width = (double) $params['param03'];
    $height = (double) $params['param04'];
    $dunit = $params['param05'];
    $packaging = $params['param06'];
    $contents = $params['param07'];
    $codvalue = (double) $params['param08'];
    $insvalue = (double) $params['param09'];
    $queryid = substr(uniqid(rand()), 0, 15);
    $wunit = strtoupper(trim($config['General']['weight_symbol']));
    if (strlen($wunit) > 2) {
        $wunit = substr($wunit, 0, 2);
    }
    $allowed_shipping_methods = cw_query("SELECT * FROM {$tables['shipping']} WHERE active=1");
    $carriers = cw_query_column("SELECT DISTINCT(code) FROM {$tables['shipping']} WHERE code<>'' AND intershipper_code!='' AND active=1");
    if (!$carriers || !$username || !$password) {
        return array();
    }
    $post[] = "Version=2.0.0.0";
    $post[] = "ShipmentID=1";
    $post[] = "QueryID=1";
    $post[] = "Username={$username}";
    $post[] = "Password={$password}";
    $post[] = "TotalClasses=4";
    $post[] = "ClassCode1=GND";
    $post[] = "ClassCode2=1DY";
    $post[] = "ClassCode3=2DY";
    $post[] = "ClassCode4=3DY";
    $post[] = "DeliveryType={$delivery}";
    $post[] = "ShipMethod={$shipmethod}";
    $post[] = "OriginationPostal={$ZO}";
    $post[] = "OriginationCountry={$CO}";
    $post[] = "DestinationPostal={$ZD}";
    $post[] = "DestinationCountry={$CD}";
    $post[] = "Currency=USD";
    // Currently, supported only "USD". maxlen=3
    $post[] = "TotalPackages=1";
    $post[] = "BoxID1=box1";
    $post[] = "Weight1={$pounds}";
    $post[] = "WeightUnit1=LB";
    $post[] = "Length1={$length}";
    $post[] = "Width1={$width}";
    $post[] = "Height1={$height}";
    $post[] = "DimensionalUnit1={$dunit}";
    // DimensionalUnit	::= CM | IN
    $post[] = "Packaging1={$packaging}";
    // Packaging		::= BOX | ENV | LTR | TUB
    $post[] = "Contents1={$contents}";
    $post[] = "Cod1={$codvalue}";
    $post[] = "Insurance1={$insvalue}";
    $post[] = "TotalCarriers=" . count($carriers);
    foreach ($carriers as $k => $v) {
        if ($v == 'CPC') {
            $v = 'CAN';
        }
        $post[] = "CarrierCode" . ($k + 1) . "=" . $v;
    }
    $query = join('&', $post);
    $md5_request = md5($query);
    if (cw_is_shipping_result_in_cache($md5_request) && $debug != "Y") {
        return cw_get_shipping_result_from_cache($md5_request);
    }
    list($header, $result) = cw_http_get_request($servername, $scriptname, $query);
    $result = preg_replace("/^<\\?xml\\s+[^>]+>/s", "", trim($result));
    $parse_errors = false;
    $options = array('XML_OPTION_CASE_FOLDING' => 1, 'XML_OPTION_TARGET_ENCODING' => 'ISO-8859-1');
    $parsed = cw_xml_parse($result, $parse_errors, $options);
    $destination = $__intershipper_userinfo['country'] == $config['Company']['country'] ? "L" : "I";
    $packages =& cw_array_path($parsed, 'SHIPMENT/PACKAGE');
    if (is_array($packages)) {
        $rates = array();
        foreach ($packages as $pkginfo) {
            if (empty($pkginfo['#']) || !is_array($pkginfo['#'])) {
                continue;
            }
            foreach ($pkginfo['#']['QUOTE'] as $quote) {
                $carrier = cw_array_path($quote, 'CARRIER/CODE/0/#');
                if ($carrier == 'USP') {
                    $carrier = 'USPS';
                }
                $service = cw_array_path($quote, 'SERVICE/NAME/0/#');
                $sn = cw_array_path($quote, 'SERVICE/CODE/0/#');
                $rate = cw_array_path($quote, 'RATE/AMOUNT/0/#') / 100.0;
                if (!$carrier || !($service || $sn) || !$rate) {
                    continue;
                }
                $saved = -1;
                foreach ($allowed_shipping_methods as $sk => $sv) {
                    if ($sv['code'] != $carrier || $sv['destination'] != $destination) {
                        continue;
                    }
                    if ($sv['intershipper_code'] == 'CPC') {
                        $sv['intershipper_code'] = 'CAN';
                    }
                    if ((!$sn || $sv['intershipper_code'] != $sn) && (!$service || !stristr($sv['shipping'], $service))) {
                        continue;
                    }
                    # Suppressing duplicates
                    if ($saved < 0 || strlen($allowed_shipping_methods[$saved]['shipping']) > strlen($sv['shipping'])) {
                        $saved = $sk;
                    }
                }
                if ($saved >= 0) {
                    $rates[$allowed_shipping_methods[$saved]['subcode']] = $rate;
                }
            }
        }
        if (!empty($rates)) {
            foreach ($rates as $k => $v) {
                $rates[$k] = array("methodid" => $k, "rate" => $v);
            }
            if ($debug != "Y") {
                cw_save_shipping_result_to_cache($md5_request, $rates);
            }
        }
    }
    return $rates;
}
function cw_ups_process($request, $tool)
{
    $post = explode("\n", $request);
    list($a, $result) = cw_https_request('POST', 'https://www.ups.com:443/ups.app/xml/' . $tool, $post, '', '', 'text/xml');
    /*
    header('Content-type: text/xml');
    echo $result;
    die;
    */
    $parse_error = false;
    $options = array('XML_OPTION_CASE_FOLDING' => 1, 'XML_OPTION_TARGET_ENCODING' => 'ISO-8859-1');
    return cw_xml_parse($result, $parse_error, $options);
}
function ab_int_ratings($allowed_shipping_methods, $address, $weight, $debug, $params)
{
    global $config, $tables;
    if ($config['Company']['country'] != 'US' || $address['country'] == 'US') {
        return array();
    }
    cw_load('xml', 'http');
    # Define transaction parameters
    $siteid = $params['id'];
    $pass = $params['password'];
    $skey = $params['skey'];
    $anumber = $params['account'];
    $sh_email = $config['Company']['orders_department'];
    $sh_address = $config['Company']['address'];
    $sh_city = $config['Company']['city'];
    $sh_state = $config['Company']['state'];
    $sh_zipcode = $config['Company']['zipcode'];
    $sh_country = $config['Company']['country'];
    $rc_address = $address['address'];
    $rc_address_2 = $address['address_2'];
    $rc_city = $address['city'];
    $rc_state = $address['state'];
    $rc_zipcode = $address['zipcode'];
    $rc_country = $address['country'];
    $rc_phone = $address['phone'];
    $rc_email = $address['email'];
    $p_width = intval($params['length']);
    $p_height = intval($params['height']);
    $p_depth = intval($params['width']);
    $p_type = $params['package'];
    $c_name = $config['Company']['company_name'];
    $c_phone = $config['Company']['company_phone'];
    $c_fax = $config['Company']['company_fax'];
    $ship_date = $params['ship_date'];
    # Correct United Kingdom code - UK
    if ($rc_country == 'GB') {
        $rc_country = 'UK';
    }
    # Define request header
    $post = <<<REQ
<?xml version='1.0'?><ECommerce action='Request' version='1.1'>
\t<Requestor>
\t\t<ID>{$siteid}</ID>
\t\t<Password>{$pass}</Password>
\t</Requestor>
REQ;
    $ship_weight = $params['weight'];
    $ship_weight_oz = $params['weight_oz'];
    if ($ship_weight_oz > 8 && $p_type == 'L') {
        return;
    }
    # Define request body
    $i = 0;
    foreach ($allowed_shipping_methods as $method) {
        if ($method['code'] != "ARB" || $params['weight'] > $method['weight_limit'] && $method['weight_limit'] > 0 || empty($method['subcode']) || $method['destination'] == 'L' || !isset($mod_AB_ship_flags[$method['subcode']])) {
            continue;
        }
        $scode = $mod_AB_ship_flags[$method['subcode']]['code'];
        $i++;
        $dims = '';
        if ($p_type == 'P') {
            $dims = <<<DIMS
\t\t<Weight>{$ship_weight}</Weight>
\t\t<Dimensions>
\t\t\t<Length>{$p_width}</Length>
\t\t\t<Width>{$p_height}</Width>
\t\t\t<Height>{$p_depth}</Height>
\t\t</Dimensions>
DIMS;
        }
        $post .= <<<REQ
 <IntlShipment action = 'RateEstimate' version = '1.0'>
\t<ShippingCredentials>
\t\t<ShippingKey>{$skey}</ShippingKey>
\t\t<AccountNbr>{$anumber}</AccountNbr>
\t</ShippingCredentials>
\t<ShipmentDetail>
\t\t<ShipDate>{$ship_date}</ShipDate>
\t\t<Service>
\t\t\t<Code>{$scode}</Code>
\t\t</Service>
\t\t<ShipmentType>
\t\t\t<Code>{$p_type}</Code>
\t\t</ShipmentType>
\t\t<ContentDesc>Big Box</ContentDesc>
\t\t{$dims}
\t</ShipmentDetail>
\t<Dutiable>
\t\t<DutiableFlag>N</DutiableFlag>
\t\t<CustomsValue>0</CustomsValue>
\t</Dutiable>
\t<Billing>
\t\t<Party>
\t\t\t<Code>S</Code>
\t\t</Party>
\t\t<DutyPaymentType>S</DutyPaymentType>
\t</Billing>
\t<Sender>
\t\t<Address>
\t\t\t<CompanyName>{$c_name}</CompanyName>
\t\t\t<Street>{$sh_address}</Street>
\t\t\t<City>{$sh_city}</City>
\t\t\t<State>{$sh_state}</State>
\t\t\t<PostalCode>{$sh_zipcode}</PostalCode>
\t\t\t<Country>{$sh_country}</Country>
\t\t</Address>
\t\t<PhoneNbr>{$c_phone}</PhoneNbr>
\t\t<Email>{$sh_email}</Email>
\t</Sender>
\t<Receiver>
\t\t<Address>
\t\t\t<Street>{$rc_address}</Street>
\t\t\t<StreetLine2>{$rc_address_2}</StreetLine2>
\t\t\t<City>{$rc_city}</City>
\t\t\t<PostalCode>{$rc_zipcode}</PostalCode>
\t\t\t<State>{$rc_state}</State>
\t\t\t<Country>{$rc_country}</Country>
\t\t</Address>
\t\t<PhoneNbr>{$rc_phone}</PhoneNbr>
\t\t<Email>{$rc_email}</Email>
\t</Receiver>
</IntlShipment>
</ECommerce>
REQ;
    }
    if (empty($i)) {
        return array();
    }
    # Request
    list($a, $result) = cw_https_request("POST", $params['url'], array($post), "", "", "text/xml");
    $parse_errors = false;
    $options = array('XML_OPTION_CASE_FOLDING' => 1, 'XML_OPTION_TARGET_ENCODING' => 'ISO-8859-1');
    $parsed = cw_xml_parse($result, $parse_errors, $options);
    # Detect common errors
    $errors = cw_array_path($parsed, "ECOMMERCE/FAULT");
    if (!empty($errors)) {
        if ($debug == 'Y') {
            echo "<h1>DHL/Airborne request faults</h1>\n";
        }
        foreach ($errors as $k => $v) {
            $errors[$k] = cw_array_path($v, "#/CODE/0/#") . ": " . cw_array_path($v, "#/DESCRIPTION/0/#");
            if ($debug == 'Y') {
                echo $errors[$k] . "<br />\n";
            }
        }
        return array();
    }
    # Detect rates
    $methods = cw_array_path($parsed, "ECOMMERCE/INTLSHIPMENT");
    if (empty($methods)) {
        return array();
    }
    foreach ($methods as $m) {
        # Detect rate error
        $errs = cw_array_path($m, "#/FAULTS");
        if (!empty($errs)) {
            $errors = array();
            foreach ($errs as $e) {
                $suberrors = cw_array_path($e, "#/FAULT");
                if (!empty($suberrors)) {
                    foreach ($suberrors as $se) {
                        $errors[] = cw_array_path($se, "#/CODE/0/#") . ": " . cw_array_path($se, "#/DESC/0/#");
                    }
                }
            }
            continue;
        }
        # Detect rate
        $id = trim(cw_array_path($m, "ESTIMATEDETAIL/SERVICE/CODE/0/#"));
        $rate = doubleval(trim(cw_array_path($m, "ESTIMATEDETAIL/RATEESTIMATE/0/#/TOTALCHARGEESTIMATE/0/#")));
        # Save rate
        foreach ($allowed_shipping_methods as $method) {
            if ($method['code'] != "ARB" || $weight > $method['weight_limit'] && $method['weight_limit'] > 0 || $mod_AB_ship_flags[$method['subcode']]['code'] != $id || $method['destination'] == 'L') {
                continue;
            }
            $rates[] = array("methodid" => $method['subcode'], "rate" => $rate, "shipping_time" => trim(cw_array_path($m, "ESTIMATEDETAIL/SERVICELEVELCOMMITMENT/DESC/0/#")));
        }
    }
}
function cw_xml2hash($str)
{
    global $app_main_dir;
    $err = false;
    $options = array('XML_OPTION_CASE_FOLDING' => 0, 'XML_OPTION_TARGET_ENCODING' => 'ISO-8859-1');
    $parsed = cw_xml_parse($str, $err, $options);
    if (!empty($parsed)) {
        foreach ($parsed as $k => $v) {
            if (is_array($v['#'])) {
                $is_str = $is_arr = 0;
                foreach ($v['#'] as $subv) {
                    if (is_array($subv)) {
                        $is_array++;
                    } else {
                        $is_str++;
                    }
                }
                if ($is_array > 0 && $is_str > 0) {
                    foreach ($v['#'] as $subk => $subv) {
                        if (!is_array($subv)) {
                            unset($v['#'][$subk]);
                        }
                    }
                }
                if ($is_array > 0) {
                    $parsed[$k] = cw_xml2hash_postprocess($v['#']);
                } else {
                    $parsed[$k] = array_pop($v['#']);
                }
            } else {
                $parsed[$k] = $v['#'];
            }
        }
    } else {
        return array();
    }
    return $parsed;
}
function cw_shipper_CPC($weight, $customer_id, $address, $debug, $cart)
{
    global $config, $tables;
    if ($config['Company']['country'] != "CA" || empty($config['Shipping']['CPC_merchant_id'])) {
        return;
    }
    $cpc_methods = array();
    foreach ($allowed_shipping_methods as $v) {
        if ($v['code'] == "CPC") {
            $cpc_methods[] = $v;
        }
    }
    if (empty($cpc_methods)) {
        return;
    }
    $cp_merchant = $config['Shipping']['CPC_merchant_id'];
    $cp_language = "en";
    $cp_qnty = "1";
    $cp_packed = true;
    $cp_weight = round(cw_weight_in_grams($weight) / 1000, 3);
    if ($cp_weight < 0.1) {
        $cp_weight = 0.1;
    }
    $cp_description = $params['param00'];
    $cp_length = $params['param01'];
    $cp_width = $params['param02'];
    $cp_height = $params['param03'];
    $cp_currency_rate = $params['param05'];
    $cp_insured_value = $params['param04'];
    $cp_dest_country = $address['country'];
    $cp_dest_city = $address['city'];
    $cp_dest_zip = $address['zipcode'];
    $cp_dest_state = empty($address['state']) ? "NA" : $address['state'];
    $cp_orig_zip = $config['Company']['zipcode'];
    # Server DNS; if does not work, use 'cybervente.postescanada.ca:30000'
    $cp_host = "sellonline.canadapost.ca:30000";
    if (isset($cart['discounted_subtotal'])) {
        $itemsPrice = "<itemsPrice>{$cart['discounted_subtotal']}</itemsPrice>";
    } elseif (!empty($cp_insured_value)) {
        $itemsPrice = "<itemsPrice>{$cp_insured_value}</itemsPrice>";
    } else {
        $itemsPrice = "";
    }
    $cp_request = "<?xml version=\"1.0\" ?>\n" . "<eparcel>" . "<language>{$cp_language}</language>\n" . "<ratesAndServicesRequest>\n" . "  <merchantCPCID>{$cp_merchant}</merchantCPCID>\n" . "  <fromPostalCode>{$cp_orig_zip}</fromPostalCode>\n" . "  {$itemsPrice}\n" . "  <lineItems>\n" . "    <item>\n" . "      <quantity>{$cp_qnty}</quantity>\n" . "      <weight>{$cp_weight}</weight>\n" . "      <length>{$cp_length}</length>\n" . "      <width>{$cp_width}</width>\n" . "      <height>{$cp_height}</height>\n" . "      <description>{$cp_description}</description>\n" . ($cp_packed ? "      <readyToShip/>\n" : "") . "    </item>\n" . "  </lineItems>\n" . "  <city>{$cp_dest_city}</city>\n" . "  <provOrState>{$cp_dest_state}</provOrState>\n" . "  <country>{$cp_dest_country}</country>\n" . "  <postalCode>{$cp_dest_zip}</postalCode>\n" . "</ratesAndServicesRequest>\n" . "</eparcel>";
    $md5_request = md5($cp_request);
    if (!cw_is_shipping_result_in_cache($md5_request) || $debug == "Y") {
        list($a, $result) = cw_http_post_request($cp_host, "/", $cp_request);
        $parse_errors = false;
        $options = array('XML_OPTION_CASE_FOLDING' => 1, 'XML_OPTION_TARGET_ENCODING' => 'ISO-8859-1');
        $parsed = cw_xml_parse($result, $parse_errors, $options);
        $products =& cw_array_path($parsed, 'EPARCEL/RATESANDSERVICESRESPONSE/PRODUCT');
        if (is_array($products)) {
            foreach ($products as $product) {
                $pid = $product['@']['ID'];
                $rate = cw_array_path($product, 'RATE/0/#');
                if ($pid === false || $rate === false) {
                    continue;
                }
                $is_found = false;
                foreach ($cpc_methods as $v) {
                    if ($v['service_code'] == $pid) {
                        $rates[] = array("methodid" => $v['subcode'], "rate" => $rate * $cp_currency_rate);
                        $is_found = true;
                        break;
                    }
                }
                if (!empty($pid) && !$is_found) {
                    $tmp_name = cw_array_path($product, "NAME/0/#");
                    cw_add_new_smethod($tmp_name, "CPC", array("service_code" => $pid));
                }
            }
        }
        if ($debug != "Y") {
            cw_save_shipping_result_to_cache($md5_request, $rates);
        }
        $error_code = cw_array_path($parsed, 'EPARCEL/ERROR/STATUSCODE/0/#');
        if ($error_code !== false) {
            $error_msg = cw_array_path($parsed, 'EPARCEL/ERROR/STATUSMESSAGE/0/#');
        }
    } else {
        $rates = cw_get_shipping_result_from_cache($md5_request);
    }
}
function cw_shipper_USPS($weight, $customer_id, $address, $debug, $cart)
{
    global $config, $tables, $current_language;
    $USPS_username = $config['Shipping']['USPS_username'];
    $USPS_password = $config['Shipping']['USPS_password'];
    $USPS_servername = $config['Shipping']['USPS_servername'];
    $use_usps_https = false;
    if (empty($USPS_username) || empty($USPS_servername)) {
        return;
    }
    $USPS_FOUND = false;
    if (is_array($allowed_shipping_methods)) {
        foreach ($allowed_shipping_methods as $key => $value) {
            if ($value['code'] == "USPS") {
                $USPS_FOUND = true;
                break;
            }
        }
    }
    if (!$USPS_FOUND) {
        return;
    }
    cw_load('http', 'xml');
    $pounds = 0;
    $ounces = ceil(round(cw_weight_in_grams($weight) / 28.35, 3));
    if ($ounces < 1) {
        $ounces = 1;
    }
    $mailtype = $params['param00'];
    $package_size = $params['param01'];
    $machinable = $params['param02'];
    $container_express = $params['param03'];
    $container_priority = $params['param04'];
    if (!empty($container_express) && $container_express != 'None') {
        $container_express = "<Container>" . $container_express . "</Container>";
    } else {
        $container_express = "";
    }
    if (!empty($container_priority) && $container_priority != 'None') {
        $container_priority = "<Container>" . $container_priority . "</Container>";
    } else {
        $container_priority = "";
    }
    if ($address['country'] == 'PR' || $address['country'] == 'GU' || $address['country'] == 'VI') {
        $address['country'] = 'US';
    }
    $dst_country = USPS_get_country($address['country']);
    if (empty($dst_country)) {
        $dst_country = cw_query_first_cell("SELECT value FROM {$tables['languages']} WHERE name = 'country_" . $address['country'] . "' AND code = '{$current_language}'");
    }
    $USPS_file = $USPS_servername == "testing.shippingapis.com" ? "/ShippingAPITest.dll" : "/ShippingAPI.dll";
    $hash = array();
    if ($address['country'] != $config['Company']['country']) {
        # International shipping
        $query = <<<EOT
<IntlRateRequest USERID="{$USPS_username}" PASSWORD="******">
<Package ID="0">
<Pounds>{$pounds}</Pounds>
<Ounces>{$ounces}</Ounces>
<MailType>{$mailtype}</MailType>
<Country>{$dst_country}</Country>
</Package>
</IntlRateRequest>
EOT;
        $md5_request = md5($query);
        if (cw_is_shipping_result_in_cache($md5_request) && $debug != "Y") {
            $rates = cw_get_shipping_result_from_cache($md5_request);
            return;
        }
        if ($use_usps_https) {
            $post = array("API=IntlRate", "XML=" . urlencode($query));
            list($header, $result) = cw_https_request("GET", "https://" . $USPS_servername . ":443" . $USPS_file . "?API=IntlRate&XML=" . urlencode($query));
        } else {
            list($header, $result) = cw_http_get_request($USPS_servername, $USPS_file, "API=IntlRate&XML=" . urlencode($query));
        }
        $xml = cw_xml_parse($result, $err);
        # Get <Error> elemenet
        $err = cw_array_path($xml, "IntlRateResponse/Package/Error");
        if (empty($err)) {
            # Get <Service> elements
            $packages = cw_array_path($xml, "IntlRateResponse/Package/Service");
            if (!empty($packages) && is_array($packages)) {
                foreach ($packages as $p) {
                    # Get shipping method name
                    $sname = cw_array_path($p, "SvcDescription/0/#");
                    # Get rate
                    $rate = cw_array_path($p, "Postage/0/#");
                    # Get comment
                    #$comment = cw_array_path($p, "SvcCommitments/0/#");
                    if (empty($sname) || zerolen($rate)) {
                        continue;
                    }
                    # Define shipping method
                    $is_found = false;
                    foreach ($allowed_shipping_methods as $sm) {
                        if ($sm['code'] == "USPS" && $sm['destination'] == "I" && preg_match("/^" . preg_quote($sm['shipping'], "/") . "/S", "USPS " . $sname)) {
                            if (!in_array($sm['subcode'], $hash)) {
                                $rates[] = array("methodid" => $sm['subcode'], "rate" => $rate, "warning" => "");
                                $hash[] = $sm['subcode'];
                            }
                            $is_found = true;
                            break;
                        }
                    }
                    if (!$is_found) {
                        # Add new shipping method
                        cw_add_new_smethod("USPS " . $sname, "USPS", array("destination" => "I"));
                    }
                }
                if ($debug != "Y") {
                    cw_save_shipping_result_to_cache($md5_request, $rates);
                }
            }
        }
    } else {
        # Domestic shipping
        $ZO = $config['Company']['zipcode'];
        $ZD = $address['zipcode'];
        $query = <<<EOT
<RateV2Request USERID="{$USPS_username}">
\t<Package ID="0">
\t\t<Service>EXPRESS</Service>
\t\t<ZipOrigination>{$ZO}</ZipOrigination>
\t\t<ZipDestination>{$ZD}</ZipDestination>
\t\t<Pounds>{$pounds}</Pounds>
\t\t<Ounces>{$ounces}</Ounces>
\t\t{$container_express}
\t\t<Size>{$package_size}</Size>
\t</Package>
\t<Package ID="1">
\t\t<Service>FIRST CLASS</Service>
\t\t<ZipOrigination>{$ZO}</ZipOrigination>
\t\t<ZipDestination>{$ZD}</ZipDestination>
\t\t<Pounds>{$pounds}</Pounds>
\t\t<Ounces>{$ounces}</Ounces>
\t\t<Container>None</Container>
\t\t<Size>{$package_size}</Size>
\t</Package>
\t<Package ID="2">
\t\t<Service>PRIORITY</Service>
\t\t<ZipOrigination>{$ZO}</ZipOrigination>
\t\t<ZipDestination>{$ZD}</ZipDestination>
\t\t<Pounds>{$pounds}</Pounds>
\t\t<Ounces>{$ounces}</Ounces>
\t\t{$container_priority}
\t\t<Size>{$package_size}</Size>
\t</Package>
\t<Package ID="3">
\t\t<Service>PARCEL</Service>
\t\t<ZipOrigination>{$ZO}</ZipOrigination>
\t\t<ZipDestination>{$ZD}</ZipDestination>
\t\t<Pounds>{$pounds}</Pounds>
\t\t<Ounces>{$ounces}</Ounces>
\t\t<Container>None</Container>
\t\t<Size>{$package_size}</Size>
\t\t<Machinable>{$machinable}</Machinable>
\t</Package>
\t<Package ID="4">
\t\t<Service>BPM</Service>
\t\t<ZipOrigination>{$ZO}</ZipOrigination>
\t\t<ZipDestination>{$ZD}</ZipDestination>
\t\t<Pounds>{$pounds}</Pounds>
\t\t<Ounces>{$ounces}</Ounces>
\t\t<Container>None</Container>
\t\t<Size>{$package_size}</Size>
\t</Package>
\t<Package ID="5">
\t\t<Service>LIBRARY</Service>
\t\t<ZipOrigination>{$ZO}</ZipOrigination>
\t\t<ZipDestination>{$ZD}</ZipDestination>
\t\t<Pounds>{$pounds}</Pounds>
\t\t<Ounces>{$ounces}</Ounces>
\t\t<Container>None</Container>
\t\t<Size>{$package_size}</Size>
\t</Package>
\t<Package ID="6">
\t\t<Service>MEDIA</Service>
\t\t<ZipOrigination>{$ZO}</ZipOrigination>
\t\t<ZipDestination>{$ZD}</ZipDestination>
\t\t<Pounds>{$pounds}</Pounds>
\t\t<Ounces>{$ounces}</Ounces>
\t\t<Container>None</Container>
\t\t<Size>{$package_size}</Size>
\t</Package>
</RateV2Request>
EOT;
        $md5_request = md5($query);
        if (cw_is_shipping_result_in_cache($md5_request) && $debug != "Y") {
            $rates = cw_get_shipping_result_from_cache($md5_request);
            return;
        }
        if ($use_usps_https) {
            $post = array("API=RateV2", "XML=" . urlencode($query));
            list($header, $result) = cw_https_request("GET", "https://" . $USPS_servername . ":443" . $USPS_file . "?API=RateV2&XML=" . urlencode($query));
        } else {
            list($header, $result) = cw_http_get_request($USPS_servername, $USPS_file, "API=RateV2&XML=" . urlencode($query));
        }
        $xml = cw_xml_parse($result, $err);
        # Get <Package> elements
        $packages = cw_array_path($xml, "RateV2Response/Package");
        if (is_array($packages)) {
            foreach ($packages as $p) {
                # Get <Error> element
                $err = cw_array_path($p, "Error");
                if (!empty($err)) {
                    continue;
                }
                # Get shipping method name
                $sname = cw_array_path($p, "Postage/MailService/0/#");
                # Get rate
                $rate = cw_array_path($p, "Postage/Rate/0/#");
                if (empty($sname) || zerolen($rate)) {
                    continue;
                }
                # Define shipping method
                $is_found = false;
                foreach ($allowed_shipping_methods as $sm) {
                    if ($sm['code'] == "USPS" && $sm['destination'] == "L" && preg_match("/^" . preg_quote($sm['shipping'], "/") . "/S", "USPS " . $sname)) {
                        if (!in_array($sm['subcode'], $hash)) {
                            $rates[] = array("methodid" => $sm['subcode'], "rate" => $rate, "warning" => "");
                            $hash[] = $sm['subcode'];
                        }
                        $is_found = true;
                        break;
                    }
                }
                if (!$is_found) {
                    # Add new shipping method
                    cw_add_new_smethod("USPS " . $sname, "USPS", array("destination" => "L"));
                }
            }
            if ($debug != "Y") {
                cw_save_shipping_result_to_cache($md5_request, $rates);
            }
        }
        // if (is_array($packages))
    }
}