1

With the following code I am redirecting user to a php script, where some actions are performed:

requestObject.queries = {
    lv   : searchQueryLV,
    desc : searchQueryDesc,
    ru   : searchQueryRU,
    oth  : searchQueryOth
};

var queryStr = $.param(requestObject);
location.replace('http://' + location.host + '/path/to/file.php?' + queryStr);

The problem is that the queryStr may contains some html special chars, like tags etc.

And when it contains them, my code fails. It ends up with the URL where the search part looks like that:

queryType=search&queries[lv]=<br>&queries[desc]=&queries[ru]=&queries[oth]=

I can't get, as you can see, I encode the queryString:

$.param(requestObject);

And when I console.log it, it is displayed as it must. But when I pass it to location.replace() it's a mess. I've tried building it manually, using JS native encodeURI, but that doesn't help.

I would be glad if you could help me with that.

VMAtm
  • 27,943
  • 17
  • 79
  • 125
noname
  • 551
  • 9
  • 29
  • What escpecially fails? The fact that you see the URL you've posted inside the adressbar doesn't have to mean that the URL isn't well-encoded, some browsers may show you the real characters while sending them encoded. – Dr.Molle Jul 15 '11 at 08:50
  • The php script is meant to put a file on download depending on the parameters provided, and then redirect back to the referrer. When I don't have special chars in URL, it works fine, when I do, it fails with a blank page. – noname Jul 15 '11 at 09:06
  • So please show us your php-scrript, I'm pretty sure the problem is not on the javascript-side. – Dr.Molle Jul 15 '11 at 09:12
  • @Dr.Molle You're right, I had a line in php script which stripped tags, so that the whole logic was failing. Thank you for your comments. – noname Jul 15 '11 at 10:36

3 Answers3

2

Use the encodeURIComponent function in Javascript on your queryStr to escape the characters that are not allowed in URLs that might be in your queryStr.

location.replace('http://' + location.host + '/path/to/file.php?' + encodeURIComponent(queryStr));

See this post for other info on the same topic.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

Try to use the encodeURIComponent function:

encodeURIComponent(queryStr);
VMAtm
  • 27,943
  • 17
  • 79
  • 125
  • 1
    As of Javascript 1.5, escape has been deprecated: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions. Use encodeURIComponent instead. – jfriend00 Jul 15 '11 at 08:31
0

Here is a jquery URLEncode/Decode Plugin: (i use it in my own projects)

/** --------------------------------------------------------------------------
 *  jQuery URL Decoder
 *  Version 1.0
 *  Parses URL and return its components. Can also build URL from components
 *  
 * ---------------------------------------------------------------------------
 *  HOW TO USE:
 *
 *  $.url.decode('http://username:password@hostname/path?arg1=value%40+1&arg2=touch%C3%A9#anchor')
 *  // returns
 *  // http://username:password@hostname/path?arg1=value@ 1&arg2=touché#anchor
 *  // Note: "%40" is replaced with "@", "+" is replaced with " " and "%C3%A9" is replaced with "é"
 *  
 *  $.url.encode('file.htm?arg1=value1 @#456&amp;arg2=value2 touché')
 *  // returns
 *  // file.htm%3Farg1%3Dvalue1%20%40%23456%26arg2%3Dvalue2%20touch%C3%A9
 *  // Note: "@" is replaced with "%40" and "é" is replaced with "%C3%A9"
 *  
 *  $.url.parse('http://username:password@hostname/path?arg1=value%40+1&arg2=touch%C3%A9#anchor')
 *  // returns
 *  {
 *      source: 'http://username:password@hostname/path?arg1=value%40+1&arg2=touch%C3%A9#anchor',
 *      protocol: 'http',
 *      authority: 'username:password@hostname',
 *      userInfo: 'username:password',
 *      user: 'username',
 *      password: 'password',
 *      host: 'hostname',
 *      port: '',
 *      path: '/path',
 *      directory: '/path',
 *      file: '',
 *      relative: '/path?arg1=value%40+1&arg2=touch%C3%A9#anchor',
 *      query: 'arg1=value%40+1&arg2=touch%C3%A9',
 *      anchor: 'anchor',
 *      params: {
 *          'arg1': 'value@ 1',
 *          'arg2': 'touché'
 *      }
 *  }
 *  
 *  $.url.build({
 *      protocol: 'http',
 *      username: 'username',
 *      password: 'password',
 *      host: 'hostname',
 *      path: '/path',
 *      query: 'arg1=value%40+1&arg2=touch%C3%A9',
 *      // or 
 *      //params: {
 *      //  'arg1': 'value@ 1',
 *      //  'arg2': 'touché'
 *      //}
 *      anchor: 'anchor',
 *  })
 *  // returns
 *  // http://username:password@hostname/path?arg1=value%40+1&arg2=touch%C3%A9#anchor   
 *  
 * ---------------------------------------------------------------------------
 * OTHER PARTIES' CODE:
 *
 * Parser based on the Regex-based URI parser by Steven Levithan.
 * For more information visit http://blog.stevenlevithan.com/archives/parseuri
 *
 * Deparam taken from jQuery BBQ by Ben Alman. Dual licensed under the MIT and GPL licenses (http://benalman.com/about/license/)
 * http://benalman.com/projects/jquery-bbq-plugin/
 *  
 * ---------------------------------------------------------------------------
*/
jQuery.url = function(){ 

    /**
     * private function to encode URL
     * 
     * @param {String} string //required
     * @return {String}
     */
    function utf8_encode(string) { 
        string = string.replace(/\r\n/g,"\n"); 
        var utftext = ""; 

        for (var n = 0; n < string.length; n++) { 

            var c = string.charCodeAt(n); 

            if (c < 128) { 
                utftext += String.fromCharCode(c); 
            } 
            else if((c > 127) && (c < 2048)) { 
                utftext += String.fromCharCode((c >> 6) | 192); 
                utftext += String.fromCharCode((c & 63) | 128); 
            } 
            else { 
                utftext += String.fromCharCode((c >> 12) | 224); 
                utftext += String.fromCharCode(((c >> 6) & 63) | 128); 
                utftext += String.fromCharCode((c & 63) | 128); 
            } 

        } 

        return utftext; 
    }

    /**
     * private function to decode URL
     * 
     * @param {String} utftext //required
     * @return {String}
     */
    function utf8_decode(utftext) { 
        var string = ""; 
        var i = 0; 
        var c = 0;
        var c2 = 0; 

        while ( i < utftext.length ) { 

            c = utftext.charCodeAt(i); 

            if (c < 128) { 
                string += String.fromCharCode(c); 
                i++; 
            } 
            else if((c > 191) && (c < 224)) { 
                c2 = utftext.charCodeAt(i+1); 
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); 
                i += 2; 
            } 
            else { 
                c2 = utftext.charCodeAt(i+1); 
                c3 = utftext.charCodeAt(i+2); 
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); 
                i += 3; 
            } 

        } 

        return string; 
    } 


    /**
     * private function to convert urlencoded query string to javascript object
     * 
     * @param {String} params //required
     * @param {Boolean} coerce //optional
     * @return {Object}
     *
     * @author Ben Alman
     */     
    function deparam(params, coerce) {
        var obj = {},
            coerce_types = {
            'true': !0,
            'false': !1,
            'null': null
        };

        // Iterate over all name=value pairs.
        $.each(params.replace(/\+/g, ' ').split('&'), function (j, v) {
            var param = v.split('='),
                key = decode(param[0]),
                val, cur = obj,
                i = 0,

            // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
            // into its component parts.
            keys = key.split(']['),
                keys_last = keys.length - 1;

            // If the first keys part contains [ and the last ends with ], then []
            // are correctly balanced.
            if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) {
                // Remove the trailing ] from the last keys part.
                keys[keys_last] = keys[keys_last].replace(/\]$/, '');

                // Split first keys part into two parts on the [ and add them back onto
                // the beginning of the keys array.
                keys = keys.shift().split('[').concat(keys);

                keys_last = keys.length - 1;
            } else {
                // Basic 'foo' style key.
                keys_last = 0;
            }

            // Are we dealing with a name=value pair, or just a name?
            if (param.length === 2) {
                val = decode(param[1]);

                // Coerce values.
                if (coerce) {
                    val = val && !isNaN(val) ? +val // number
                    : val === 'undefined' ? undefined // undefined
                    : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
                    : val; // string
                }

                if (keys_last) {
                    // Complex key, build deep object structure based on a few rules:
                    // * The 'cur' pointer starts at the object top-level.
                    // * [] = array push (n is set to array length), [n] = array if n is 
                    //   numeric, otherwise object.
                    // * If at the last keys part, set the value.
                    // * For each keys part, if the current level is undefined create an
                    //   object or array based on the type of the next keys part.
                    // * Move the 'cur' pointer to the next level.
                    // * Rinse & repeat.
                    for (; i <= keys_last; i++) {
                        key = keys[i] === '' ? cur.length : keys[i];
                        cur = cur[key] = i < keys_last ? cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? {} : []) : val;
                    }

                } else {
                    // Simple key, even simpler rules, since only scalars and shallow
                    // arrays are allowed.
                    if ($.isArray(obj[key])) {
                        // val is already an array, so push on the next value.
                        obj[key].push(val);

                    } else if (obj[key] !== undefined) {
                        // val isn't an array, but since a second value has been specified,
                        // convert val into an array.
                        obj[key] = [obj[key], val];

                    } else {
                        // val is a scalar.
                        obj[key] = val;
                    }
                }

            } else if (key) {
                // No value was defined, so set something meaningful.
                obj[key] = coerce ? undefined : '';
            }
        });

        return obj;
    }

     /**
     * private function to parse URL to components
     * 
     * @param {String} url_str //optional, if omited using current location
     * @return {Object}
     */     
    function parse(url_str) {
        url_str = url_str || window.location;

        /**
        * @author of RegExp Steven Levithan 
        */
        var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;

        var keys = ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];

        var m = re.exec( url_str );
        var uri = {};
        var i = keys.length;

        while ( i-- ) {
            uri[ keys[i] ] = m[i] || "";
        }
        /*
        uri.params = {};

        uri.query.replace( /(?:^|&)([^&=]*)=?([^&]*)/g, function ( $0, $1, $2 ) {
            if ($1) {
                uri.params[decode($1)] = decode($2);
            }
        });
        */
        if(uri.query){
            uri.params = deparam(uri.query,true);
        }

        return uri;
    }


     /**
     * private function to build URL string from components
     * 
     * @param {Object} url_obj //required
     * @return {String}
     */     
    function build(url_obj) {

        if (url_obj.source){
            return encodeURI(url_obj.source);
        }

        var resultArr = [];

        if (url_obj.protocol){
            if (url_obj.protocol == 'file'){
                resultArr.push('file:///');
            } else if (url_obj.protocol == 'mailto'){
                resultArr.push('mailto:');
            } else {
                resultArr.push(url_obj.protocol + '://');
            }
        }

        if (url_obj.authority){
            resultArr.push(url_obj.authority);
        } else {
            if (url_obj.userInfo){
                resultArr.push(url_obj.userInfo + '@');
            } else if(url_obj.user){
                resultArr.push(url_obj.user);
                if(url_obj.password){
                    resultArr.push(':' + url_obj.password);
                }
                resultArr.push('@');
            }

            if (url_obj.host){
                resultArr.push(url_obj.host);
                if(url_obj.port){
                    resultArr.push(':' + url_obj.port);
                }
            }
        }

        if (url_obj.path){
            resultArr.push(url_obj.path);
        } else {
            if(url_obj.directory){
                resultArr.push(url_obj.directory);
            }
            if(url_obj.file){
                resultArr.push(url_obj.file);
            }

        }

        if (url_obj.query){
            resultArr.push('?' + url_obj.query);
        } else  if(url_obj.params){
            resultArr.push('?' + $.param(url_obj.params));
        }

        if (url_obj.anchor){
            resultArr.push('#' + url_obj.anchor);
        }

        return resultArr.join('');
    }

    /**
     * wrapper around encoder
     * 
     * @param {String} string //required
     * @return {String}
     */     
    function encode(string) { 
        //return build(parse(string));
        //return escape(utf8_encode(string));
        return encodeURIComponent(string);
    } 

    /**
     * wrapper around decoder
     * 
     * @param {String} string //optional, if omited using current location
     * @return {String}
     */     
    function decode(string) { 
        string = string ||  window.location.toString();
        return utf8_decode(unescape(string.replace(/\+/g, ' '))); 
    }

    /**
     * public functions
     * 
     * @see #encode
     * @see #decode
     * @see #parse
     * @see #build
     *
     * @return {Object}
     */     
    return {
        encode: encode,
        decode: decode,
        parse: parse,
        build: build
    };
}();
VMAtm
  • 27,943
  • 17
  • 79
  • 125