1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-25 15:00:58 +01:00

Fix /tag/aa%20bb project URIs

Summary:
Ref T9551. To set things up:

  - Name a project `aa bb`. This will have the tag `aa_bb`.
  - Try to visit `/tag/aa%20bb`.

Here's what happens now:

  - You get an Aphront redirect error as it tries to add the trailing `/`. Add `phutil_escape_uri()` so that works again.
  - Then, you 404, even though this tag is reasonably equivalent to the real project tag and could be redirected. Add a fallback to lookup, resolve, and redirect if we can find a hit for the tag.

This also fixes stuff like `/tag/AA_BB/`.

Test Plan: Visited URIs like `/tag/aa%20bb`, `/tag/aa%20bb/`, `/tag/Aa_bB/`, etc. None of them worked before and now they all do.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9551

Differential Revision: https://secure.phabricator.com/D14260
This commit is contained in:
epriestley 2015-10-12 17:02:42 -07:00
parent 1bdf225354
commit 3ff5ca789a
4 changed files with 49 additions and 4 deletions

View file

@ -372,6 +372,13 @@ abstract class AphrontApplicationConfiguration extends Phobject {
$result = $this->routePath($maps, $path.'/'); $result = $this->routePath($maps, $path.'/');
if ($result) { if ($result) {
$slash_uri = $request->getRequestURI()->setPath($path.'/'); $slash_uri = $request->getRequestURI()->setPath($path.'/');
// We need to restore URI encoding because the webserver has
// interpreted it. For example, this allows us to redirect a path
// like `/tag/aa%20bb` to `/tag/aa%20bb/`, which may eventually be
// resolved meaningfully by an application.
$slash_uri = phutil_escape_uri($slash_uri);
$external = strlen($request->getRequestURI()->getDomain()); $external = strlen($request->getRequestURI()->getDomain());
return $this->buildRedirectController($slash_uri, $external); return $this->buildRedirectController($slash_uri, $external);
} }

View file

@ -26,9 +26,16 @@ final class PhabricatorProjectViewController
} }
$project = $query->executeOne(); $project = $query->executeOne();
if (!$project) { if (!$project) {
return new Aphront404Response();
// If this request corresponds to a project but just doesn't have the
// slug quite right, redirect to the proper URI.
$uri = $this->getNormalizedURI($slug);
if ($uri !== null) {
return id(new AphrontRedirectResponse())->setURI($uri);
} }
return new Aphront404Response();
}
$columns = id(new PhabricatorProjectColumnQuery()) $columns = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer) ->setViewer($viewer)
@ -53,4 +60,31 @@ final class PhabricatorProjectViewController
return $this->delegateToController($controller_object); return $this->delegateToController($controller_object);
} }
private function getNormalizedURI($slug) {
if (!strlen($slug)) {
return null;
}
$normal = PhabricatorSlug::normalizeProjectSlug($slug);
if ($normal === $slug) {
return null;
}
$viewer = $this->getViewer();
// Do execute() instead of executeOne() here so we canonicalize before
// raising a policy exception. This is a little more polished than letting
// the user hit the error on any variant of the slug.
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withSlugs(array($normal))
->execute();
if (!$projects) {
return null;
}
return "/tag/{$normal}/";
}
} }

View file

@ -498,9 +498,7 @@ final class PhabricatorProjectTransactionEditor
PhabricatorLiskDAO $object, PhabricatorLiskDAO $object,
$name) { $name) {
$object = (clone $object); $slug = PhabricatorSlug::normalizeProjectSlug($name);
$object->setPhrictionSlug($name);
$slug = $object->getPrimarySlug();
$slug_object = id(new PhabricatorProjectSlug())->loadOneWhere( $slug_object = id(new PhabricatorProjectSlug())->loadOneWhere(
'slug = %s', 'slug = %s',

View file

@ -2,6 +2,12 @@
final class PhabricatorSlug extends Phobject { final class PhabricatorSlug extends Phobject {
public static function normalizeProjectSlug($slug) {
$slug = str_replace('/', ' ', $slug);
$slug = self::normalize($slug);
return rtrim($slug, '/');
}
public static function normalize($slug) { public static function normalize($slug) {
$slug = preg_replace('@/+@', '/', $slug); $slug = preg_replace('@/+@', '/', $slug);
$slug = trim($slug, '/'); $slug = trim($slug, '/');