Add preg_replace_ex

having preg_replace return string|array|null is a pain, string|exception is much cleaner
This commit is contained in:
Shish 2024-08-31 19:53:07 +01:00 committed by Shish
parent 2e8f38cce0
commit 8b20fa3bc2
18 changed files with 61 additions and 54 deletions

View file

@ -55,7 +55,7 @@ class Block
if (is_null($id)) { if (is_null($id)) {
$id = (empty($header) ? md5($this->body ?? '') : $header) . $section; $id = (empty($header) ? md5($this->body ?? '') : $header) . $section;
} }
$str_id = preg_replace('/[^\w-]/', '', str_replace(' ', '_', $id)); $str_id = preg_replace_ex('/[^\w-]/', '', str_replace(' ', '_', $id));
assert(is_string($str_id)); assert(is_string($str_id));
$this->id = $str_id; $this->id = $str_id;
} }

View file

@ -185,8 +185,7 @@ class Database
global $_tracer, $tracer_enabled; global $_tracer, $tracer_enabled;
$dur = ftime() - $start; $dur = ftime() - $start;
// trim whitespace // trim whitespace
$query = \Safe\preg_replace('/[\n\t ]+/m', ' ', $query); $query = preg_replace_ex('/[\n\t ]+/m', ' ', $query);
assert(is_string($query));
$query = trim($query); $query = trim($query);
if ($tracer_enabled) { if ($tracer_enabled) {
$_tracer->complete($start * 1000000, $dur * 1000000, "DB Query", ["query" => $query, "args" => $args, "method" => $method]); $_tracer->complete($start * 1000000, $dur * 1000000, "DB Query", ["query" => $query, "args" => $args, "method" => $method]);

View file

@ -196,13 +196,13 @@ class Tag
public static function sanitize(string $tag): string public static function sanitize(string $tag): string
{ {
$tag = preg_replace("/\s/", "", $tag); # whitespace $tag = preg_replace_ex("/\s/", "", $tag); # whitespace
assert($tag !== null); assert($tag !== null);
$tag = preg_replace('/\x20[\x0e\x0f]/', '', $tag); # unicode RTL $tag = preg_replace_ex('/\x20[\x0e\x0f]/', '', $tag); # unicode RTL
assert($tag !== null); assert($tag !== null);
$tag = preg_replace("/\.+/", ".", $tag); # strings of dots? $tag = preg_replace_ex("/\.+/", ".", $tag); # strings of dots?
assert($tag !== null); assert($tag !== null);
$tag = preg_replace("/^(\.+[\/\\\\])+/", "", $tag); # trailing slashes? $tag = preg_replace_ex("/^(\.+[\/\\\\])+/", "", $tag); # trailing slashes?
assert($tag !== null); assert($tag !== null);
$tag = trim($tag, ", \t\n\r\0\x0B"); $tag = trim($tag, ", \t\n\r\0\x0B");

View file

@ -693,8 +693,7 @@ function validate_input(array $inputs): array
*/ */
function sanitize_path(string $path): string function sanitize_path(string $path): string
{ {
$r = \Safe\preg_replace('|[\\\\/]+|S', DIRECTORY_SEPARATOR, $path); $r = preg_replace_ex('|[\\\\/]+|S', DIRECTORY_SEPARATOR, $path);
assert(is_string($r));
return $r; return $r;
} }

View file

@ -21,7 +21,7 @@ function _load_event_listeners(): void
{ {
global $_shm_event_listeners; global $_shm_event_listeners;
$ver = preg_replace("/[^a-zA-Z0-9\.]/", "_", VERSION); $ver = preg_replace_ex("/[^a-zA-Z0-9\.]/", "_", VERSION);
$key = md5(Extension::get_enabled_extensions_as_string()); $key = md5(Extension::get_enabled_extensions_as_string());
$cache_path = data_path("cache/event_listeners/el.$ver.$key.php"); $cache_path = data_path("cache/event_listeners/el.$ver.$key.php");

View file

@ -32,3 +32,12 @@ function filter_var_ex(mixed $variable, int $filter = FILTER_DEFAULT, mixed $opt
{ {
return false_throws(filter_var($variable, $filter, $options)); return false_throws(filter_var($variable, $filter, $options));
} }
function preg_replace_ex(string $pattern, string $replacement, string $subject, int $limit = -1, ?int &$count = null): string
{
$res = preg_replace($pattern, $replacement, $subject, $limit, $count);
if (is_null($res)) {
throw new \Exception("preg_replace failed");
}
return $res;
}

View file

@ -18,36 +18,36 @@ class BBCode extends FormatterExtension
foreach ([ foreach ([
"b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4", "b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4",
] as $el) { ] as $el) {
$text = preg_replace("!\[$el\](.*?)\[/$el\]!s", "<$el>$1</$el>", $text); $text = preg_replace_ex("!\[$el\](.*?)\[/$el\]!s", "<$el>$1</$el>", $text);
} }
$text = preg_replace('!^&gt;&gt;([^\d].+)!', '<blockquote><small>$1</small></blockquote>', $text); $text = preg_replace_ex('!^&gt;&gt;([^\d].+)!', '<blockquote><small>$1</small></blockquote>', $text);
$text = preg_replace('!&gt;&gt;(\d+)(#c?\d+)?!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('post/view/$1$2').'">&gt;&gt;$1$2</a>', $text); $text = preg_replace_ex('!&gt;&gt;(\d+)(#c?\d+)?!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('post/view/$1$2').'">&gt;&gt;$1$2</a>', $text);
$text = preg_replace('!\[anchor=(.*?)\](.*?)\[/anchor\]!s', '<span class="anchor">$2 <a class="alink" href="#bb-$1" name="bb-$1" title="link to this anchor"> ¶ </a></span>', $text); // add "bb-" to avoid clashing with eg #top $text = preg_replace_ex('!\[anchor=(.*?)\](.*?)\[/anchor\]!s', '<span class="anchor">$2 <a class="alink" href="#bb-$1" name="bb-$1" title="link to this anchor"> ¶ </a></span>', $text); // add "bb-" to avoid clashing with eg #top
$text = preg_replace('!\[url=site://(.*?)(#c\d+)?\](.*?)\[/url\]!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('$1$2').'">$3</a>', $text); $text = preg_replace_ex('!\[url=site://(.*?)(#c\d+)?\](.*?)\[/url\]!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('$1$2').'">$3</a>', $text);
$text = preg_replace('!\[url\]site://(.*?)(#c\d+)?\[/url\]!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('$1$2').'">$1$2</a>', $text); $text = preg_replace_ex('!\[url\]site://(.*?)(#c\d+)?\[/url\]!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('$1$2').'">$1$2</a>', $text);
$text = preg_replace('!\[url=((?:https?|ftp|irc|mailto)://.*?)\](.*?)\[/url\]!s', '<a href="$1">$2</a>', $text); $text = preg_replace_ex('!\[url=((?:https?|ftp|irc|mailto)://.*?)\](.*?)\[/url\]!s', '<a href="$1">$2</a>', $text);
$text = preg_replace('!\[url\]((?:https?|ftp|irc|mailto)://.*?)\[/url\]!s', '<a href="$1">$1</a>', $text); $text = preg_replace_ex('!\[url\]((?:https?|ftp|irc|mailto)://.*?)\[/url\]!s', '<a href="$1">$1</a>', $text);
$text = preg_replace('!\[email\](.*?)\[/email\]!s', '<a href="mailto:$1">$1</a>', $text); $text = preg_replace_ex('!\[email\](.*?)\[/email\]!s', '<a href="mailto:$1">$1</a>', $text);
$text = preg_replace('!\[img\](https?:\/\/.*?)\[/img\]!s', '<img alt="user image" src="$1">', $text); $text = preg_replace_ex('!\[img\](https?:\/\/.*?)\[/img\]!s', '<img alt="user image" src="$1">', $text);
$text = preg_replace('!\[\[([^\|\]]+)\|([^\]]+)\]\]!s', '<a href="'.make_link('wiki/$1').'">$2</a>', $text); $text = preg_replace_ex('!\[\[([^\|\]]+)\|([^\]]+)\]\]!s', '<a href="'.make_link('wiki/$1').'">$2</a>', $text);
$text = preg_replace('!\[\[([^\]]+)\]\]!s', '<a href="'.make_link('wiki/$1').'">$1</a>', $text); $text = preg_replace_ex('!\[\[([^\]]+)\]\]!s', '<a href="'.make_link('wiki/$1').'">$1</a>', $text);
$text = preg_replace("!\n\s*\n!", "\n\n", $text); $text = preg_replace_ex("!\n\s*\n!", "\n\n", $text);
$text = str_replace("\n", "\n<br>", $text); $text = str_replace("\n", "\n<br>", $text);
$text = preg_replace("/\[quote\](.*?)\[\/quote\]/s", "<blockquote><small>\\1</small></blockquote>", $text); $text = preg_replace_ex("/\[quote\](.*?)\[\/quote\]/s", "<blockquote><small>\\1</small></blockquote>", $text);
$text = preg_replace("/\[quote=(.*?)\](.*?)\[\/quote\]/s", "<blockquote><em>\\1 said:</em><br><small>\\2</small></blockquote>", $text); $text = preg_replace_ex("/\[quote=(.*?)\](.*?)\[\/quote\]/s", "<blockquote><em>\\1 said:</em><br><small>\\2</small></blockquote>", $text);
while (preg_match("/\[list\](.*?)\[\/list\]/s", $text)) { while (preg_match("/\[list\](.*?)\[\/list\]/s", $text)) {
$text = preg_replace("/\[list\](.*?)\[\/list\]/s", "<ul>\\1</ul>", $text); $text = preg_replace_ex("/\[list\](.*?)\[\/list\]/s", "<ul>\\1</ul>", $text);
} }
while (preg_match("/\[ul\](.*?)\[\/ul\]/s", $text)) { while (preg_match("/\[ul\](.*?)\[\/ul\]/s", $text)) {
$text = preg_replace("/\[ul\](.*?)\[\/ul\]/s", "<ul>\\1</ul>", $text); $text = preg_replace_ex("/\[ul\](.*?)\[\/ul\]/s", "<ul>\\1</ul>", $text);
} }
while (preg_match("/\[ol\](.*?)\[\/ol\]/s", $text)) { while (preg_match("/\[ol\](.*?)\[\/ol\]/s", $text)) {
$text = preg_replace("/\[ol\](.*?)\[\/ol\]/s", "<ol>\\1</ol>", $text); $text = preg_replace_ex("/\[ol\](.*?)\[\/ol\]/s", "<ol>\\1</ol>", $text);
} }
$text = preg_replace("/\[li\](.*?)\[\/li\]/s", "<li>\\1</li>", $text); $text = preg_replace_ex("/\[li\](.*?)\[\/li\]/s", "<li>\\1</li>", $text);
$text = preg_replace("#\[\*\]#s", "<li>", $text); $text = preg_replace_ex("#\[\*\]#s", "<li>", $text);
$text = preg_replace("#<br><(li|ul|ol|/ul|/ol)>#s", "<\\1>", $text); $text = preg_replace_ex("#<br><(li|ul|ol|/ul|/ol)>#s", "<\\1>", $text);
$text = preg_replace("#\[align=(left|center|right)\](.*?)\[\/align\]#s", "<div style='text-align:\\1;'>\\2</div>", $text); $text = preg_replace_ex("#\[align=(left|center|right)\](.*?)\[\/align\]#s", "<div style='text-align:\\1;'>\\2</div>", $text);
$text = $this->filter_spoiler($text); $text = $this->filter_spoiler($text);
$text = $this->insert_code($text); $text = $this->insert_code($text);
return $text; return $text;
@ -59,17 +59,17 @@ class BBCode extends FormatterExtension
"b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4", "b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4",
"code", "url", "email", "li", "code", "url", "email", "li",
] as $el) { ] as $el) {
$text = preg_replace("!\[$el\](.*?)\[/$el\]!s", '$1', $text); $text = preg_replace_ex("!\[$el\](.*?)\[/$el\]!s", '$1', $text);
} }
$text = preg_replace("!\[anchor=(.*?)\](.*?)\[/anchor\]!s", '$2', $text); $text = preg_replace_ex("!\[anchor=(.*?)\](.*?)\[/anchor\]!s", '$2', $text);
$text = preg_replace("!\[url=(.*?)\](.*?)\[/url\]!s", '$2', $text); $text = preg_replace_ex("!\[url=(.*?)\](.*?)\[/url\]!s", '$2', $text);
$text = preg_replace("!\[img\](.*?)\[/img\]!s", "", $text); $text = preg_replace_ex("!\[img\](.*?)\[/img\]!s", "", $text);
$text = preg_replace("!\[\[([^\|\]]+)\|([^\]]+)\]\]!s", '$2', $text); $text = preg_replace_ex("!\[\[([^\|\]]+)\|([^\]]+)\]\]!s", '$2', $text);
$text = preg_replace("!\[\[([^\]]+)\]\]!s", '$1', $text); $text = preg_replace_ex("!\[\[([^\]]+)\]\]!s", '$1', $text);
$text = preg_replace("!\[quote\](.*?)\[/quote\]!s", "", $text); $text = preg_replace_ex("!\[quote\](.*?)\[/quote\]!s", "", $text);
$text = preg_replace("!\[quote=(.*?)\](.*?)\[/quote\]!s", "", $text); $text = preg_replace_ex("!\[quote=(.*?)\](.*?)\[/quote\]!s", "", $text);
$text = preg_replace("!\[/?(list|ul|ol)\]!", "", $text); $text = preg_replace_ex("!\[/?(list|ul|ol)\]!", "", $text);
$text = preg_replace("!\[\*\](.*?)!s", '$1', $text); $text = preg_replace_ex("!\[\*\](.*?)!s", '$1', $text);
$text = $this->strip_spoiler($text); $text = $this->strip_spoiler($text);
return $text; return $text;
} }

View file

@ -12,7 +12,7 @@ class Emoticons extends FormatterExtension
public function format(string $text): string public function format(string $text): string
{ {
$data_href = get_base_href(); $data_href = get_base_href();
$text = preg_replace("/:([a-z]*?):/s", "<img alt='\1' src='$data_href/ext/emoticons/default/\\1.gif'>", $text); $text = preg_replace_ex("/:([a-z]*?):/s", "<img alt='\1' src='$data_href/ext/emoticons/default/\\1.gif'>", $text);
return $text; return $text;
} }

View file

@ -123,7 +123,7 @@ class ET extends Extension
$commitHash = trim(\Safe\exec('git log --pretty="%h" -n1 HEAD')); $commitHash = trim(\Safe\exec('git log --pretty="%h" -n1 HEAD'));
$commitBranch = trim(\Safe\exec('git rev-parse --abbrev-ref HEAD')); $commitBranch = trim(\Safe\exec('git rev-parse --abbrev-ref HEAD'));
$commitOrigin = trim(\Safe\exec('git config --get remote.origin.url')); $commitOrigin = trim(\Safe\exec('git config --get remote.origin.url'));
$commitOrigin = preg_replace("#//.*@#", "//xxx@", $commitOrigin); $commitOrigin = preg_replace_ex("#//.*@#", "//xxx@", $commitOrigin);
$info['versions']['shimmie'] .= $commitHash; $info['versions']['shimmie'] .= $commitHash;
$info['versions']['origin'] = "$commitOrigin ($commitBranch)"; $info['versions']['origin'] = "$commitOrigin ($commitBranch)";
$info['git'] = [ $info['git'] = [

View file

@ -244,7 +244,7 @@ class ImageIO extends Extension
if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) { if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) {
$if_modified_since = preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]); $if_modified_since = preg_replace_ex('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]);
} else { } else {
$if_modified_since = ""; $if_modified_since = "";
} }

View file

@ -174,7 +174,7 @@ class Index extends Extension
); );
$sql_str = $q->sql; $sql_str = $q->sql;
$sql_str = preg_replace("/\s+/", " ", $sql_str); $sql_str = preg_replace_ex("/\s+/", " ", $sql_str);
foreach ($q->variables as $key => $val) { foreach ($q->variables as $key => $val) {
if (is_string($val)) { if (is_string($val)) {
$sql_str = str_replace(":$key", "'$val'", $sql_str); $sql_str = str_replace(":$key", "'$val'", $sql_str);

View file

@ -252,7 +252,7 @@ class Media extends Extension
$event->add_querylet(new Querylet("$field = :true", ["true" => true])); $event->add_querylet(new Querylet("$field = :true", ["true" => true]));
} }
} elseif (preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/i", $event->term, $matches)) { } elseif (preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/i", $event->term, $matches)) {
$cmp = preg_replace('/^:/', '=', $matches[1]); $cmp = preg_replace_ex('/^:/', '=', $matches[1]);
$args = ["width{$event->id}" => int_escape($matches[2]), "height{$event->id}" => int_escape($matches[3])]; $args = ["width{$event->id}" => int_escape($matches[2]), "height{$event->id}" => int_escape($matches[3])];
$event->add_querylet(new Querylet("width / :width{$event->id} $cmp height / :height{$event->id}", $args)); $event->add_querylet(new Querylet("width / :width{$event->id} $cmp height / :height{$event->id}", $args));
} elseif (preg_match("/^size([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)x(\d+)$/i", $event->term, $matches)) { } elseif (preg_match("/^size([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)x(\d+)$/i", $event->term, $matches)) {

View file

@ -36,7 +36,7 @@ class StaticFiles extends Extension
// hax. // hax.
if ($page->mode == PageMode::PAGE && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) { if ($page->mode == PageMode::PAGE && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) {
$h_pagename = html_escape(implode('/', $event->args)); $h_pagename = html_escape(implode('/', $event->args));
$f_pagename = preg_replace("/[^a-z_\-\.]+/", "_", $h_pagename); $f_pagename = preg_replace_ex("/[^a-z_\-\.]+/", "_", $h_pagename);
$theme_name = $config->get_string(SetupConfig::THEME, "default"); $theme_name = $config->get_string(SetupConfig::THEME, "default");
$theme_file = "themes/$theme_name/static/$f_pagename"; $theme_file = "themes/$theme_name/static/$f_pagename";

View file

@ -351,7 +351,7 @@ class Upload extends Extension
// Parse metadata // Parse metadata
$s_filename = find_header($headers, 'Content-Disposition'); $s_filename = find_header($headers, 'Content-Disposition');
$h_filename = ($s_filename ? preg_replace('/^.*filename="([^ ]+)"/i', '$1', $s_filename) : null); $h_filename = ($s_filename ? preg_replace_ex('/^.*filename="([^ ]+)"/i', '$1', $s_filename) : null);
$filename = $h_filename ?: basename($url); $filename = $h_filename ?: basename($url);
$new_images = $database->with_savepoint(function () use ($tmp_filename, $filename, $slot, $metadata) { $new_images = $database->with_savepoint(function () use ($tmp_filename, $filename, $slot, $metadata) {

View file

@ -402,7 +402,7 @@ class UserPageTheme extends Themelet
$doc = $perm->getDocComment(); $doc = $perm->getDocComment();
if ($doc) { if ($doc) {
$doc = preg_replace('/\/\*\*|\n\s*\*\s*|\*\//', '', $doc); $doc = preg_replace_ex('/\/\*\*|\n\s*\*\s*|\*\//', '', $doc);
$row->appendChild(TD(["style" => "text-align: left;"], $doc)); $row->appendChild(TD(["style" => "text-align: left;"], $doc));
} else { } else {
$row->appendChild(TD("")); $row->appendChild(TD(""));

View file

@ -75,7 +75,7 @@ class UserConfigTheme extends Themelet
{ {
$h = $block->header; $h = $block->header;
$b = $block->body; $b = $block->body;
$i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup"; $i = preg_replace_ex('/[^a-zA-Z0-9]/', '_', $h) . "-setup";
$html = " $html = "
<section class='setupblock'> <section class='setupblock'>
<b class='shm-toggler' data-toggle-sel='#$i'>$h</b> <b class='shm-toggler' data-toggle-sel='#$i'>$h</b>

View file

@ -32,10 +32,10 @@ class WordFilter extends Extension
$search = trim($search); $search = trim($search);
$replace = trim($replace); $replace = trim($replace);
if ($search[0] == '/') { if ($search[0] == '/') {
$text = preg_replace($search, $replace, $text); $text = preg_replace_ex($search, $replace, $text);
} else { } else {
$search = "/\\b" . str_replace("/", "\\/", $search) . "\\b/i"; $search = "/\\b" . str_replace("/", "\\/", $search) . "\\b/i";
$text = preg_replace($search, $replace, $text); $text = preg_replace_ex($search, $replace, $text);
} }
} }
return $text; return $text;

View file

@ -87,7 +87,7 @@ class CustomCommentListTheme extends CommentListTheme
} else { } else {
$h_comment = $tfe->formatted; $h_comment = $tfe->formatted;
} }
$h_comment = preg_replace("/(^|>)(&gt;[^<\n]*)(<|\n|$)/", '${1}<span class=\'greentext\'>${2}</span>${3}', $h_comment); $h_comment = preg_replace_ex("/(^|>)(&gt;[^<\n]*)(<|\n|$)/", '${1}<span class=\'greentext\'>${2}</span>${3}', $h_comment);
// handles discrepency in comment page and homepage // handles discrepency in comment page and homepage
$h_comment = str_replace("<br>", "", $h_comment); $h_comment = str_replace("<br>", "", $h_comment);
$h_comment = str_replace("\n", "<br>", $h_comment); $h_comment = str_replace("\n", "<br>", $h_comment);