make it more explicit that caret/decaret are for encoding tags into URL paths

This commit is contained in:
Shish 2020-01-30 21:50:30 +00:00
parent fb80509be9
commit da42b19d6b
8 changed files with 70 additions and 73 deletions

View file

@ -72,16 +72,6 @@ class PageRequestEvent extends Event
// break the path into parts
$args = explode('/', $path);
// voodoo so that an arg can contain a slash; is
// this still needed?
if (strpos($path, "^") !== false) {
$unescaped = [];
foreach ($args as $part) {
$unescaped[] = _decaret($part);
}
$args = $unescaped;
}
$this->args = $args;
$this->arg_count = count($args);
}
@ -152,7 +142,7 @@ class PageRequestEvent extends Event
{
$search_terms = [];
if ($this->count_args() === 2) {
$search_terms = Tag::explode($this->get_arg(0));
$search_terms = Tag::explode(Tag::decaret($this->get_arg(0)));
}
return $search_terms;
}

View file

@ -152,7 +152,6 @@ class Tag
return $tag_array;
}
public static function sqlify(string $term): string
{
global $database;
@ -165,4 +164,51 @@ class Tag
// $term = str_replace("?", "_", $term);
return $term;
}
/**
* Kind of like urlencode, but using a custom scheme so that
* tags always fit neatly between slashes in a URL. Use this
* when you want to put an arbitrary tag into a URL.
*/
public static function caret(string $input): string
{
$to_caret = [
"^" => "^",
"/" => "s",
"\\" => "b",
"?" => "q",
"&" => "a",
];
foreach($to_caret as $from => $to) {
$input = str_replace($from, '^' . $to, $input);
}
return $input;
}
/**
* Use this when you want to get a tag out of a URL
*/
public static function decaret(string $str): string
{
$from_caret = [
"^" => "^",
"s" => "/",
"b" => "\\",
"q" => "?",
"a" => "&",
];
$out = "";
$length = strlen($str);
for ($i=0; $i<$length; $i++) {
if ($str[$i] == "^") {
$i++;
$out .= $from_caret[$str[$i]] ?? '';
} else {
$out .= $str[$i];
}
}
return $out;
}
}

View file

@ -449,32 +449,9 @@ function int_escape(?string $input): int
*/
function url_escape(?string $input): string
{
/*
Shish: I have a feeling that these three lines are important, possibly for searching for tags with slashes in them like fate/stay_night
green-ponies: indeed~
$input = str_replace('^', '^^', $input);
$input = str_replace('/', '^s', $input);
$input = str_replace('\\', '^b', $input);
/* The function idn_to_ascii is used to support Unicode domains / URLs as well.
See here for more: http://php.net/manual/en/function.filter-var.php
However, it is only supported by PHP version 5.3 and up
if (function_exists('idn_to_ascii')) {
return filter_var(idn_to_ascii($input), FILTER_SANITIZE_URL);
} else {
return filter_var($input, FILTER_SANITIZE_URL);
}
*/
if (is_null($input)) {
return "";
}
$input = str_replace('^', '^^', $input);
$input = str_replace('/', '^s', $input);
$input = str_replace('\\', '^b', $input);
$input = str_replace('?', '^q', $input);
$input = str_replace('&', '^a', $input);
$input = rawurlencode($input);
return $input;
}

View file

@ -30,7 +30,7 @@ class PolyfillsTest extends \PHPUnit\Framework\TestCase
public function test_url_escape()
{
$this->assertEquals(url_escape("^\o/^"), "%5E%5E%5Ebo%5Es%5E%5E");
$this->assertEquals(url_escape("^\o/^"), "%5E%5Co%2F%5E");
$this->assertEquals(url_escape(null), "");
}

19
core/tests/tag.test.php Normal file
View file

@ -0,0 +1,19 @@
<?php declare(strict_types=1);
require_once "core/imageboard/tag.php";
class TagTest extends \PHPUnit\Framework\TestCase
{
public function test_caret()
{
$this->assertEquals("foo", Tag::decaret("foo"));
$this->assertEquals("foo?", Tag::decaret("foo^q"));
$this->assertEquals("a^b/c\\d?e&f", Tag::decaret("a^^b^sc^bd^qe^af"));
}
public function test_decaret()
{
$this->assertEquals("foo", Tag::caret("foo"));
$this->assertEquals("foo^q", Tag::caret("foo?"));
$this->assertEquals("a^^b^sc^bd^qe^af", Tag::caret("a^b/c\\d?e&f"));
}
}

View file

@ -606,41 +606,6 @@ function _fatal_error(Exception $e): void
}
}
/**
* Turn ^^ into ^ and ^s into /
*
* Necessary because various servers and various clients
* think that / is special...
*/
function _decaret(string $str): string
{
$out = "";
$length = strlen($str);
for ($i=0; $i<$length; $i++) {
if ($str[$i] == "^") {
$i++;
if ($str[$i] == "^") {
$out .= "^";
}
if ($str[$i] == "s") {
$out .= "/";
}
if ($str[$i] == "b") {
$out .= "\\";
}
if ($str[$i] == "q") {
$out .= "?";
}
if ($str[$i] == "a") {
$out .= "&";
}
} else {
$out .= $str[$i];
}
}
return $out;
}
function _get_user(): User
{
global $config, $page;

View file

@ -25,7 +25,7 @@ class Index extends Extension
if ($event->page_matches("post/list")) {
if (isset($_GET['search'])) {
// implode(explode()) to resolve aliases and sanitise
$search = url_escape(Tag::implode(Tag::explode($_GET['search'], false)));
$search = url_escape(Tag::caret(Tag::implode(Tag::explode($_GET['search'], false))));
if (empty($search)) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list/1"));

View file

@ -9,7 +9,7 @@ class RSSImages extends Extension
$title = $config->get_string(SetupConfig::TITLE);
if (count($event->search_terms) > 0) {
$search = html_escape(implode(' ', $event->search_terms));
$search = url_escape(Tag::caret(Tag::implode($event->search_terms)));
$page->add_html_header("<link id=\"images\" rel=\"alternate\" type=\"application/rss+xml\" ".
"title=\"$title - Images with tags: $search\" href=\"".make_link("rss/images/$search/1")."\" />");
} else {