Support » Everything else WordPress » Bug: In “add_query_arg” with # vs. & ?

  • Hello,

    i don’t know if this is really a bug, but let me explain what I found out.

    I used the plugin “pagebar” ( to have a nicer paging, together with the “Event Calendar Plugin” ( The “Event Calendar Plugin” generates URLs like “?year=2007&monthnum=3&cat=2”. If the “pagebar” generates the “paginglinks” everything is okay. But on the next page (page 2) the link back to the first page is broken (from html sourcecode): “?year=2007#038;monthnum=3&cat=2&paged=1” – the first & before the #038 is missing (& = & = & = Ampersand). I looked into the code. In the plugin “pagebar” everything is okay. “pagebar” calls the wordpressfunction “get_pagenum_link” in “link-template.php”. I found out that in the function “get_pagenum_link” the url is always right – the & is still there:

    At the end of this function there is a if-statement:

    // showing /page/1/ or ?paged=1 is redundant
    	if ( 1 === $pagenum ) {
    		$qstr = str_replace('page/1/', '', $qstr); // for mod_rewrite style
    		$qstr = remove_query_arg('paged', $qstr); // for query style

    This is the reason why a link to page 2 is okay and a link to page 1 is not okay, because only a link to page 1 will call the function “remove_query_arg” in “functions.php”. “remove_query_arg” calls “add_query_arg”. And in that function at :

    if ( $frag = strstr($uri, '#') )
    		$uri = substr($uri, 0, -strlen($frag));
    		$frag = '';

    the “bug” happend, i guess. After this if-statement:

    $frag = “#038;monthnum=3&cat=2&paged=1”
    $uri = “”

    The function goes on by doing something with $uri and at the end of the last foreach:

    foreach($qs as $k => $v) {
    		if ( $v !== FALSE ) {
    			if ( $ret != '' )
    				$ret .= '&';
    			if ( empty($v) && !preg_match('|[?&]' . preg_quote($k, '|') . '=|', $query) )
    				$ret .= $k;
    				$ret .= "$k=$v";

    the value $ret = “year=2007”. $ret was set in the “else”, because the function do not find the word “paged” given from “get_pagenum_link” – I don’t understand the parameterpassing but my debugging let me guess that, and there is a comment in “get_pagenum_link” that told me that the reason for calling “remove_query_arg”/”add_query_arg” is to remove the queryparameter “paged”. But the function can not remove it, because the parameter is in $frag and the value of $frag is part of the new return url:

    $ret = $protocol . $base . $ret . $frag;

    And because of $ret = “year=2007” the & is missing.

    So my solution is this in “add_query_arg”:

    //if ( $frag = strstr($uri, '#') )
    	//	$uri = substr($uri, 0, -strlen($frag));
    $frag = '';

    The full url will be processed by the rest of the code and
    then the paging works fine. I still have the “paged=1” in the links, but that is not so bad.

    I think this bug is not only a problem with my combination of plugins. Everytime a url with a querystring where the “Ampersand” is escaped with the unicode dezimal code & and the function “add_query_arg” is called this will happend. And WP uses the code & at many positions in the code e.g. in the function “wp_specialchars” in “formating.php”.

    Thank you

  • The topic ‘Bug: In “add_query_arg” with # vs. & ?’ is closed to new replies.