I use the faceted_search module on my site. You can search the site by using the facets of the search which creates an URL like this:
http://localhost/en/facetsearch/results/author:1
If the user then wants to login, the function drupal_get_destination is used and the URL of the login page looks like this:
http://localhost/en/login?destination=facetsearch%2Fresults%2Fauthor%3A1

That's all right. But then in drupal_goto, the destination URL gets decoded: facetsearch/results/author:1
and parsed: host: facetsearch, port: 1, path: /results/author:1

The path is used for the redirect and leads to a page not found error. If I have a faceted search parameter like city:"munich" there is no problem, the URL doesn't get split. It seams that parse_url declares the value of the parameter author as port. On php.net/parse_url site there is a note that this function doesn't work with relative URLs.

This might be no Faceted Search Issue, but maybe somebody her already knows what to do.

Comments

john morahan’s picture

Project: Faceted Search » Drupal core
Version: 5.x-1.0-beta3 » 7.x-dev
Component: Miscellaneous » base system
Category: support » bug

I just ran into the same issue with logintoboggan for D6 - it's a core bug IMO; drupal_goto should not use parse_url on a relative URL if php.net says it doesn't work.

This would have to be fixed in D7 first and backported, I think. I will try to provide a patch soon if nobody else does.

john morahan’s picture

Status: Active » Needs work
StatusFileSize
new851 bytes

Here's the beginnings of one idea. Needs a test.

john morahan’s picture

Status: Needs work » Needs review
StatusFileSize
new2.22 KB
catch’s picture

Does this only ever need to be run in drupal_goto(), if there's other use cases, should we make drupal_parse_url() or similar?

john morahan’s picture

Status: Needs review » Needs work

Hmm, good point. A quick grep of core reveals 8 more references to parse_url(). Most of them are probably legitimate (i.e. expect a full URL), but the one in menu.admin.inc looks suspicious -- and sure enough, try to add a menu link to node/add/page?test=foo:/:bar and you get an error "The path '/add/page' is either invalid or you do not have access to it."

john morahan’s picture

Status: Needs work » Needs review
StatusFileSize
new3.26 KB
john morahan’s picture

Hmm, one unintended consequence of this is that drupal_goto will now happily redirect to an absolute URL in the destination. Not sure if that's a good thing or a bad thing.

coltrane’s picture

@John Morahan, I think its a good thing and I haven't heard any reason so far it'd be a problem. This dev list thread is relevant: http://lists.drupal.org/pipermail/development/2008-May/029772.html

coltrane’s picture

frankcarey’s picture

+1 I would like to see this!

Status: Needs review » Needs work

The last submitted patch failed testing.

john morahan’s picture

Status: Needs work » Needs review

suspected test bot failure

Mark Theunissen’s picture

I have also just encountered this bug in Drupal 6 using the Menu module. Unable to create a link to a URL with a colon in it. +1 from me!

cburschka’s picture

Status: Needs review » Needs work
preg_match('/^([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/', $url, $matches);
$parts['path'] = $matches[1];

You can't execute a regular expression and then use the match groups without first checking if the expression matched. If the expression didn't match, you will see notices about $matches[1] not being defined.

What you need is

if (preg_match('/^([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/', $url, $matches)) {
  $parts['path'] = $matches[1];
  // ...
}
else {
  // error-handling - maybe return null or something.
}
john morahan’s picture

How would it not match?

cburschka’s picture

Status: Needs work » Needs review

/^([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/

Oh, whoops. I misread a part of it (regexes are my personal nemesis). Yes, it seems that this pattern should match any string, so a check probably isn't required.

john morahan’s picture

Status: Needs review » Needs work

The last submitted patch failed testing.

c960657’s picture

See #553262: Make getAbsoluteURL() standard compliant that suggests a new function, drupal_parse_url(), that supports parsing relative URLs.

willmoy’s picture

#203571: Custom logout redirects to external sites depends on this issue. Seems like we could solve the open redirect issue by adding an argument $external = FALSE to drupal_goto(), which was only overridden to permit external redirects in suitable contexts.

c960657’s picture

Status: Needs work » Fixed

I believe this has been fixed in #578520: Make $query in url() only accept an array.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

fizk’s picture

Status: Closed (fixed) » Needs work

I'm not sure how this was fixed by #578520: Make $query in url() only accept an array.

I'm trying to use login_destination to redirect from an SSL login page to a NON-SSL front page. Using "http://www.example.com" isn't working because of this bug.

chrisns’s picture

Version: 7.x-dev » 6.22
Status: Needs work » Needs review
StatusFileSize
new623 bytes

patches above didn't work for me, at least not with drupal 6.22 so made this one that does based on the one in comment 2

Status: Needs review » Needs work

The last submitted patch, 337261-parse_url_in_drupal_goto.patch, failed testing.

kleinmp’s picture

Version: 6.22 » 7.x-dev

Yes, this still seems to be an issue in Drupal 7 as it is noted in drupal_parse_url() that 'relative URL "foo/bar:1" isn't properly parsed'.

BassistJimmyJam’s picture

Status: Needs work » Needs review

#6: drupal_goto-parse_url.patch queued for re-testing.

neilt17’s picture

Issue summary: View changes

Just in case anyone still needs to fix this issue when using Faceted Search in Drupal 6, just appending a dot to the destination url on login where there is just one taxonomy term on the url does it. So you could do this (a bit of a hack really):

<?php

/**
 * Implementation of hook_user
 *
 */
function mymodule_user($op, &$edit, &$account, $category = NULL) {
  if ($op == 'login') {
    if (preg_match('@^.+/taxonomy:[0-9]+$@', $_REQUEST['destination'])) {
      $_REQUEST['destination'] = $_REQUEST['destination'] . '.';
    }
  }
}



?>

Status: Needs review » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.