简体   繁体   中英

Issue with urlencode

I have a problem with encoding ampersand in a filtering system.
If for example the first filter is for brands and the brand name is 'Head & Shoulders', the url should look like website/category/brand-head+%26+shoulders, but the filter works only if the url is website/category/brand-head-%252526+shoulders.
If there is another filter selected for example height the brand filter works if the url is website/category/brand-head-%25252526+shoulders and so on i have to add another 25 before percentage sign.

This is brand filter code

if($brand == false){
    $data['brands'] = array();
    $brands         = $attributes->getBrands($av_list, $_GET['c']);
    $brandTotalCnt  = 0;

    if(!empty($brands)){
        foreach ($brands as &$brand) {
            if($av_list){
                $cur_av_list  = $av_list  . $brand['brand'];
                $cur_av_uri   = $_GET['av'] . $brand['brand'];
            } else {
                $cur_av_list  = $brand['brand'];
                $cur_av_uri   = $brand['brand'];
            }
            $tmp_uri          = explode('/', $ln_uri);
            $tmp_uri_array    = $attributes->remove_items_by_value($tmp_uri, 'brand');
            $new_uri          = implode('/', $tmp_uri_array);   
            $brandTotalCnt   += $brand['num'];

            $data['brands'][] = array(
                    'brand'           => ucwords(strtolower($brand['brand'])),
                    'num'             => $brand['num'],
                    'href'            => $url->link('/c/'.$_GET['c'], '/brand-'. urlencode(strtolower($brand['brand'].'1')). $new_uri)
                );

        }
    }
    $data['brandTotalCnt'] = $brandTotalCnt;
}

Urldecode for every filter

if(isset($brand)){
    $sql .= " AND brand = '".urldecode($brand)."'";
}

if(isset($gramaj)){
    $height= $_GET['height'];
    $sql .= " AND height= '".urldecode($height)."'";
}

This is from my htaccess

# rewrite /category/brand-mybrand/country-mycountry/offer-yes/new-yes
# to /index.php/brand-mybrand/country-mycountry/offer-yes/new-yes?c=category
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^c/([^/]+)/([^-]+.+)/?$ /index.php/$2?c=$1 [L,QSA]

# rewrite /index.php/brand-mybrand/country-mycountry/offer-yes/new-yes?c=category
# converts any /name-val/ to query parameter name=val in every rewrite
# stopping when there is no part left after /index.php
RewriteRule ^(index\.php)/([^-]+)-([^/]+)(/.*)?$ /$1$4?$2=$3 [L,QSA]

PHP automatically parses the query string and URL-decodes the values during startup, when it populates $_GET[] .

It's correct to urlencode() the values when you generate an URL but you must not urldecode() the values you pick from $_GET[] .

Update:

As it is explained in the Apache documentation :

mod_rewrite has to unescape URLs before mapping them, so backreferences are unescaped at the time they are applied

If your rewrite rule takes a part of the path and puts it into the query string, the flag [B] (escape backreferences) instructs the engine to use the unescaped URL to match the rule.

You have two solutions for your problem:

  1. (the simple solution): generate the URLs to not contain non-alphanumeric characters; use only letters, digits and dash ( - ) and you are safe;
  2. (the advanced solution): add the [B] flag to the affected rewrite rules:

     RewriteRule ^c/([^/]+)/([^-]+.+)/?$ /index.php/$2?c=$1 [L,QSA,B] 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM