Rework pretty URLs

This commit is contained in:
grandeljay 2022-11-11 13:40:40 +01:00
parent 29c9c3c472
commit aa1c391166
6 changed files with 106 additions and 78 deletions

View file

@ -10,11 +10,11 @@
RewriteRule ^([a-z\-]+)$ /?page=$1 [QSA,L]
# Wishlists (My lists)
RewriteRule ^(wishlists)/([0-9]+)$ /?page=$1&id=$2 [QSA,L]
RewriteRule ^(wishlists)/([0-9]+)/add$ /?page=$1&id=$2&wish_add=true [QSA,L]
RewriteRule ^wishlists/([0-9]+)$ /?page=wishlists&id=$1 [QSA,L]
RewriteRule ^wishlists/([0-9]+)/add$ /?page=wishlists&id=$1&wish_add=true [QSA,L]
# Wishlist
RewriteRule ^(wishlist)/([0-9a-f]{40})$ /?page=$1&hash=$2 [QSA,L]
RewriteRule ^wishlist/([0-9a-f]{40})$ /?page=wishlist&hash=$1 [QSA,L]
# Blog Post
RewriteRule ^blog/([a-z\-0-9]+)$ /?page=post&slug=$1 [QSA,L]

View file

@ -18,12 +18,13 @@ if (!isset($page)) {
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
if (isset($_GET['url'])) {
$url = new URL(base64_decode($_GET['url']));
$url_old = base64_decode($_GET['url']);
$url = new URL($url_old);
$response['data'] = array(
'url' => $url->getPretty(),
'url_old' => $url->url,
'url_old_pretty' => $url->isPretty(),
'url' => $url_old,
'url_pretty' => $url->getPretty(),
'url_is_pretty' => $url->isPretty(),
);
}
break;

View file

@ -81,7 +81,7 @@ $(function () {
.then(handleFetchError)
.then(handleFetchResponse)
.then(function(response) {
window.history.pushState(null, document.title, response.data.url);
window.history.pushState(null, document.title, response.data.url_pretty);
$('.ui.dropdown.filter.priority')
.dropdown('restore default value')

View file

@ -149,35 +149,26 @@ class Page
/**
* Session
*/
$user = isset($_SESSION['user']->id) ? $_SESSION['user'] : new User();
$ignorePower = array(
'blog',
'changelog',
'home',
'install',
'login',
'maintenance',
'post',
'register',
'wishlist',
);
if (
false === $user->isLoggedIn()
&& isset($_GET['page'])
&& false === in_array($_GET['page'], $ignorePower)
) {
redirect(Page::PAGE_LOGIN);
}
$user = isset($_SESSION['user']->id) ? $_SESSION['user'] : new User();
/**
* Power
*/
if (isset($user->power) && $user->power < $this->power) {
if (isset($user->power) && $user->power < $this->power && 0 !== $this->power) {
redirect(Page::PAGE_POWER . '&required=' . $this->power);
}
/**
* Login
*/
if (
false === $user->isLoggedIn()
&& isset($_GET['page'])
&& 0 !== $this->power
) {
redirect(Page::PAGE_LOGIN);
}
/**
* Update
*/
@ -200,7 +191,7 @@ class Page
* Redirect
*/
if ($options && $options->getOption('isInstalled') && isset($_GET)) {
$url = new URL(http_build_query($_GET));
$url = new URL($_SERVER['REQUEST_URI']);
if ($url->url && false === $url->isPretty()) {
redirect($url->getPretty());

View file

@ -11,7 +11,11 @@ namespace wishthis;
class URL
{
/**
* Static
* Returns the HTTP status code of a URL.
*
* @param string $url
*
* @return integer
*/
public static function getResponseCode(string $url): int
{
@ -43,24 +47,41 @@ class URL
}
/**
* Non-Static
* The current URL. Can be pretty or not.
*
* @var string
*/
public string $url;
/**
* Constructor
*
* @param string $url
*/
public function __construct(string $url)
{
$this->url = urldecode($url);
$_GET = $this->get_GET();
$_GET = $this->getGET();
}
/**
* Returns whether the current URL is pretty.
*
* @return boolean
*/
public function isPretty(): bool
{
$isPretty = 1 === preg_match('/^\/[a-z0-9\/]+/', $this->url);
$isPretty = 1 === preg_match('/^\/[a-z0-9\/\-]+$/', $this->url);
return $isPretty;
}
/**
* Returns the original, un-pretty URL or an empty string on failure.
*
* @return string
*/
public function getPermalink(): string
{
$htaccess = preg_split('/\r\n|\r|\n/', file_get_contents(ROOT . '/.htaccess'));
@ -95,10 +116,14 @@ class URL
return $permalink;
}
/**
* Returns a pretty version of the current URL.
*
* @return string
*/
public function getPretty(): string
{
$htaccess = preg_split('/\r\n|\r|\n/', file_get_contents(ROOT . '/.htaccess'));
$pretty_url = '';
$htaccess = preg_split('/\r\n|\r|\n/', file_get_contents(ROOT . '/.htaccess'));
if (!$this->url) {
return '';
@ -121,63 +146,74 @@ class URL
explode('&', parse_url($target, PHP_URL_QUERY))
);
$flags = explode(',', substr($parts[3], 1, -1)) ?? array();
parse_str($this->url, $getParameters);
uasort(
$getParameters,
function ($a, $b) {
return strlen($a) <=> strlen($b);
parse_str(ltrim($target, '/?'), $parameters);
/** */
/** Determine a potential URL. */
$potential_url = $rewriteRule;
preg_match_all('/\(.+?\)/', $rewriteRule, $groups);
$groups = $groups[0];
for ($i = 0; $i < count($groups); $i++) {
foreach ($parameters as $key => $value) {
$replacement = '$' . $i + 1;
if ($replacement === $value && isset($_GET[$key])) {
$potential_url = str_replace(
$groups[$i],
$_GET[$key],
$potential_url
);
}
}
}
$match = preg_match(
'/^' . str_replace(array('/'), array('\/'), $rewriteRule) . '$/',
$potential_url
);
$getParameters = array_reverse($getParameters, true);
preg_match_all('/\(.+?\)/', $rewriteRule, $regexes);
$countMatches = 0;
foreach ($regexes as $matches) {
foreach ($matches as $match) {
foreach ($getParameters as $key => $value) {
if (
preg_match('/^' . $match . '$/', $value)
&& in_array($key, $keys)
&& count($getParameters) === count($keys)
) {
$rewriteRule = str_replace($match, $value, $rewriteRule);
$countMatches++;
break;
}
}
}
if ($countMatches > 0 && $countMatches === count($matches)) {
$pretty_url = '/' . $rewriteRule;
if (in_array('L', $flags)) {
break 3;
}
}
if (1 === $match && count($_GET) === count(explode('/', $rewriteRule))) {
return '/' . $potential_url;
}
break;
}
}
}
return $pretty_url ?: '/?' . $this->url;
if ('/?' === substr($this->url, 0, 2)) {
return $this->url;
}
return '/?' . $this->url;
}
public function get_GET(): array
/**
* Returns the current URL parameters, even for pretty URLs.
*
* @return array
*/
public function getGET(): array
{
$queryString = parse_url($this->getPermalink(), PHP_URL_QUERY);
$queryString = $this->url;
$GET = array();
if ($this->isPretty() && $queryString) {
parse_str($queryString, $GET);
} else {
$GET = $_GET;
if ($this->isPretty()) {
$queryString = parse_url($this->getPermalink(), PHP_URL_QUERY);
}
if (null === $queryString) {
return array();
}
if ('/?' === substr($queryString, 0, 2)) {
$queryString = substr($queryString, 2);
}
parse_str($queryString, $GET);
return $GET;
}
}

View file

@ -43,7 +43,7 @@ $page->navigation();
<li>
<?php
/** TRANSLATORS: Changelog: Improved */
echo __('Completely reworked the API');
echo __('Large parts of wishthis have been completely rewritten, such as the API and how pretty URLs work. The aim was to increase security and maintenability.');
?>
</li>
</ul>