From ce803f6d0618451aefac97ecd68b7b3d0e8d3b32 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sun, 21 Feb 2016 20:00:07 +0100 Subject: [PATCH] WebFinger aliases with 'index.php/' --- lib/util.php | 31 +++++++++++++++++++++ plugins/WebFinger/WebFingerPlugin.php | 11 ++++++-- plugins/WebFinger/lib/webfingerresource.php | 28 +++++++++++++++---- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/lib/util.php b/lib/util.php index 64af25f059..bef56502a0 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1428,6 +1428,37 @@ function common_fake_local_fancy_url($url) return $fancy_url; } +// FIXME: Maybe this should also be able to handle non-fancy URLs with index.php?p=... +function common_fake_local_nonfancy_url($url) +{ + /** + * This is a hacky fix to make URIs NOT generated with "index.php/" match against + * locally stored URIs WITH that. The reverse from the above. + * + * It will also "repair" index.php URLs with multiple / prepended. Like https://some.example///index.php/user/1 + */ + if (!preg_match( + // [1] protocol part, we can only rewrite http/https anyway. + '/^(https?:\/\/)' . + // [2] site name. + // FIXME: Dunno how this acts if we're aliasing ourselves with a .onion domain etc. + '('.preg_quote(common_config('site', 'server'), '/').')' . + // [3] site path, or if that is empty just '/' (to retain the /) + '('.preg_quote(common_config('site', 'path') ?: '/', '/').')' . + // [4] should be empty (might contain one or more / and then maybe also index.php). Will be overwritten. + // [5] will have the extracted actual URL part (besides site path) + '((?!index.php\/)\/*(?:index.php\/)?)(.*)$/', $url, $matches)) { + // if preg_match failed to match + throw new Exception('No known change could be made to the URL.'); + } + + $matches[4] = 'index.php/'; // inject the index.php/ rewritethingy + + // remove the first element, which is the full matching string + array_shift($matches); + return implode($matches); +} + function common_inject_session($url, $serverpart = null) { if (!common_have_session()) { diff --git a/plugins/WebFinger/WebFingerPlugin.php b/plugins/WebFinger/WebFingerPlugin.php index 84d2f63b6c..5eec98ea69 100644 --- a/plugins/WebFinger/WebFingerPlugin.php +++ b/plugins/WebFinger/WebFingerPlugin.php @@ -105,11 +105,16 @@ class WebFingerPlugin extends Plugin $profile = $user->getProfile(); } catch (NoResultException $e) { try { - // common_fake_local_fancy_url can throw an exception - $fancy_url = common_fake_local_fancy_url($resource); + try { // if it's a /index.php/ url + // common_fake_local_fancy_url can throw an exception + $alt_url = common_fake_local_fancy_url($resource); + } catch (Exception $e) { // let's try to create a fake local /index.php/ url + // this too if it can't do anything about the URL + $alt_url = common_fake_local_nonfancy_url($resource); + } // and this will throw a NoResultException if not found - $user = User::getByUri($fancy_url); + $user = User::getByUri($alt_url); $profile = $user->getProfile(); } catch (Exception $e) { // if our rewrite hack didn't work, try to get something by profile URL diff --git a/plugins/WebFinger/lib/webfingerresource.php b/plugins/WebFinger/lib/webfingerresource.php index 0445b9a0a2..51308c32d4 100644 --- a/plugins/WebFinger/lib/webfingerresource.php +++ b/plugins/WebFinger/lib/webfingerresource.php @@ -47,17 +47,33 @@ abstract class WebFingerResource // getUrl failed because no valid URL could be returned, just ignore it } - // We claim that we are for example https://site.example/user/1 even if the client - // requests https://site.example/index.php/user/1 due to behaviour seen in the wild. + /** + * Here we add some hacky hotfixes for remote lookups that have been taught the + * (at least now) wrong URI but it's still obviously the same user. Such as: + * - https://site.example/user/1 even if the client requests https://site.example/index.php/user/1 + * - https://site.example/user/1 even if the client requests https://site.example//index.php/user/1 + * - https://site.example/index.php/user/1 even if the client requests https://site.example/user/1 + * - https://site.example/index.php/user/1 even if the client requests https://site.example///index.php/user/1 + */ + + foreach(array_keys($aliases) as $alias) { try { // get a "fancy url" version of the alias, even without index.php/ - $fancy_url = common_fake_local_fancy_url($alias); + $alt_url = common_fake_local_fancy_url($alias); // store this as well so remote sites can be sure we really are the same profile - $aliases[$fancy_url] = true; + $aliases[$alt_url] = true; } catch (Exception $e) { - // in case we couldn't make a "fake local fancy URL", just continue the foreach-loop - continue; + // Apparently we couldn't rewrite that, the $alias was as the function wanted it to be + } + + try { + // get a non-"fancy url" version of the alias, i.e. add index.php/ + $alt_url = common_fake_local_nonfancy_url($alias); + // store this as well so remote sites can be sure we really are the same profile + $aliases[$alt_url] = true; + } catch (Exception $e) { + // Apparently we couldn't rewrite that, the $alias was as the function wanted it to be } }