The drupal_get_destination / drupal_goto mechanism doesn't work when the destination contains query parameters.

Example : on content admin page ('admin/node'), go to page 2 (if you have enough nodes...),
and go 'edit' a node. When you submit the form, you are not redirected where you should be...

The 'destination' is handled in drupal_goto by (approx) the following code :

extract(parse_url($_REQUEST['destination']));
...
$url = url($path, $query, $fragment, TRUE);

drupal_get_destination, builds a value for the 'destination' param like :
the/path/goes/here&param1=value1&param2=value2

When ran through parse_url, this value gives

Array
(
    [path] => the/path/goes/here&param1=value1&param2=value2
)

The query part is left in $path, and then the 'url' function messes with it...

In order for the query part to be recognized, drupal_get_destination should build a value like :
the/path/goes/here?param1=value1&param2=value2
(note the ? instead of & after 'the/path/goes/here').

So that parse_url correctly parses :

Array
(
    [path] => the/path/goes/here
    [query] => param1=value1&param2=value2
)
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yched’s picture

Probably not critical, though... Sorry about that.

yched’s picture

Priority: Critical » Normal
Bèr Kessels’s picture

Priority: Normal » Critical

It is critical, because it causes a lot of links to no longer work.

Another example is the admin/path/delete/54?destination=admin%2Fpath deletion. It is no longer possible to delete paths, without hacking the url. Instead you get a blank page.

Bèr Kessels’s picture

Status: Active » Needs work

Looking at the patch. It works. And it looks good.
however: + $querystring = (!empty($query)) ? ('?'.implode('&', $query)) : ''; is undrupalish.
We try to avoid one-line conditions at all costs (well... allmost).

Bèr Kessels’s picture

Status: Needs work » Needs review
FileSize
935 bytes
yched’s picture

Right, I wasn't aware of the 'one-line condition' reluctance :-)

BTW, does anyone know a good reason why 'drupal_get_destination' only keeps the 'pager query params' ?

$params = array('page', 'sort', 'order');
foreach ($params as $param) {
    if (isset($_GET[$param])) {
        ...
    }
}

Why not take all the parameters of the current url ? I needed that feature and I hade to code my own 'my_drupal_get_destination' in a module somewhere - which makes me... not so happy...

I could provide a patch for that too, but there has to be a reason in the first place ?

Dries’s picture

Status: Needs review » Needs work

It would be nice if drupal_get_destination were more generic. I guess that might solve the problem more elegantly?

The coding style of Ber's patch needs work: missing spaces.

yched’s picture

Dries : It would be nice if drupal_get_destination were more generic. I guess that might solve the problem more elegantly?
I'm not sure what you mean by that.
If it's : "let's include all query params in the destination (and not only the pager ones)", well, the included patch does that.
(But then again, maybe i'm just happily interpreting your post according to my own wishes :-)

This patch also corrects missing spaces (well I think it does ?).

BTW, I hadn't noticed Ber made a mistake translating my one-liner conditional into a proper if statement :
if(empty($query)) {...
should be :
if(!empty($query)) {...

rmiotke’s picture

FileSize
660 bytes

i had to patch (or at least i think i had to) drupal_goto to check for destination ($_REQUEST['destination'] and $_REQUEST['edit']['destination']) via isset, rather than with shorthand true/false.

the problem--at least with logintoboggan access denied login pages enabled, and with anonymous access totally disallowed, and destination slated for drupal root--is that drupal root (ie, null) would get interpreted as false and hence cause redirect to user page upon successful login. (why, anyway, by the way, is a user profile page considered a better failover redirect than home? i'm assuming there's a good reason.)

i'm attaching my little patch here, but maybe just be included in this other stuff? unless of course i'm totally wrong.

Bèr Kessels’s picture

rmiotke, is your patch replacnig the one by yched? I fail to see how your patch fixes this issue.

yched, your patch seems to work, I tested it on a clean site.
But, I am wondering if we need not add a line to legacy.module?

yched’s picture

rmiotke's patch is a separate point. I have no opinion about it being an issue or not, but it should IMO have its own thread.

As for legacy.module : well, I've only been hanging around drupal for a few months, so I guess I'm too much of a drupal noob to be aware of legacy issues.

yched’s picture

Status: Needs work » Needs review

forgot to update status...

rmiotke’s picture

posted my issue under separate cover. sorry for muddying the waters ....

Dries’s picture

Code looks good. Needs some testing though.

yched’s picture

I feel I should stress the fact the my patch actually does two different things :

  1. correct a bug that was stopping the redirection mechanism from working in some (non rare) cases.
    I think it does that allright, more reviews are welcome.
  2. On Ber's request (or at least the way I understood his comment), it also modifies the extent to which query params in the curent url are mirrored in the destination url.
    Previous behaviour : only params generated by a pager (namely 'page', 'sort' and 'order') are mirrored
    Patch behaviour : all the params (except 'q'...) are mirrored.

    I like (and I need..) this new behaviour, but I can't help but thinking that maybe there was a good reason for this "pager-limited" destination thing, even if I can't think of any. Like, "too easy"...

    So : reviews AND historical point of views are welcome

yched’s picture

Mistake. I meant "On Dries's request...". Sorry.

ebruts’s picture

Assigned: Unassigned » ebruts
FileSize
1.02 KB

I was about to address the very same issue and just found this.

The supplied patch almost do the job but keep in mind that a param can already be encoded. Like

http://drupal.org/node?key1=val%26ue2&key2=value2 (%26 is &)

Inside the $_GET array it will appear as decoded and so $_GET['key1'] is 'val&ue2'.

This will encode into
"destination=node%3Fkey1%3Dval%26ue2%26key2%3Dvalue2"
but it should really be
"destination=node%3Fkey1%3Dval%2526ue2%26key2%3Dvalue2"

ebruts’s picture

FileSize
1.03 KB

Just noticed that I forgot the urlencode() around the key.

moshe weitzman’s picture

i can't seem to reproduce this. i clicked on 'edit' from the 2nd page of admin/node and admin/comment and arrived back at my destination correctly. how are you guys seeing this?

i can't recall why i limited the destination handling to just tablesort and pager variables. i might have been trying to simplify some urlencoding issue? seems correct to just pass along all querystring params. note the array2uri function proposed at http://drupal.org/node/5371

moshe weitzman’s picture

with clean urls disabled, i can now reproduce this. i will review the patch this weekend.

ebruts’s picture

Actually this applies to both, clean and non-clean urls. It just "works" with clean urls because it is rewritten by mod_rewrite (more on this later).

You can reproduce this with a fresh installation, at last 1 node and clean urls enabled.

1. Get and install the cvs.
2. Add a story with non-sense content.
3. Open http://example.com/admin/node?page=2 (there is no second page but it does not matter for the test).
4. Click "edit" your node you just created. This will open the page
   http://example.com/node/1/edit?destination=admin%2Fnode%26page%3D2
5. Save the node. This will redirect you to
   http://example.com/admin/node%26page%3D2
      but it should redirect to
   http://example.com/admin/node?page=2

It just works with http://example.com/admin/node%26page%3D2 because mod_rewrite calls the index.php with ?q=admin/node&page=2. Whereas the uri in the browser is still wrong!

For non-clean urls the current method does not work at all because after you save the node it will redirect you to

?q=admin/node%26page%3D2

which does not contain any other arguments except 'q' and therefore e.g. the pager will not be able to access $_GET['pager'].

The submitted patch fixes both, clean and non-clean urls. (Where clean urls work without the patch, too, but look worse in the url textfield of your browser).

ebruts’s picture

There are at the moment 2 related reports.

http://drupal.org/node/43301
http://drupal.org/node/51258

ebruts’s picture

Note: #51258 is not related, it was just in my clipboard so I thought it was.

moshe weitzman’s picture

Status: Needs review » Reviewed & tested by the community

verified that this patch fixes the issue. code looks reasonable.

killes@www.drop.org’s picture

Status: Reviewed & tested by the community » Fixed

applied.

Anonymous’s picture

Status: Fixed » Closed (fixed)