@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+49 -4
+7
src/aphront/configuration/AphrontApplicationConfiguration.php
··· 372 372 $result = $this->routePath($maps, $path.'/'); 373 373 if ($result) { 374 374 $slash_uri = $request->getRequestURI()->setPath($path.'/'); 375 + 376 + // We need to restore URI encoding because the webserver has 377 + // interpreted it. For example, this allows us to redirect a path 378 + // like `/tag/aa%20bb` to `/tag/aa%20bb/`, which may eventually be 379 + // resolved meaningfully by an application. 380 + $slash_uri = phutil_escape_uri($slash_uri); 381 + 375 382 $external = strlen($request->getRequestURI()->getDomain()); 376 383 return $this->buildRedirectController($slash_uri, $external); 377 384 }
+35 -1
src/applications/project/controller/PhabricatorProjectViewController.php
··· 26 26 } 27 27 $project = $query->executeOne(); 28 28 if (!$project) { 29 + 30 + // If this request corresponds to a project but just doesn't have the 31 + // slug quite right, redirect to the proper URI. 32 + $uri = $this->getNormalizedURI($slug); 33 + if ($uri !== null) { 34 + return id(new AphrontRedirectResponse())->setURI($uri); 35 + } 36 + 29 37 return new Aphront404Response(); 30 38 } 31 - 32 39 33 40 $columns = id(new PhabricatorProjectColumnQuery()) 34 41 ->setViewer($viewer) ··· 51 58 } 52 59 53 60 return $this->delegateToController($controller_object); 61 + } 62 + 63 + private function getNormalizedURI($slug) { 64 + if (!strlen($slug)) { 65 + return null; 66 + } 67 + 68 + $normal = PhabricatorSlug::normalizeProjectSlug($slug); 69 + if ($normal === $slug) { 70 + return null; 71 + } 72 + 73 + $viewer = $this->getViewer(); 74 + 75 + // Do execute() instead of executeOne() here so we canonicalize before 76 + // raising a policy exception. This is a little more polished than letting 77 + // the user hit the error on any variant of the slug. 78 + 79 + $projects = id(new PhabricatorProjectQuery()) 80 + ->setViewer($viewer) 81 + ->withSlugs(array($normal)) 82 + ->execute(); 83 + if (!$projects) { 84 + return null; 85 + } 86 + 87 + return "/tag/{$normal}/"; 54 88 } 55 89 56 90 }
+1 -3
src/applications/project/editor/PhabricatorProjectTransactionEditor.php
··· 498 498 PhabricatorLiskDAO $object, 499 499 $name) { 500 500 501 - $object = (clone $object); 502 - $object->setPhrictionSlug($name); 503 - $slug = $object->getPrimarySlug(); 501 + $slug = PhabricatorSlug::normalizeProjectSlug($name); 504 502 505 503 $slug_object = id(new PhabricatorProjectSlug())->loadOneWhere( 506 504 'slug = %s',
+6
src/infrastructure/util/PhabricatorSlug.php
··· 2 2 3 3 final class PhabricatorSlug extends Phobject { 4 4 5 + public static function normalizeProjectSlug($slug) { 6 + $slug = str_replace('/', ' ', $slug); 7 + $slug = self::normalize($slug); 8 + return rtrim($slug, '/'); 9 + } 10 + 5 11 public static function normalize($slug) { 6 12 $slug = preg_replace('@/+@', '/', $slug); 7 13 $slug = trim($slug, '/');