function cw_fedex_prepare_dimensions_xml($pack, $fedex_options)
{
    global $config;
    if ($fedex_options['packaging'] == 'YOUR_PACKAGING') {
        $dims = array($pack['length'], $pack['width'], $pack['height']);
        foreach ($dims as $k => $v) {
            //              $dims[$k] = $v;
            $dims[$k] = intval(cw_units_convert(cw_dim_in_centimeters($v), 'cm', $config['General']['dim_units'], 1));
        }
        list($dim_length, $dim_width, $dim_height) = $dims;
        $dimensions_xml = <<<OUT
    <q0:Dimensions>
        <q0:Length>{$dim_length}</q0:Length>
        <q0:Width>{$dim_width}</q0:Width>
        <q0:Height>{$dim_height}</q0:Height>
        <q0:Units>IN</q0:Units>
    </q0:Dimensions>
OUT;
    } else {
        $dimensions_xml = '';
    }
    return $dimensions_xml;
}
function cw_ups_shipping_get_rates($params, $return)
{
    global $config;
    global $ups_services;
    if (empty($config['shipping_ups']['username']) || empty($config['shipping_ups']['password']) || empty($config['shipping_ups']['accesskey'])) {
        return $return;
    }
    extract($params);
    $weight_condition = "weight_min<='{$weight}' AND (weight_limit='0' OR weight_limit>='{$weight}')";
    $shipping = cw_func_call('cw_shipping_search', array('data' => array('active' => 1, 'addon' => 'shipping_ups', 'where' => array($weight_condition))));
    if (!$shipping) {
        return $return;
    }
    $ups_parameters = $config['shipping_ups'];
    switch ($ups_parameters['account_type']) {
        case "01":
            $ups_parameters['customer_classification_code'] = "01";
            $ups_parameters['pickup_type'] = "01";
            break;
        case "02":
            $ups_parameters['customer_classification_code'] = "03";
            $ups_parameters['pickup_type'] = "03";
            break;
        case "03":
        default:
            $ups_parameters['customer_classification_code'] = "04";
            $ups_parameters['pickup_type'] = "11";
    }
    $src_country_code = $from_address['country'];
    $src_city = cw_ups_xml_quote($from_address['city']);
    $src_zipcode = $from_address['zipcode'];
    $dest_code = $dst_country_code = $to_address['country'];
    if ($to_address['state'] == "PR" || $to_address['state'] == "VI") {
        $dest_code = $dst_country_code = $to_address['state'];
    }
    $dst_city = cw_ups_xml_quote($to_address['city']);
    $dst_zipcode = $to_address['zipcode'];
    if ($src_country_code == "US" && !empty($ups_parameters['customer_classification_code'])) {
        $customer_classification_code = $ups_parameters['customer_classification_code'];
        $customer_classification_query = <<<EOT
    <CustomerClassification>
        <Code>{$customer_classification_code}</Code>
    </CustomerClassification>
EOT;
    }
    #
    # Pickup Type and Packaging Type
    #
    $pickup_type = $ups_parameters['pickup_type'];
    $packaging_type = $ups_parameters['packaging_type'];
    $insvalue = round(doubleval($ups_parameters['iv_amount']), 2);
    $pkgopt = array();
    if ($insvalue > 0.1) {
        $pkgopt[] = <<<EOT
                <InsuredValue>
                    <CurrencyCode>{$ups_parameters['iv_currency']}</CurrencyCode>
                    <MonetaryValue>{$insvalue}</MonetaryValue>
                </InsuredValue>

EOT;
    }
    $delivery_conf = intval($ups_parameters['delivery_conf']);
    if ($delivery_conf > 0 && $delivery_conf < 4) {
        $pkgopt[] = <<<EOT
                <DeliveryConfirmation>
                    <DCISType>{$delivery_conf}</DCISType>
                </DeliveryConfirmation>

EOT;
    }
    $codvalue = round(doubleval($ups_parameters['codvalue']), 2);
    $cod_is_allowed = false;
    $cod_is_allowed |= ($src_country_code == "US" || $src_country_code == "PR") && ($dst_country_code == "US" || $dst_country_code == "PR");
    $cod_is_allowed |= $src_country_code == "CA" && ($dst_country_code == "US" || $dst_country_code == "CA");
    if ($cod_is_allowed && $codvalue > 0.1) {
        $pkgopt[] = <<<EOT
                <COD>
                    <CODCode>3</CODCode>
                    <CODFundsCode>{$ups_parameters['cod_funds_code']}</CODFundsCode>
                    <CODAmount>
                        <CurrencyCode>{$ups_parameters['cod_currency']}</CurrencyCode>
                        <MonetaryValue>{$codvalue}</MonetaryValue>
                    </CODAmount>
                </COD>

EOT;
    }
    $pkgparams = count($pkgopt) > 0 ? "\t\t\t<PackageServiceOptions>\n" . join("", $pkgopt) . "\t\t\t</PackageServiceOptions>\n" : "";
    $srvopts = array();
    if ($ups_parameters['options']) {
        foreach ($ups_parameters['options'] as $opt) {
            switch ($opt) {
                case "AH":
                    $pkgparams .= "\t\t\t<AdditionalHandling/>";
                    break;
                case "SP":
                    $srvopts[] = "\t\t\t<SaturdayPickupIndicator/>\n";
                    break;
                case "SD":
                    $srvopts[] = "\t\t\t<SaturdayDeliveryIndicator/>\n";
                    break;
            }
        }
    }
    if (!empty($ups_parameters['shipper_number'])) {
        $shipper_number_xml = <<<EOT
            <ShipperNumber>{$ups_parameters['shipper_number']}</ShipperNumber>
EOT;
    } else {
        $shipper_number_xml = "";
    }
    if (count($srvopts) > 0) {
        $shipment_options_xml .= "\t\t<ShipmentServiceOptions>\n" . join("", $srvopts) . "\t\t</ShipmentServiceOptions>";
    }
    $weight = cw_units_convert(cw_weight_in_grams($weight), "g", "lbs", 1);
    if (!$weight) {
        $weight = 0.1;
    }
    // Fill the packages
    $packages_xml = '';
    $packages = cw_call('cw_shipping_get_packages', array($params));
    foreach ($packages as $pack) {
        $packages_xml .= <<<EOT
        <Package>
            <PackagingType>
                <Code>{$packaging_type}</Code>
            </PackagingType>
            <PackageWeight>
                <UnitOfMeasurement>
                    <Code>LBS</Code>
                </UnitOfMeasurement>
                <Weight>{$pack['weight']}</Weight>
            </PackageWeight>
    {$dimensions_query}
    {$pkgparams}
        </Package>

EOT;
    }
    $query = <<<EOT
<?xml version='1.0'?>
<AccessRequest xml:lang='en-US'>
    <AccessLicenseNumber>{$config['shipping_ups']['accesskey']}</AccessLicenseNumber>
    <UserId>{$config['shipping_ups']['username']}</UserId>
    <Password>{$config['shipping_ups']['password']}</Password>
</AccessRequest>
<?xml version='1.0'?>
<RatingServiceSelectionRequest xml:lang='en-US'>
    <Request>
        <TransactionReference>
            <CustomerContext>Rating and Service</CustomerContext>
            <XpciVersion>1.0001</XpciVersion>
        </TransactionReference>
        <RequestAction>Rate</RequestAction>
        <RequestOption>shop</RequestOption>
    </Request>
    <PickupType>
        <Code>{$pickup_type}</Code>
    </PickupType>
{$customer_classification_query}
    <Shipment>
        <Shipper>
{$shipper_number_xml}
            <Address>
                <City>{$src_city}</City>
                <PostalCode>{$src_zipcode}</PostalCode>
                <CountryCode>{$src_country_code}</CountryCode>
            </Address>
        </Shipper>
        <ShipFrom>
            <Address>
                <City>{$src_city}</City>
                <PostalCode>{$src_zipcode}</PostalCode>
                <CountryCode>{$src_country_code}</CountryCode>
            </Address>
        </ShipFrom>
        <ShipTo>
            <Address>
                <City>{$dst_city}</City>
                <PostalCode>{$dst_zipcode}</PostalCode>
                <CountryCode>{$dst_country_code}</CountryCode>
            </Address>
        </ShipTo>
{$packages_xml}
{$shipment_options_xml}       
    </Shipment>
</RatingServiceSelectionRequest>
EOT;
    $parsed = cw_ups_process($query, 'Rate');
    $ups_rates = array();
    $error['code'] = cw_array_path($parsed, 'RATINGSERVICESELECTIONRESPONSE/RESPONSE/ERROR/ERRORCODE/0/#');
    if ($error['code']) {
        $error['msg'] = cw_array_path($parsed, 'RATINGSERVICESELECTIONRESPONSE/RESPONSE/ERROR/ERRORDESCRIPTION/0/#');
    } else {
        $origin_code = cw_ups_get_origin_code($src_country_code);
        $dest_code = cw_ups_get_origin_code($dest_code);
        $entries = cw_array_path($parsed, 'RATINGSERVICESELECTIONRESPONSE/RATEDSHIPMENT');
        if (is_array($entries)) {
            foreach ($entries as $k => $entry) {
                $service_type = intval(cw_array_path($entry, 'SERVICE/CODE/0/#'));
                # kornev, don't use that for now
                //              $estimated_time = cw_array_path($entry, 'GUARANTEEDDAYSTODELIVERY/0/#');
                if ($estimated_time) {
                    $curtime = time();
                    $_time = strtotime($estimated_time);
                    if ($_time > $curtime) {
                        $estimated_time = ceil(($_time - $curtime) / 86400);
                    } else {
                        $estimated_time = 0;
                    }
                } else {
                    $estimated_time = 0;
                }
                $estimated_rate = cw_array_path($entry, 'TOTALCHARGES/MONETARYVALUE/0/#');
                if ($ups_services[$service_type][$origin_code]) {
                    if ($service_type == '11' && $origin_code == 'US' && $dest_code == 'CA') {
                        $service_type = '110';
                    } elseif ($service_type == '65') {
                        if ($origin_code == 'US' || $origin_code == 'PR') {
                            $service_type = '145';
                        } elseif ($origin_code == 'CA' && ($dest_code == 'US' || $dest_code == 'CA') || $origin_code == 'EU' && $dest_code == 'EU') {
                            $service_type = '146';
                        } else {
                            $service_type = '144';
                        }
                        // UPS Worldwide Express Saver (SM)
                    } else {
                        $service_type = $ups_services[$service_type][$origin_code];
                    }
                }
                $ups_rates[$service_type] = array('original_rate' => $estimated_rate, 'shipping_time' => $estimated_time);
            }
        }
    }
    if ($ups_rates) {
        foreach ($shipping as $sh) {
            if (!$ups_rates[$sh['code']]) {
                continue;
            }
            $sh = array_merge($sh, $ups_rates[$sh['code']]);
            $return[$sh['shipping_id']] = $sh;
        }
    }
    return $return;
}