[core] exact and named page args

This commit is contained in:
Shish 2024-02-11 11:34:09 +00:00
parent 78aaff5c8f
commit 8c22cb1fb6
79 changed files with 718 additions and 829 deletions

View file

@ -40,13 +40,12 @@ class InitExtEvent extends Event
* A signal that a page has been requested.
*
* User requests /view/42 -> an event is generated with $args = array("view",
* "42"); when an event handler asks $event->page_matches("view"), it returns
* true and ignores the matched part, such that $event->count_args() = 1 and
* $event->get_arg(0) = "42"
* "42"); when an event handler asks $event->page_matches("view/{id}"), it returns
* true and sets $event->get_arg('id') = "42"
*/
class PageRequestEvent extends Event
{
public string $method;
private string $method;
public string $path;
/** @var array<string, string|string[]> */
public array $GET;
@ -57,9 +56,12 @@ class PageRequestEvent extends Event
* @var string[]
*/
public array $args;
public int $arg_count;
public int $part_count;
public bool $is_authed;
/**
* @var array<string, string>
*/
private array $named_args = [];
public int $page_num;
private bool $is_authed;
/**
* @param string $method The HTTP method used to make the request
@ -83,13 +85,15 @@ class PageRequestEvent extends Event
$this->path = $path;
$this->GET = $get;
$this->POST = $post;
$this->is_authed = $user->check_auth_token();
$this->is_authed = (
defined("UNITTEST")
|| (isset($_POST["auth_token"]) && $_POST["auth_token"] == $user->get_auth_token())
);
// break the path into parts
$args = explode('/', $path);
$this->args = $args;
$this->arg_count = count($args);
}
public function get_GET(string $key): ?string
@ -166,10 +170,24 @@ class PageRequestEvent extends Event
*
* If it matches, store the remaining path elements in $args
*/
public function page_matches(string $name, ?string $method = null, ?bool $authed = null, ?string $permission = null): bool
{
public function page_matches(
string $name,
?string $method = null,
?bool $authed = null,
?string $permission = null,
bool $paged = false,
): bool {
global $user;
if($paged) {
if($this->page_matches("$name/{page_num}", $method, $authed, $permission, false)) {
$pn = $this->get_arg("page_num");
if(is_numberish($pn)) {
return true;
}
}
}
assert($method === null || in_array($method, ["GET", "POST", "OPTIONS"]));
$authed = $authed ?? $method == "POST";
@ -180,12 +198,15 @@ class PageRequestEvent extends Event
// check if the path matches
$parts = explode("/", $name);
$this->part_count = count($parts);
if ($this->part_count > $this->arg_count) {
$part_count = count($parts);
if ($part_count != count($this->args)) {
return false;
}
for ($i = 0; $i < $this->part_count; $i++) {
if ($parts[$i] != $this->args[$i]) {
$this->named_args = [];
for ($i = 0; $i < $part_count; $i++) {
if (str_starts_with($parts[$i], "{")) {
$this->named_args[substr($parts[$i], 1, -1)] = $this->args[$i];
} elseif ($parts[$i] != $this->args[$i]) {
return false;
}
}
@ -205,103 +226,30 @@ class PageRequestEvent extends Event
/**
* Get the n th argument of the page request (if it exists.)
*/
public function get_arg(int $n): string
public function get_arg(string $n, ?string $default = null): string
{
$offset = $this->part_count + $n;
if ($offset >= 0 && $offset < $this->arg_count) {
return rawurldecode($this->args[$offset]);
if(array_key_exists($n, $this->named_args)) {
return rawurldecode($this->named_args[$n]);
} elseif($default !== null) {
return $default;
} else {
$nm1 = $this->arg_count - 1;
throw new UserErrorException("Requested an invalid page argument {$offset} / {$nm1}");
throw new UserErrorException("Page argument {$n} is missing");
}
}
/**
* If page arg $n is set, then treat that as a 1-indexed page number
* and return a 0-indexed page number less than $max; else return 0
*/
public function try_page_num(int $n, ?int $max = null): int
public function get_iarg(string $n, ?int $default = null): int
{
if ($this->count_args() > $n) {
$i = $this->get_arg($n);
if (is_numberish($i) && int_escape($i) > 0) {
return page_number($i, $max);
} else {
return 0;
if(array_key_exists($n, $this->named_args)) {
if(is_numberish($this->named_args[$n]) === false) {
throw new UserErrorException("Page argument {$n} exists but is not numeric");
}
return int_escape($this->named_args[$n]);
} elseif($default !== null) {
return $default;
} else {
return 0;
throw new UserErrorException("Page argument {$n} is missing");
}
}
/**
* Returns the number of arguments the page request has.
*/
public function count_args(): int
{
return $this->arg_count - $this->part_count;
}
/*
* Many things use these functions
*/
/**
* @return string[]
*/
public function get_search_terms(): array
{
$search_terms = [];
if ($this->count_args() === 2) {
$str = $this->get_arg(0);
// decode legacy caret-encoding just in case
// somebody has bookmarked such a URL
$from_caret = [
"^" => "^",
"s" => "/",
"b" => "\\",
"q" => "?",
"a" => "&",
"d" => ".",
];
$out = "";
$length = strlen($str);
for ($i = 0; $i < $length; $i++) {
if ($str[$i] == "^") {
$i++;
$out .= $from_caret[$str[$i]] ?? '';
} else {
$out .= $str[$i];
}
}
$str = $out;
// end legacy
$search_terms = Tag::explode($str);
}
return $search_terms;
}
public function get_page_number(): int
{
$page_number = 1;
if ($this->count_args() === 1) {
$page_number = int_escape($this->get_arg(0));
} elseif ($this->count_args() === 2) {
$page_number = int_escape($this->get_arg(1));
}
if ($page_number === 0) {
$page_number = 1;
} // invalid -> 0
return $page_number;
}
public function get_page_size(): int
{
global $config;
return $config->get_int(IndexConfig::IMAGES);
}
}

View file

@ -18,13 +18,13 @@ use function MicroHTML\SELECT;
use function MicroHTML\SPAN;
use function MicroHTML\{TABLE,THEAD,TFOOT,TR,TH,TD};
function SHM_FORM(string $target, string $method = "POST", bool $multipart = false, string $form_id = "", string $onsubmit = "", string $name = ""): HTMLElement
function SHM_FORM(string $target, bool $multipart = false, string $form_id = "", string $onsubmit = "", string $name = ""): HTMLElement
{
global $user;
$attrs = [
"action" => make_link($target),
"method" => $method
"method" => 'POST'
];
if ($form_id) {
@ -39,10 +39,10 @@ function SHM_FORM(string $target, string $method = "POST", bool $multipart = fal
if ($name) {
$attrs["name"] = $name;
}
return FORM(
$attrs,
INPUT(["type" => "hidden", "name" => "q", "value" => $target]),
$method == "GET" ? "" : $user->get_auth_microhtml()
INPUT(["type" => "hidden", "name" => "auth_token", "value" => $user->get_auth_token()])
);
}

View file

@ -106,6 +106,7 @@ if(class_exists("\\PHPUnit\\Framework\\TestCase")) {
if (str_contains($page_name, "?")) {
throw new \RuntimeException("Query string included in page name");
}
$_SERVER['REQUEST_METHOD'] = $method;
$_SERVER['REQUEST_URI'] = make_link($page_name, http_build_query($get_args));
$_GET = $get_args;
$_POST = $post_args;

View file

@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace Shimmie2;
use PHPUnit\Framework\TestCase;
class PageRequestEventTest extends TestCase
{
public function testPageMatches(): void
{
$e = new PageRequestEvent("GET", "foo/bar", [], []);
$this->assertFalse($e->page_matches("foo"));
$this->assertFalse($e->page_matches("foo/qux"));
$this->assertTrue($e->page_matches("foo/bar"));
$this->assertFalse($e->page_matches("foo/bar/baz"));
$this->assertFalse($e->page_matches("{thing}"));
$this->assertTrue($e->page_matches("foo/{thing}"));
$this->assertEquals("bar", $e->get_arg('thing'));
$this->assertTrue($e->page_matches("{thing}/bar"));
$this->assertEquals("foo", $e->get_arg('thing'));
$this->assertFalse($e->page_matches("qux/{thing}"));
$this->assertFalse($e->page_matches("foo/{thing}/long"));
}
public function testPageMatchesPaged(): void
{
$e = new PageRequestEvent("GET", "foo/bar/4", [], []);
$this->assertFalse($e->page_matches("foo", paged: true));
$this->assertEquals(1, $e->get_iarg('page_num', 1));
$this->assertFalse($e->page_matches("foo/qux", paged: true));
$this->assertTrue($e->page_matches("foo/bar", paged: true));
$this->assertEquals(4, $e->get_iarg('page_num', 1));
$this->assertFalse($e->page_matches("foo/bar/baz", paged: true));
$this->assertFalse($e->page_matches("{thing}", paged: true));
$this->assertTrue($e->page_matches("foo/{thing}", paged: true));
$this->assertEquals("bar", $e->get_arg('thing'));
$this->assertEquals(4, $e->get_iarg('page_num', 1));
$this->assertTrue($e->page_matches("{thing}/bar", paged: true));
$this->assertEquals("foo", $e->get_arg('thing'));
$this->assertEquals(4, $e->get_iarg('page_num', 1));
$this->assertFalse($e->page_matches("qux/{thing}", paged: true));
$this->assertFalse($e->page_matches("foo/{thing}/long", paged: true));
}
}

View file

@ -27,8 +27,8 @@ class UrlsTest extends TestCase
*/
$gst = function (array $terms): array {
$pre = new PageRequestEvent("GET", _get_query(search_link($terms)), [], []);
$pre->page_matches("post/list");
return $pre->get_search_terms();
$pre->page_matches("post/list/{search}/{page}");
return Tag::explode($pre->get_arg('search'));
};
global $config;

View file

@ -262,32 +262,4 @@ class User
$addr = get_session_ip($config);
return md5(md5($this->passhash . $addr) . "salty-csrf-" . $salt);
}
public function get_auth_html(): string
{
$at = $this->get_auth_token();
return '<input type="hidden" name="auth_token" value="'.$at.'">';
}
// Temporary? This should eventually become get_auth_html (probably with a different name?).
public function get_auth_microhtml(): HTMLElement
{
$at = $this->get_auth_token();
return INPUT(["type" => "hidden", "name" => "auth_token", "value" => $at]);
}
public function check_auth_token(): bool
{
if (defined("UNITTEST")) {
return true;
}
return (isset($_POST["auth_token"]) && $_POST["auth_token"] == $this->get_auth_token());
}
public function ensure_authed(): void
{
if (!$this->check_auth_token()) {
die("Invalid auth token");
}
}
}

View file

@ -737,14 +737,10 @@ function show_ip(string $ip, string $ban_reason): string
/**
* Make a form tag with relevant auth token and stuff
*/
function make_form(string $target, string $method = "POST", bool $multipart = false, string $form_id = "", string $onsubmit = ""): string
function make_form(string $target, bool $multipart = false, string $form_id = "", string $onsubmit = "", string $name = ""): string
{
global $user;
if ($method == "GET") {
die("make_form: GET method is not supported");
} else {
$extra_inputs = $user->get_auth_html();
}
$at = $user->get_auth_token();
$extra = empty($form_id) ? '' : 'id="'. $form_id .'"';
if ($multipart) {
@ -753,7 +749,11 @@ function make_form(string $target, string $method = "POST", bool $multipart = fa
if ($onsubmit) {
$extra .= ' onsubmit="'.$onsubmit.'"';
}
return '<form action="'.$target.'" method="'.$method.'" '.$extra.'>'.$extra_inputs;
if ($name) {
$extra .= ' name="'.$name.'"';
}
return '<form action="'.$target.'" method="POST" '.$extra.'>'.
'<input type="hidden" name="auth_token" value="'.$at.'">';
}
const BYTE_DENOMINATIONS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

View file

@ -49,23 +49,21 @@ class AdminPage extends Extension
{
global $database, $page, $user;
if ($event->page_matches("admin", permission: Permissions::MANAGE_ADMINTOOLS)) {
if ($event->count_args() == 0) {
send_event(new AdminBuildingEvent($page));
} else {
$action = $event->get_arg(0);
$aae = new AdminActionEvent($action, $event->POST);
if ($event->page_matches("admin", method: "GET", permission: Permissions::MANAGE_ADMINTOOLS)) {
send_event(new AdminBuildingEvent($page));
}
if ($event->page_matches("admin/{action}", method: "POST", permission: Permissions::MANAGE_ADMINTOOLS)) {
$action = $event->get_arg('action');
$aae = new AdminActionEvent($action, $event->POST);
$user->ensure_authed();
log_info("admin", "Util: $action");
shm_set_timeout(null);
$database->set_timeout(null);
send_event($aae);
log_info("admin", "Util: $action");
shm_set_timeout(null);
$database->set_timeout(null);
send_event($aae);
if ($aae->redirect) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
if ($aae->redirect) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
}
}

View file

@ -65,51 +65,49 @@ class AliasEditor extends Extension
{
global $config, $database, $page, $user;
if ($event->page_matches("alias")) {
if ($event->page_matches("alias/add", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
$input = validate_input(["c_oldtag" => "string", "c_newtag" => "string"]);
try {
send_event(new AddAliasEvent($input['c_oldtag'], $input['c_newtag']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
} catch (AddAliasException $ex) {
$this->theme->display_error(500, "Error adding alias", $ex->getMessage());
}
}
if ($event->page_matches("alias/remove", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
$input = validate_input(["d_oldtag" => "string"]);
send_event(new DeleteAliasEvent($input['d_oldtag']));
if ($event->page_matches("alias/add", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
$input = validate_input(["c_oldtag" => "string", "c_newtag" => "string"]);
try {
send_event(new AddAliasEvent($input['c_oldtag'], $input['c_newtag']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
} catch (AddAliasException $ex) {
$this->theme->display_error(500, "Error adding alias", $ex->getMessage());
}
if ($event->page_matches("alias/list")) {
$t = new AliasTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$t->size = $config->get_int('alias_items_per_page', 30);
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
$t->create_url = make_link("alias/add");
$t->delete_url = make_link("alias/remove");
}
$this->theme->display_aliases($t->table($t->query()), $t->paginator());
}
if ($event->page_matches("alias/remove", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
$input = validate_input(["d_oldtag" => "string"]);
send_event(new DeleteAliasEvent($input['d_oldtag']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
}
if ($event->page_matches("alias/list")) {
$t = new AliasTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$t->size = $config->get_int('alias_items_per_page', 30);
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
$t->create_url = make_link("alias/add");
$t->delete_url = make_link("alias/remove");
}
if ($event->page_matches("alias/export")) {
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::CSV);
$page->set_filename("aliases.csv");
$page->set_data($this->get_alias_csv($database));
}
if ($event->page_matches("alias/import", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
if (count($_FILES) > 0) {
$tmp = $_FILES['alias_file']['tmp_name'];
$contents = file_get_contents_ex($tmp);
$this->add_alias_csv($contents);
log_info("alias_editor", "Imported aliases from file", "Imported aliases"); # FIXME: how many?
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
} else {
$this->theme->display_error(400, "No File Specified", "You have to upload a file");
}
$this->theme->display_aliases($t->table($t->query()), $t->paginator());
}
if ($event->page_matches("alias/export/aliases.csv")) {
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::CSV);
$page->set_filename("aliases.csv");
$page->set_data($this->get_alias_csv($database));
}
if ($event->page_matches("alias/import", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
if (count($_FILES) > 0) {
$tmp = $_FILES['alias_file']['tmp_name'];
$contents = file_get_contents_ex($tmp);
$this->add_alias_csv($contents);
log_info("alias_editor", "Imported aliases from file", "Imported aliases"); # FIXME: how many?
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
} else {
$this->theme->display_error(400, "No File Specified", "You have to upload a file");
}
}
}

View file

@ -40,15 +40,15 @@ class Approval extends Extension
{
global $page, $user;
if ($event->page_matches("approve_image", method: "POST", permission: Permissions::APPROVE_IMAGE)) {
$image_id = int_escape(null_throws($event->get_arg(0)));
if ($event->page_matches("approve_image/{image_id}", method: "POST", permission: Permissions::APPROVE_IMAGE)) {
$image_id = int_escape($event->get_arg('image_id'));
self::approve_image($image_id);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/" . $image_id));
}
if ($event->page_matches("disapprove_image", method: "POST", permission: Permissions::APPROVE_IMAGE)) {
$image_id = int_escape(null_throws($event->get_arg(0)));
if ($event->page_matches("disapprove_image/{image_id}", method: "POST", permission: Permissions::APPROVE_IMAGE)) {
$image_id = int_escape($event->get_arg('image_id'));
self::disapprove_image($image_id);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$image_id));

View file

@ -169,8 +169,8 @@ class Artists extends Extension
{
global $page, $user;
if ($event->page_matches("artist/list")) {
$this->get_listing(clamp(int_escape($event->get_arg(0)), 1, null) - 1);
if ($event->page_matches("artist/list/{page}")) {
$this->get_listing(page_number($event->get_arg('page')));
$this->theme->sidebar_options("neutral");
}
if ($event->page_matches("artist/new")) {
@ -197,8 +197,8 @@ class Artists extends Extension
$this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist.");
}
}
if ($event->page_matches("artist/view")) {
$artistID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/view/{artistID}")) {
$artistID = $event->get_iarg('artistID');
$artist = $this->get_artist($artistID);
$aliases = $this->get_alias($artist['id']);
$members = $this->get_members($artist['id']);
@ -220,8 +220,8 @@ class Artists extends Extension
$this->theme->sidebar_options("editor", $artistID, $userIsAdmin);
}
if ($event->page_matches("artist/edit")) {
$artistID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/edit/{artistID}")) {
$artistID = $event->get_iarg('artistID');
$artist = $this->get_artist($artistID);
$aliases = $this->get_alias($artistID);
$members = $this->get_members($artistID);
@ -252,8 +252,8 @@ class Artists extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/nuke/" . $artistID));
}
if ($event->page_matches("artist/nuke")) {
$artistID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/nuke/{artistID}")) {
$artistID = $event->get_iarg('artistID');
$this->delete_artist($artistID); // this will delete the artist, its alias, its urls and its members
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/list"));
@ -276,15 +276,15 @@ class Artists extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
}
if ($event->page_matches("artist/alias/delete")) {
$aliasID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/alias/delete/{aliasID}")) {
$aliasID = $event->get_iarg('aliasID');
$artistID = $this->get_artistID_by_aliasID($aliasID);
$this->delete_alias($aliasID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
}
if ($event->page_matches("artist/alias/edit")) {
$aliasID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/alias/edit/{aliasID}")) {
$aliasID = $event->get_iarg('aliasID');
$alias = $this->get_alias_by_id($aliasID);
$this->theme->show_alias_editor($alias);
}
@ -301,15 +301,15 @@ class Artists extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
}
if ($event->page_matches("artist/url/delete")) {
$urlID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/url/delete/{urlID}")) {
$urlID = $event->get_iarg('urlID');
$artistID = $this->get_artistID_by_urlID($urlID);
$this->delete_url($urlID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
}
if ($event->page_matches("artist/url/edit")) {
$urlID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/url/edit/{urlID}")) {
$urlID = $event->get_iarg('urlID');
$url = $this->get_url_by_id($urlID);
$this->theme->show_url_editor($url);
}
@ -326,15 +326,15 @@ class Artists extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
}
if ($event->page_matches("artist/member/delete")) {
$memberID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/member/delete/{memberID}")) {
$memberID = $event->get_iarg('memberID');
$artistID = $this->get_artistID_by_memberID($memberID);
$this->delete_member($memberID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
}
if ($event->page_matches("artist/member/edit")) {
$memberID = int_escape($event->get_arg(0));
if ($event->page_matches("artist/member/edit/{memberID}")) {
$memberID = $event->get_iarg('memberID');
$member = $this->get_member_by_id($memberID);
$this->theme->show_member_editor($member);
}

View file

@ -33,46 +33,39 @@ class ArtistsTheme extends Themelet
$html = "";
if ($mode == "neutral") {
$html = "<form method='post' action='".make_link("artist/new_artist")."'>
".$user->get_auth_html()."
$html = make_form(make_link("artist/new_artist"))."
<input type='submit' name='edit' id='edit' value='New Artist'/>
</form>";
}
if ($mode == "editor") {
$html = "<form method='post' action='".make_link("artist/new_artist")."'>
".$user->get_auth_html()."
$html = make_form(make_link("artist/new_artist"))."
<input type='submit' name='edit' value='New Artist'/>
</form>
<form method='post' action='".make_link("artist/edit_artist")."'>
".$user->get_auth_html()."
".make_form(make_link("artist/edit_artist"))."
<input type='submit' name='edit' value='Edit Artist'/>
<input type='hidden' name='artist_id' value='".$artistID."'>
</form>";
if ($is_admin) {
$html .= "<form method='post' action='".make_link("artist/nuke_artist")."'>
".$user->get_auth_html()."
$html .= make_form(make_link("artist/nuke_artist"))."
<input type='submit' name='edit' value='Delete Artist'/>
<input type='hidden' name='artist_id' value='".$artistID."'>
</form>";
}
$html .= "<form method='post' action='".make_link("artist/add_alias")."'>
".$user->get_auth_html()."
$html .= make_form(make_link("artist/add_alias"))."
<input type='submit' name='edit' value='Add Alias'/>
<input type='hidden' name='artist_id' value='".$artistID."'>
</form>
<form method='post' action='".make_link("artist/add_member")."'>
".$user->get_auth_html()."
".make_form(make_link("artist/add_member"))."
<input type='submit' name='edit' value='Add Member'/>
<input type='hidden' name='artist_id' value='".$artistID."'>
</form>
<form method='post' action='".make_link("artist/add_url")."'>
".$user->get_auth_html()."
".make_form(make_link("artist/add_url"))."
<input type='submit' name='edit' value='Add Url'/>
<input type='hidden' name='artist_id' value='".$artistID."'>
</form>";
@ -127,9 +120,7 @@ class ArtistsTheme extends Themelet
$urlsString = substr($urlsString, 0, strlen($urlsString) - 1);
$urlsIDsString = rtrim($urlsIDsString);
$html = '
<form method="POST" action="'.make_link("artist/edited/".$artist['id']).'">
'.$user->get_auth_html().'
$html = make_form(make_link("artist/edited/".$artist['id'])).'
<table>
<tr><td>Name:</td><td><input type="text" name="name" value="'.$artistName.'" />
<input type="hidden" name="id" value="'.$artistID.'" /></td></tr>
@ -153,8 +144,7 @@ class ArtistsTheme extends Themelet
{
global $page, $user;
$html = "<form action=".make_link("artist/create")." method='POST'>
".$user->get_auth_html()."
$html = make_form(make_link("artist/create"))."
<table>
<tr><td>Name:</td><td><input type='text' name='name' /></td></tr>
<tr><td>Aliases:</td><td><input type='text' name='aliases' /></td></tr>
@ -256,9 +246,7 @@ class ArtistsTheme extends Themelet
{
global $user;
$html = '
<form method="POST" action='.make_link("artist/alias/add").'>
'.$user->get_auth_html().'
$html = make_form(make_link("artist/alias/add")).'
<table>
<tr><td>Alias:</td><td><input type="text" name="aliases" />
<input type="hidden" name="artistID" value='.$artistID.' /></td></tr>
@ -275,9 +263,7 @@ class ArtistsTheme extends Themelet
{
global $user;
$html = '
<form method="POST" action='.make_link("artist/member/add").'>
'.$user->get_auth_html().'
$html = make_form(make_link("artist/member/add")).'
<table>
<tr><td>Members:</td><td><input type="text" name="members" />
<input type="hidden" name="artistID" value='.$artistID.' /></td></tr>
@ -294,9 +280,7 @@ class ArtistsTheme extends Themelet
{
global $user;
$html = '
<form method="POST" action='.make_link("artist/url/add").'>
'.$user->get_auth_html().'
$html = make_form(make_link("artist/url/add")).'
<table>
<tr><td>URL:</td><td><textarea name="urls"></textarea>
<input type="hidden" name="artistID" value='.$artistID.' /></td></tr>
@ -316,9 +300,7 @@ class ArtistsTheme extends Themelet
{
global $user;
$html = '
<form method="POST" action="'.make_link("artist/alias/edited/".$alias['id']).'">
'.$user->get_auth_html().'
$html = make_form(make_link("artist/alias/edited/".$alias['id'])).'
<label for="alias">Alias:</label>
<input type="text" name="alias" id="alias" value="'.$alias['alias'].'" />
<input type="hidden" name="aliasID" value="'.$alias['id'].'" />
@ -337,9 +319,7 @@ class ArtistsTheme extends Themelet
{
global $user;
$html = '
<form method="POST" action="'.make_link("artist/url/edited/".$url['id']).'">
'.$user->get_auth_html().'
$html = make_form(make_link("artist/url/edited/".$url['id'])).'
<label for="url">URL:</label>
<input type="text" name="url" id="url" value="'.$url['url'].'" />
<input type="hidden" name="urlID" value="'.$url['id'].'" />
@ -358,9 +338,7 @@ class ArtistsTheme extends Themelet
{
global $user;
$html = '
<form method="POST" action="'.make_link("artist/member/edited/".$member['id']).'">
'.$user->get_auth_html().'
$html = make_form(make_link("artist/member/edited/".$member['id'])).'
<label for="name">Member name:</label>
<input type="text" name="name" id="name" value="'.$member['name'].'" />
<input type="hidden" name="memberID" value="'.$member['id'].'" />

View file

@ -71,51 +71,49 @@ class AutoTagger extends Extension
{
global $config, $database, $page, $user;
if ($event->page_matches("auto_tag")) {
if ($event->page_matches("auto_tag/add", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
$input = validate_input(["c_tag" => "string", "c_additional_tags" => "string"]);
try {
send_event(new AddAutoTagEvent($input['c_tag'], $input['c_additional_tags']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("auto_tag/list"));
} catch (AddAutoTagException $ex) {
$this->theme->display_error(500, "Error adding auto-tag", $ex->getMessage());
}
}
if ($event->page_matches("auto_tag/remove", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
$input = validate_input(["d_tag" => "string"]);
send_event(new DeleteAutoTagEvent($input['d_tag']));
if ($event->page_matches("auto_tag/add", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
$input = validate_input(["c_tag" => "string", "c_additional_tags" => "string"]);
try {
send_event(new AddAutoTagEvent($input['c_tag'], $input['c_additional_tags']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("auto_tag/list"));
} catch (AddAutoTagException $ex) {
$this->theme->display_error(500, "Error adding auto-tag", $ex->getMessage());
}
if ($event->page_matches("auto_tag/list")) {
$t = new AutoTaggerTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$t->size = $config->get_int(AutoTaggerConfig::ITEMS_PER_PAGE, 30);
if ($user->can(Permissions::MANAGE_AUTO_TAG)) {
$t->create_url = make_link("auto_tag/add");
$t->delete_url = make_link("auto_tag/remove");
}
$this->theme->display_auto_tagtable($t->table($t->query()), $t->paginator());
}
if ($event->page_matches("auto_tag/remove", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
$input = validate_input(["d_tag" => "string"]);
send_event(new DeleteAutoTagEvent($input['d_tag']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("auto_tag/list"));
}
if ($event->page_matches("auto_tag/list")) {
$t = new AutoTaggerTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$t->size = $config->get_int(AutoTaggerConfig::ITEMS_PER_PAGE, 30);
if ($user->can(Permissions::MANAGE_AUTO_TAG)) {
$t->create_url = make_link("auto_tag/add");
$t->delete_url = make_link("auto_tag/remove");
}
if ($event->page_matches("auto_tag/export")) {
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::CSV);
$page->set_filename("auto_tag.csv");
$page->set_data($this->get_auto_tag_csv($database));
}
if ($event->page_matches("auto_tag/import", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
if (count($_FILES) > 0) {
$tmp = $_FILES['auto_tag_file']['tmp_name'];
$contents = file_get_contents_ex($tmp);
$count = $this->add_auto_tag_csv($contents);
log_info(AutoTaggerInfo::KEY, "Imported $count auto-tag definitions from file from file", "Imported $count auto-tag definitions");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("auto_tag/list"));
} else {
$this->theme->display_error(400, "No File Specified", "You have to upload a file");
}
$this->theme->display_auto_tagtable($t->table($t->query()), $t->paginator());
}
if ($event->page_matches("auto_tag/export/auto_tag.csv")) {
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::CSV);
$page->set_filename("auto_tag.csv");
$page->set_data($this->get_auto_tag_csv($database));
}
if ($event->page_matches("auto_tag/import", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
if (count($_FILES) > 0) {
$tmp = $_FILES['auto_tag_file']['tmp_name'];
$contents = file_get_contents_ex($tmp);
$count = $this->add_auto_tag_csv($contents);
log_info(AutoTaggerInfo::KEY, "Imported $count auto-tag definitions from file from file", "Imported $count auto-tag definitions");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("auto_tag/list"));
} else {
$this->theme->display_error(400, "No File Specified", "You have to upload a file");
}
}
}

View file

@ -25,7 +25,7 @@ class AutoTaggerTheme extends Themelet
";
$bulk_html = "
".make_form(make_link("auto_tag/import"), 'POST', true)."
".make_form(make_link("auto_tag/import"), multipart: true)."
<input type='file' name='auto_tag_file'>
<input type='submit' value='Upload List'>
</form>

View file

@ -68,38 +68,36 @@ class Blocks extends Extension
}
}
if ($event->page_matches("blocks", permission: Permissions::MANAGE_BLOCKS)) {
if ($event->page_matches("blocks/add", method: "POST")) {
$database->execute("
if ($event->page_matches("blocks/add", method: "POST", permission: Permissions::MANAGE_BLOCKS)) {
$database->execute("
INSERT INTO blocks (pages, title, area, priority, content, userclass)
VALUES (:pages, :title, :area, :priority, :content, :userclass)
", ['pages' => $event->req_POST('pages'), 'title' => $event->req_POST('title'), 'area' => $event->req_POST('area'), 'priority' => (int)$event->req_POST('priority'), 'content' => $event->req_POST('content'), 'userclass' => $event->req_POST('userclass')]);
log_info("blocks", "Added Block #".($database->get_last_insert_id('blocks_id_seq'))." (".$event->req_POST('title').")");
$cache->delete("blocks");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blocks/list"));
}
if ($event->page_matches("blocks/update", method: "POST")) {
if (!empty($event->req_POST('delete'))) {
$database->execute("
log_info("blocks", "Added Block #".($database->get_last_insert_id('blocks_id_seq'))." (".$event->req_POST('title').")");
$cache->delete("blocks");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blocks/list"));
}
if ($event->page_matches("blocks/update", method: "POST", permission: Permissions::MANAGE_BLOCKS)) {
if (!empty($event->req_POST('delete'))) {
$database->execute("
DELETE FROM blocks
WHERE id=:id
", ['id' => $event->req_POST('id')]);
log_info("blocks", "Deleted Block #".$event->req_POST('id'));
} else {
$database->execute("
log_info("blocks", "Deleted Block #".$event->req_POST('id'));
} else {
$database->execute("
UPDATE blocks SET pages=:pages, title=:title, area=:area, priority=:priority, content=:content, userclass=:userclass
WHERE id=:id
", ['pages' => $event->req_POST('pages'), 'title' => $event->req_POST('title'), 'area' => $event->req_POST('area'), 'priority' => (int)$event->req_POST('priority'), 'content' => $event->req_POST('content'), 'userclass' => $event->req_POST('userclass'), 'id' => $event->req_POST('id')]);
log_info("blocks", "Updated Block #".$event->req_POST('id')." (".$event->req_POST('title').")");
}
$cache->delete("blocks");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blocks/list"));
}
if ($event->page_matches("blocks/list")) {
$this->theme->display_blocks($database->get_all("SELECT * FROM blocks ORDER BY area, priority"));
log_info("blocks", "Updated Block #".$event->req_POST('id')." (".$event->req_POST('title').")");
}
$cache->delete("blocks");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blocks/list"));
}
if ($event->page_matches("blocks/list", permission: Permissions::MANAGE_BLOCKS)) {
$this->theme->display_blocks($database->get_all("SELECT * FROM blocks ORDER BY area, priority"));
}
}
}

View file

@ -96,8 +96,7 @@ class BlotterTheme extends Themelet
<td>$entry_date</td>
<td>$entry_text</td>
<td>$important</td>
<td><form name='remove$id' method='post' action='".make_link("blotter/remove")."'>
".$user->get_auth_html()."
<td>".make_form(make_link("blotter/remove"), name: "remove$id")."
<input type='hidden' name='id' value='$id' />
<input type='submit' style='width: 100%;' value='Remove' />
</form>

View file

@ -48,14 +48,14 @@ class BrowserSearch extends Extension
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::XML);
$page->set_data($xml);
} elseif ($event->page_matches("browser_search")) {
} elseif ($event->page_matches("browser_search/{tag_search}")) {
$suggestions = $config->get_string("search_suggestions_results_order");
if ($suggestions == "n") {
return;
}
// We have to build some json stuff
$tag_search = $event->get_arg(0);
$tag_search = $event->get_arg('tag_search');
// Now to get DB results
if ($suggestions == "a") {

View file

@ -36,7 +36,7 @@ class BulkActionsTheme extends Themelet
}
foreach ($actions as $action) {
$body .= "<div class='bulk_action'>" . make_form(make_link("bulk_action"), "POST", false, "", "return validate_selections(this,'" . html_escape($action["confirmation_message"]) . "');") .
$body .= "<div class='bulk_action'>" . make_form(make_link("bulk_action"), onsubmit: "return validate_selections(this,'" . html_escape($action["confirmation_message"]) . "');") .
"<input type='hidden' name='bulk_query' value='" . html_escape($query) . "'>" .
"<input type='hidden' name='bulk_selected_ids' />" .
"<input type='hidden' name='bulk_action' value='" . $action["action"] . "' />" .

View file

@ -212,12 +212,12 @@ class CommentList extends Extension
$this->theme->display_error(403, "Comment Blocked", $ex->getMessage());
}
}
if ($event->page_matches("comment/delete", permission: Permissions::DELETE_COMMENT)) {
if ($event->page_matches("comment/delete/{comment_id}/{image_id}", permission: Permissions::DELETE_COMMENT)) {
// FIXME: post, not args
send_event(new CommentDeletionEvent(int_escape($event->get_arg(0))));
send_event(new CommentDeletionEvent($event->get_iarg('comment_id')));
$page->flash("Deleted comment");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link("post/view/" . $event->get_arg(1))));
$page->set_redirect(referer_or(make_link("post/view/" . $event->get_iarg('image_id'))));
}
if ($event->page_matches("comment/bulk_delete", method: "POST", permission: Permissions::DELETE_COMMENT)) {
$ip = $event->req_POST('ip');
@ -237,7 +237,7 @@ class CommentList extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
if ($event->page_matches("comment/list")) {
if ($event->page_matches("comment/list", paged: true)) {
$threads_per_page = 10;
$where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : "";
@ -248,7 +248,7 @@ class CommentList extends Extension
") / $threads_per_page), 600);
$total_pages = max($total_pages, 1);
$current_page = $event->try_page_num(1, $total_pages);
$current_page = $event->get_iarg('page_num', 1) - 1;
$start = $threads_per_page * $current_page;
$result = $database->execute("
@ -286,9 +286,9 @@ class CommentList extends Extension
$this->theme->display_comment_list($images, $current_page + 1, $total_pages, $user->can(Permissions::CREATE_COMMENT));
}
if ($event->page_matches("comment/beta-search")) {
$search = $event->get_arg(0);
$page_num = $event->try_page_num(1);
if ($event->page_matches("comment/beta-search/{search}", paged: true)) {
$search = $event->get_arg('search');
$page_num = $event->get_iarg('page_num', 1) - 1;
$duser = User::by_name($search);
$i_comment_count = Comment::count_comments_by_user($duser);
$com_per_page = 50;

View file

@ -68,14 +68,10 @@ class CronUploader extends Extension
*/
public function onPageRequest(PageRequestEvent $event): void
{
global $user;
if ($event->page_matches("cron_upload")) {
if ($event->count_args() == 1 && $event->get_arg(0) == "run") {
$this->process_upload(); // Start upload
} elseif ($user->can(Permissions::CRON_RUN)) {
$this->display_documentation();
}
if ($event->page_matches("cron_upload/run")) {
$this->process_upload();
} elseif ($event->page_matches("cron_upload", permission: Permissions::CRON_RUN)) {
$this->display_documentation();
}
}

View file

@ -187,13 +187,13 @@ class CronUploaderTheme extends Themelet
$html .= "<tr><td colspan='2'><input type='submit' value='Re-stage files to queue' /></td></tr>";
$html .= "</table></form>";
$html .= make_form(make_link("admin/cron_uploader_clear_queue"), "POST", false, "", "return confirm('Are you sure you want to delete everything in the queue folder?');")
$html .= make_form(make_link("admin/cron_uploader_clear_queue"), onsubmit: "return confirm('Are you sure you want to delete everything in the queue folder?');")
."<table class='form'><tr><td>"
."<input type='submit' value='Clear queue folder'></td></tr></table></form>";
$html .= make_form(make_link("admin/cron_uploader_clear_uploaded"), "POST", false, "", "return confirm('Are you sure you want to delete everything in the uploaded folder?');")
$html .= make_form(make_link("admin/cron_uploader_clear_uploaded"), onsubmit: "return confirm('Are you sure you want to delete everything in the uploaded folder?');")
."<table class='form'><tr><td>"
."<input type='submit' value='Clear uploaded folder'></td></tr></table></form>";
$html .= make_form(make_link("admin/cron_uploader_clear_failed"), "POST", false, "", "return confirm('Are you sure you want to delete everything in the failed folder?');")
$html .= make_form(make_link("admin/cron_uploader_clear_failed"), onsubmit: "return confirm('Are you sure you want to delete everything in the failed folder?');")
."<table class='form'><tr><td>"
."<input type='submit' value='Clear failed folder'></td></tr></table></form>";
$html .= "</table>\n";

View file

@ -40,31 +40,31 @@ class DanbooruApi extends Extension
{
public function onPageRequest(PageRequestEvent $event): void
{
if ($event->page_matches("api/danbooru")) {
global $page;
global $page;
if ($event->page_matches("api/danbooru/add_post") || $event->page_matches("api/danbooru/post/create.xml")) {
// No XML data is returned from this function
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::TEXT);
$this->api_add_post();
} elseif ($event->page_matches("api/danbooru/find_posts") || $event->page_matches("api/danbooru/post/index.xml")) {
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::XML_APPLICATION);
$page->set_data((string)$this->api_find_posts($event->GET));
} elseif ($event->page_matches("api/danbooru/find_tags")) {
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::XML_APPLICATION);
$page->set_data((string)$this->api_find_tags($event->GET));
}
if ($event->page_matches("api/danbooru/add_post") || $event->page_matches("api/danbooru/post/create.xml")) {
// No XML data is returned from this function
$page->set_mime(MimeType::TEXT);
$this->api_add_post();
} elseif ($event->page_matches("api/danbooru/find_posts") || $event->page_matches("api/danbooru/post/index.xml")) {
$page->set_mime(MimeType::XML_APPLICATION);
$page->set_data((string)$this->api_find_posts($event->GET));
} elseif ($event->page_matches("api/danbooru/find_tags")) {
$page->set_mime(MimeType::XML_APPLICATION);
$page->set_data((string)$this->api_find_tags($event->GET));
}
// Hackery for danbooruup 0.3.2 providing the wrong view url. This simply redirects to the proper
// Shimmie view page
// Example: danbooruup says the url is https://shimmie/api/danbooru/post/show/123
// This redirects that to https://shimmie/post/view/123
elseif ($event->page_matches("api/danbooru/post/show")) {
$fixedlocation = make_link("post/view/" . $event->get_arg(0));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($fixedlocation);
}
// Hackery for danbooruup 0.3.2 providing the wrong view url. This simply redirects to the proper
// Shimmie view page
// Example: danbooruup says the url is https://shimmie/api/danbooru/post/show/123
// This redirects that to https://shimmie/post/view/123
elseif ($event->page_matches("api/danbooru/post/show/{id}")) {
$fixedlocation = make_link("post/view/" . $event->get_iarg('id'));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($fixedlocation);
}
}

View file

@ -10,7 +10,7 @@ class DownloadTest extends ShimmiePHPUnitTestCase
{
global $page;
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$this->get_page("image/$image_id");
$this->get_page("image/$image_id/moo.jpg");
$this->assertEquals(PageMode::FILE, $page->mode);
}
}

View file

@ -28,7 +28,7 @@ class DowntimeTheme extends Themelet
$theme_name = $config->get_string(SetupConfig::THEME);
$data_href = get_base_href();
$login_link = make_link("user_admin/login");
$auth = $user->get_auth_html();
$form = make_form($login_link);
$page->set_mode(PageMode::DATA);
$page->set_code(503);
@ -50,8 +50,7 @@ class DowntimeTheme extends Themelet
<section>
<h3>Admin Login</h3>
<div id="login" class="blockbody">
<form action="$login_link" method="POST">
$auth
$form
<table id="login_table" summary="Login Form">
<tr>
<td width="70"><label for="user">Name</label></td>

View file

@ -28,39 +28,32 @@ class ExtManager extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("ext_manager")) {
if ($user->can(Permissions::MANAGE_EXTENSION_LIST)) {
if ($event->count_args() == 1 && $event->get_arg(0) == "set" && $user->check_auth_token()) {
if (is_writable("data/config")) {
$this->set_things($event->POST);
log_warning("ext_manager", "Active extensions changed", "Active extensions changed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ext_manager"));
} else {
$this->theme->display_error(
500,
"File Operation Failed",
"The config file (data/config/extensions.conf.php) isn't writable by the web server :("
);
}
} else {
$this->theme->display_table($page, $this->get_extensions(true), true);
}
if ($event->page_matches("ext_manager/set", method: "POST", permission: Permissions::MANAGE_EXTENSION_LIST)) {
if (is_writable("data/config")) {
$this->set_things($event->POST);
log_warning("ext_manager", "Active extensions changed", "Active extensions changed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ext_manager"));
} else {
$this->theme->display_table($page, $this->get_extensions(false), false);
$this->theme->display_error(
500,
"File Operation Failed",
"The config file (data/config/extensions.conf.php) isn't writable by the web server :("
);
}
} elseif ($event->page_matches("ext_manager", method: "GET")) {
$is_admin = $user->can(Permissions::MANAGE_EXTENSION_LIST);
$this->theme->display_table($page, $this->get_extensions($is_admin), $is_admin);
}
if ($event->page_matches("ext_doc")) {
if ($event->count_args() == 1) {
$ext = $event->get_arg(0);
if (file_exists("ext/$ext/info.php")) {
$info = ExtensionInfo::get_by_key($ext);
$this->theme->display_doc($page, $info);
}
} else {
$this->theme->display_table($page, $this->get_extensions(false), false);
if ($event->page_matches("ext_doc/{ext}")) {
$ext = $event->get_arg('ext');
$info = ExtensionInfo::get_by_key($ext);
if($info) {
$this->theme->display_doc($page, $info);
}
} elseif ($event->page_matches("ext_doc")) {
$this->theme->display_table($page, $this->get_extensions(false), false);
}
}

View file

@ -67,14 +67,14 @@ class Favorites extends Extension
return;
} // FIXME: proper permissions
if ($event->page_matches("favourite/add", method: "POST")) {
$image_id = int_escape($event->get_arg(0));
if ($event->page_matches("favourite/add/{image_id}", method: "POST")) {
$image_id = $event->get_iarg('image_id');
send_event(new FavoriteSetEvent($image_id, $user, true));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
if ($event->page_matches("favourite/remove", method: "POST")) {
$image_id = int_escape($event->get_arg(0));
if ($event->page_matches("favourite/remove/{image_id}", method: "POST")) {
$image_id = $event->get_iarg('image_id');
send_event(new FavoriteSetEvent($image_id, $user, false));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));

View file

@ -18,27 +18,25 @@ class Featured extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $config, $page, $user;
if ($event->page_matches("featured_image")) {
if ($event->page_matches("featured_image/set", method: "POST", permission: Permissions::EDIT_FEATURE)) {
$id = int_escape($event->req_POST('image_id'));
$config->set_int("featured_id", $id);
log_info("featured", "Featured post set to >>$id", "Featured post set");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$id"));
if ($event->page_matches("featured_image/set", method: "POST", permission: Permissions::EDIT_FEATURE)) {
$id = int_escape($event->req_POST('image_id'));
$config->set_int("featured_id", $id);
log_info("featured", "Featured post set to >>$id", "Featured post set");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$id"));
}
if ($event->page_matches("featured_image/download")) {
$image = Image::by_id($config->get_int("featured_id"));
if (!is_null($image)) {
$page->set_mode(PageMode::DATA);
$page->set_mime($image->get_mime());
$page->set_data(file_get_contents_ex($image->get_image_filename()));
}
if ($event->page_matches("featured_image/download")) {
$image = Image::by_id($config->get_int("featured_id"));
if (!is_null($image)) {
$page->set_mode(PageMode::DATA);
$page->set_mime($image->get_mime());
$page->set_data(file_get_contents_ex($image->get_image_filename()));
}
}
if ($event->page_matches("featured_image/view")) {
$image = Image::by_id($config->get_int("featured_id"));
if (!is_null($image)) {
send_event(new DisplayingImageEvent($image));
}
}
if ($event->page_matches("featured_image/view")) {
$image = Image::by_id($config->get_int("featured_id"));
if (!is_null($image)) {
send_event(new DisplayingImageEvent($image));
}
}
}

View file

@ -99,33 +99,22 @@ class Forum extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("forum/index")) {
if ($event->count_args() >= 2) {
$pageNumber = page_number($event->get_arg(1));
} else {
$pageNumber = 0;
}
if ($event->page_matches("forum/index", paged: true)) {
$pageNumber = $event->get_iarg('page_num', 1) - 1;
$this->show_last_threads($page, $pageNumber, $user->can(Permissions::FORUM_ADMIN));
if (!$user->can(Permissions::FORUM_CREATE_THREAD)) {
$this->theme->display_new_thread_composer($page);
}
}
if ($event->page_matches("forum/view")) {
$threadID = int_escape($event->get_arg(1));
// $pageNumber = int_escape($event->get_arg(2));
if ($event->page_matches("forum/view/{threadID}", paged: true)) {
$threadID = $event->get_iarg('threadID');
$pageNumber = $event->get_iarg('page_num', 1) - 1;
$errors = $this->sanity_check_viewed_thread($threadID);
if (count($errors) > 0) {
throw new UserErrorException(implode("<br>", $errors));
}
$threadID = int_escape($event->get_arg(1));
if ($event->count_args() >= 3) {
$pageNumber = page_number($event->get_arg(2));
} else {
$pageNumber = 0;
}
$this->show_posts($threadID, $pageNumber, $user->can(Permissions::FORUM_ADMIN));
if ($user->can(Permissions::FORUM_ADMIN)) {
$this->theme->add_actions_block($page, $threadID);
@ -154,9 +143,9 @@ class Forum extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link($redirectTo));
}
if ($event->page_matches("forum/delete")) {
$threadID = int_escape($event->get_arg(1));
$postID = int_escape($event->get_arg(2));
if ($event->page_matches("forum/delete/{threadID}/{postID}")) {
$threadID = $event->get_iarg('threadID');
$postID = $event->get_iarg('postID');
if ($user->can(Permissions::FORUM_ADMIN)) {
$this->delete_post($postID);
@ -165,8 +154,8 @@ class Forum extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/view/" . $threadID));
}
if ($event->page_matches("forum/nuke")) {
$threadID = int_escape($event->get_arg(1));
if ($event->page_matches("forum/nuke/{threadID}")) {
$threadID = $event->get_iarg('threadID');
if ($user->can(Permissions::FORUM_ADMIN)) {
$this->delete_thread($threadID);

View file

@ -16,8 +16,8 @@ class SVGFileHandler extends DataHandlerExtension
public function onPageRequest(PageRequestEvent $event): void
{
global $page;
if ($event->page_matches("get_svg")) {
$id = int_escape($event->get_arg(0));
if ($event->page_matches("get_svg/{id}")) {
$id = $event->get_iarg('id');
$image = Image::by_id($id);
$hash = $image->hash;

View file

@ -46,30 +46,27 @@ class HelpPages extends Extension
{
global $page;
if ($event->page_matches("help")) {
if ($event->page_matches("help/{topic}")) {
$pages = send_event(new HelpPageListBuildingEvent())->pages;
if ($event->count_args() == 0) {
$name = array_key_first($pages);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("help/".$name));
return;
$page->set_mode(PageMode::PAGE);
$name = $event->get_arg('topic');
if (array_key_exists($name, $pages)) {
$title = $pages[$name];
} else {
$page->set_mode(PageMode::PAGE);
$name = $event->get_arg(0);
if (array_key_exists($name, $pages)) {
$title = $pages[$name];
} else {
return;
}
$this->theme->display_help_page($title);
$hpbe = send_event(new HelpPageBuildingEvent($name));
ksort($hpbe->blocks);
foreach ($hpbe->blocks as $block) {
$page->add_block($block);
}
return;
}
$this->theme->display_help_page($title);
$hpbe = send_event(new HelpPageBuildingEvent($name));
ksort($hpbe->blocks);
foreach ($hpbe->blocks as $block) {
$page->add_block($block);
}
} elseif ($event->page_matches("help")) {
$pages = send_event(new HelpPageListBuildingEvent())->pages;
$name = array_key_first($pages);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("help/".$name));
}
}

View file

@ -101,11 +101,11 @@ class ImageIO extends Extension
$page->set_redirect(referer_or(make_link(), ['post/view']));
}
}
} elseif ($event->page_matches("image")) {
$num = int_escape($event->get_arg(0));
} elseif ($event->page_matches("image/{image_id}/{filename}")) {
$num = $event->get_iarg('image_id');
$this->send_file($num, "image", $event->GET);
} elseif ($event->page_matches("thumb")) {
$num = int_escape($event->get_arg(0));
} elseif ($event->page_matches("thumb/{image_id}/{filename}")) {
$num = $event->get_iarg('image_id');
$this->send_file($num, "thumb", $event->GET);
}
}

View file

@ -89,39 +89,37 @@ class ImageBan extends Extension
{
global $database, $page, $user;
if ($event->page_matches("image_hash_ban", permission: Permissions::BAN_IMAGE)) {
if ($event->page_matches("image_hash_ban/add", method: "POST")) {
$input = validate_input(["c_hash" => "optional,string", "c_reason" => "string", "c_image_id" => "optional,int"]);
$image = isset($input['c_image_id']) ? Image::by_id($input['c_image_id']) : null;
$hash = isset($input["c_hash"]) ? $input["c_hash"] : $image->hash;
$reason = isset($input['c_reason']) ? $input['c_reason'] : "DNP";
if ($event->page_matches("image_hash_ban/add", method: "POST", permission: Permissions::BAN_IMAGE)) {
$input = validate_input(["c_hash" => "optional,string", "c_reason" => "string", "c_image_id" => "optional,int"]);
$image = isset($input['c_image_id']) ? Image::by_id($input['c_image_id']) : null;
$hash = isset($input["c_hash"]) ? $input["c_hash"] : $image->hash;
$reason = isset($input['c_reason']) ? $input['c_reason'] : "DNP";
if ($hash) {
send_event(new AddImageHashBanEvent($hash, $reason));
$page->flash("Post ban added");
if ($hash) {
send_event(new AddImageHashBanEvent($hash, $reason));
$page->flash("Post ban added");
if ($image) {
send_event(new ImageDeletionEvent($image));
$page->flash("Post deleted");
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
if ($image) {
send_event(new ImageDeletionEvent($image));
$page->flash("Post deleted");
}
}
if ($event->page_matches("image_hash_ban/remove", method: "POST")) {
$input = validate_input(["d_hash" => "string"]);
send_event(new RemoveImageHashBanEvent($input['d_hash']));
$page->flash("Post ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
}
if ($event->page_matches("image_hash_ban/list")) {
$t = new HashBanTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$this->theme->display_crud("Post Bans", $t->table($t->query()), $t->paginator());
}
}
if ($event->page_matches("image_hash_ban/remove", method: "POST", permission: Permissions::BAN_IMAGE)) {
$input = validate_input(["d_hash" => "string"]);
send_event(new RemoveImageHashBanEvent($input['d_hash']));
$page->flash("Post ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
}
if ($event->page_matches("image_hash_ban/list", permission: Permissions::BAN_IMAGE)) {
$t = new HashBanTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$this->theme->display_crud("Post Bans", $t->table($t->query()), $t->paginator());
}
}

View file

@ -27,18 +27,20 @@ class Index extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $cache, $config, $page, $user;
if ($event->page_matches("post/list")) {
if (
$event->page_matches("post/list", paged: true)
|| $event->page_matches("post/list/{search}", paged: true)
) {
if ($event->get_GET('search')) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(search_link(Tag::explode($event->get_GET('search'), false)));
return;
}
$search_terms = $event->get_search_terms();
$page_number = $event->get_page_number();
$page_size = $event->get_page_size();
$search_terms = Tag::explode($event->get_arg('search', ""), false);
$count_search_terms = count($search_terms);
$page_number = $event->get_iarg('page_num', 1);
$page_size = $config->get_int(IndexConfig::IMAGES);
try {
$fast_page_limit = 500;

View file

@ -4,8 +4,6 @@ declare(strict_types=1);
namespace Shimmie2;
use PHPUnit\Framework\Attributes\Depends;
class IndexTest extends ShimmiePHPUnitTestCase
{
public function testIndexPage(): void

View file

@ -89,7 +89,7 @@ and of course start organising your images :-)
$h_search_string = html_escape(Tag::implode($search_terms));
$h_search_link = search_link();
$h_search = "
<p><form action='$h_search_link' method='POST'>
<p><form action='$h_search_link' method='GET'>
<input type='search' name='search' value='$h_search_string' placeholder='Search' class='autocomplete_tags' />
<input type='submit' value='Find' style='display: none;' />
</form>

View file

@ -180,32 +180,28 @@ class IPBan extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
if ($event->page_matches("ip_ban", permission: Permissions::BAN_IP)) {
global $database, $page, $user;
if ($event->page_matches("ip_ban/create", method: "POST")) {
$user->ensure_authed();
$input = validate_input(["c_ip" => "string", "c_mode" => "string", "c_reason" => "string", "c_expires" => "optional,date"]);
send_event(new AddIPBanEvent($input['c_ip'], $input['c_mode'], $input['c_reason'], $input['c_expires']));
$page->flash("Ban for {$input['c_ip']} added");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list"));
}
if ($event->page_matches("ip_ban/delete", method: "POST")) {
$user->ensure_authed();
$input = validate_input(["d_id" => "int"]);
send_event(new RemoveIPBanEvent($input['d_id']));
$page->flash("Ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list"));
}
if ($event->page_matches("ip_ban/list")) {
$event->GET['c_banner'] = $user->name;
$event->GET['c_added'] = date('Y-m-d');
$t = new IPBanTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$this->theme->display_bans($page, $t->table($t->query()), $t->paginator());
}
global $database, $page, $user;
if ($event->page_matches("ip_ban/create", method: "POST", permission: Permissions::BAN_IP)) {
$input = validate_input(["c_ip" => "string", "c_mode" => "string", "c_reason" => "string", "c_expires" => "optional,date"]);
send_event(new AddIPBanEvent($input['c_ip'], $input['c_mode'], $input['c_reason'], $input['c_expires']));
$page->flash("Ban for {$input['c_ip']} added");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list"));
}
if ($event->page_matches("ip_ban/delete", method: "POST", permission: Permissions::BAN_IP)) {
$input = validate_input(["d_id" => "int"]);
send_event(new RemoveIPBanEvent($input['d_id']));
$page->flash("Ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list"));
}
if ($event->page_matches("ip_ban/list", method: "GET", permission: Permissions::BAN_IP)) {
$event->GET['c_banner'] = $user->name;
$event->GET['c_added'] = date('Y-m-d');
$t = new IPBanTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$this->theme->display_bans($page, $t->table($t->query()), $t->paginator());
}
}

View file

@ -25,7 +25,7 @@ class LogConsole extends Extension
$this->log(new LogEvent(
"access",
SCORE_LOG_INFO,
"{$event->method} {$_SERVER['REQUEST_URI']}"
"{$_SERVER['REQUEST_METHOD']} {$_SERVER['REQUEST_URI']}"
));
}

View file

@ -74,11 +74,8 @@ class Media extends Extension
{
global $page, $user;
if (
$event->page_matches("media_rescan", method: "POST") &&
$user->can(Permissions::RESCAN_MEDIA)
) {
$image = Image::by_id(int_escape($event->get_arg(0)));
if ($event->page_matches("media_rescan/{image_id}", method: "POST", permission: Permissions::RESCAN_MEDIA)) {
$image = Image::by_id($event->get_iarg('image_id'));
send_event(new MediaCheckPropertiesEvent($image));
$image->save_to_db();

View file

@ -78,21 +78,21 @@ class Notes extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("note/list")) {
$this->get_notes_list($event->try_page_num(0)); // This should show images like post/list but i don't know how do that.
if ($event->page_matches("note/list", paged: true)) {
$this->get_notes_list($event->get_iarg('page_num', 1) - 1); // This should show images like post/list but i don't know how do that.
}
if ($event->page_matches("note/requests")) {
$this->get_notes_requests($event->try_page_num(0)); // This should show images like post/list but i don't know how do that.
if ($event->page_matches("note/requests", paged: true)) {
$this->get_notes_requests($event->get_iarg('page_num', 1) - 1); // This should show images like post/list but i don't know how do that.
}
if ($event->page_matches("note/updated")) {
$this->get_histories($event->try_page_num(0));
if ($event->page_matches("note/updated", paged: true)) {
$this->get_histories($event->get_iarg('page_num', 1) - 1);
}
if ($event->page_matches("note/history")) {
$this->get_history(int_escape($event->get_arg(0)), $event->try_page_num(1));
if ($event->page_matches("note/history/{note_id}", paged: true)) {
$this->get_history($event->get_iarg('note_id'), $event->get_iarg('page_num', 1) - 1);
}
if ($event->page_matches("note/revert")) {
$noteID = int_escape($event->get_arg(0));
$reviewID = int_escape($event->get_arg(1));
if ($event->page_matches("note/revert/{noteID}/{reviewID}")) {
$noteID = $event->get_iarg('noteID');
$reviewID = $event->get_iarg('reviewID');
if (!$user->is_anonymous()) {
$this->revert_history($noteID, $reviewID);
}

View file

@ -138,8 +138,8 @@ class NumericScore extends Extension
{
global $config, $database, $user, $page;
if ($event->page_matches("numeric_score_votes")) {
$image_id = int_escape($event->get_arg(0));
if ($event->page_matches("numeric_score_votes/{image_id}")) {
$image_id = $event->get_iarg('image_id');
$x = $database->get_all(
"SELECT users.name as username, user_id, score
FROM numeric_score_votes

View file

@ -15,31 +15,26 @@ class NumericScoreTheme extends Themelet
$html = "
Current Score: $i_score
<p><form action='".make_link("numeric_score_vote")."' method='POST'>
".$user->get_auth_html()."
<p>".make_form(make_link("numeric_score_vote"))."
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='vote' value='1'>
<input type='submit' value='Vote Up'>
</form>
<form action='".make_link("numeric_score_vote")."' method='POST'>
".$user->get_auth_html()."
".make_form(make_link("numeric_score_vote"))."
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='vote' value='0'>
<input type='submit' value='Remove Vote'>
</form>
<form action='".make_link("numeric_score_vote")."' method='POST'>
".$user->get_auth_html()."
".make_form(make_link("numeric_score_vote"))."
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='vote' value='-1'>
<input type='submit' value='Vote Down'>
</form>
";
if ($user->can(Permissions::EDIT_OTHER_VOTE)) {
$html .= "
<form action='".make_link("numeric_score/remove_votes_on")."' method='POST'>
".$user->get_auth_html()."
$html .= make_form(make_link("numeric_score/remove_votes_on"))."
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='submit' value='Remove All Votes'>
</form>
@ -58,9 +53,7 @@ class NumericScoreTheme extends Themelet
public function get_nuller(User $duser): void
{
global $user, $page;
$html = "
<form action='".make_link("numeric_score/remove_votes_by")."' method='POST'>
".$user->get_auth_html()."
$html = make_form(make_link("numeric_score/remove_votes_by"))."
<input type='hidden' name='user_id' value='{$duser->id}'>
<input type='submit' value='Delete all votes by this user'>
</form>

View file

@ -227,8 +227,8 @@ class PrivMsg extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $cache, $database, $page, $user;
if ($event->page_matches("pm/read", permission: Permissions::READ_PM)) {
$pm_id = int_escape($event->get_arg(1));
if ($event->page_matches("pm/read/{pm_id}", permission: Permissions::READ_PM)) {
$pm_id = $event->get_iarg('pm_id');
$pm = $database->get_row("SELECT * FROM private_message WHERE id = :id", ["id" => $pm_id]);
if (is_null($pm)) {
$this->theme->display_error(404, "No such PM", "There is no PM #$pm_id");

View file

@ -20,7 +20,7 @@ class PrivMsgTest extends ShimmiePHPUnitTestCase
// Check that user can see own messages
$this->log_in_as_user();
$this->get_page("user");
$this->get_page("user/" . self::$user_name);
$this->assert_text("message demo to test");
// FIXME: read PM

View file

@ -47,9 +47,8 @@ class PrivMsgTheme extends Themelet
<td><a href='$pm_url'>$h_subject</a></td>
<td><a href='$from_url'>$h_from</a></td>
<td>$h_date</td>
<td><form action='$del_url' method='POST'>
<input type='hidden' name='pm_id' value='{$pm->id}'>
".$user->get_auth_html()."
<td>".make_form($del_url)."
<input type='hidden' name='pm_id' value='{$pm->id}'>
<input type='submit' value='Delete'>
</form></td>
</tr>";
@ -67,10 +66,9 @@ class PrivMsgTheme extends Themelet
$post_url = make_link("pm/send");
$h_subject = html_escape($subject);
$to_id = $to->id;
$auth = $user->get_auth_html();
$form = make_form($post_url);
$html = <<<EOD
<form action="$post_url" method="POST">
$auth
$form
<input type="hidden" name="to_id" value="$to_id">
<table style="width: 400px;" class="form">
<tr><th>Subject:</th><td><input type="text" name="subject" value="$h_subject"></td></tr>

View file

@ -237,19 +237,17 @@ class Pools extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $config, $database, $page, $user;
if ($event->page_matches("pool/list")) { //index
if (
$event->page_matches("pool/list", paged: true)
|| $event->page_matches("pool/list/{search}", paged: true)
) { //index
if ($event->get_GET('search')) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link('pool/list') . '/' . url_escape($event->get_GET('search')) . '/' . strval($event->try_page_num(1)));
$page->set_redirect(make_link('pool/list') . '/' . url_escape($event->get_GET('search')) . '/' . strval($event->page_num));
return;
}
if ($event->count_args() >= 2) { // Assume first 2 args are search and page num
$search = $event->get_arg(0); // Search is based on name comparison instead of tag search
$page_num = $event->try_page_num(1);
} else {
$search = "";
$page_num = $event->try_page_num(0);
}
$search = $event->get_arg('search', "");
$page_num = $event->get_iarg('page_num', 1) - 1;
$this->list_pools($page, $page_num, $search);
}
if ($event->page_matches("pool/new", method: "GET", permission: Permissions::POOLS_CREATE)) {
@ -271,15 +269,15 @@ class Pools extends Extension
$this->theme->display_error(400, "Error", $e->error);
}
}
if ($event->page_matches("pool/view", method: "GET")) {
$poolID = int_escape($event->get_arg(0));
$this->get_posts($event->try_page_num(1), $poolID);
if ($event->page_matches("pool/view/{poolID}", method: "GET", paged: true)) {
$poolID = $event->get_iarg('poolID');
$this->get_posts($event->get_iarg('page_num', 1) - 1, $poolID);
}
if ($event->page_matches("pool/updated")) {
$this->get_history($event->try_page_num(0));
if ($event->page_matches("pool/updated", paged: true)) {
$this->get_history($event->get_iarg('page_num', 1) - 1);
}
if ($event->page_matches("pool/revert", method: "POST", permission: Permissions::POOLS_UPDATE)) {
$historyID = int_escape($event->get_arg(0));
if ($event->page_matches("pool/revert/{historyID}", method: "POST", permission: Permissions::POOLS_UPDATE)) {
$historyID = $event->get_iarg('historyID');
$this->revert_history($historyID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/updated"));
@ -619,7 +617,7 @@ class Pools extends Extension
}
}
private function list_pools(Page $page, int $pageNumber, ?string $search): void
private function list_pools(Page $page, int $pageNumber, string $search): void
{
global $config, $database;

View file

@ -43,9 +43,8 @@ class PrivateImage extends Extension
{
global $page, $user, $user_config;
if ($event->page_matches("privatize_image", method: "POST", permission: Permissions::SET_PRIVATE_IMAGE)) {
// Try to get the image ID
$image_id = int_escape(null_throws($event->get_arg(0)));
if ($event->page_matches("privatize_image/{image_id}", method: "POST", permission: Permissions::SET_PRIVATE_IMAGE)) {
$image_id = $event->get_iarg('image_id');
$image = Image::by_id($image_id);
if ($image == null) {
throw new SCoreException("Post not found.");
@ -59,9 +58,8 @@ class PrivateImage extends Extension
$page->set_redirect(make_link("post/view/" . $image_id));
}
if ($event->page_matches("publicize_image", method: "POST")) {
// Try to get the image ID
$image_id = int_escape(null_throws($event->get_arg(0)));
if ($event->page_matches("publicize_image/{image_id}", method: "POST")) {
$image_id = $event->get_iarg('image_id');
$image = Image::by_id($image_id);
if ($image == null) {
throw new SCoreException("Post not found.");

View file

@ -13,16 +13,12 @@ class RandomImage extends Extension
{
global $page;
if ($event->page_matches("random_image")) {
if ($event->count_args() == 1) {
$action = $event->get_arg(0);
$search_terms = [];
} elseif ($event->count_args() == 2) {
$action = $event->get_arg(0);
$search_terms = Tag::explode($event->get_arg(1));
} else {
throw new SCoreException("Error: too many arguments.");
}
if (
$event->page_matches("random_image/{action}")
|| $event->page_matches("random_image/{action}/{search}")
) {
$action = $event->get_arg('action');
$search_terms = Tag::explode($event->get_arg('search', ""), false);
$image = Image::by_random($search_terms);
if (!$image) {
throw new SCoreException("Couldn't find any posts randomly");

View file

@ -27,12 +27,9 @@ class RandomList extends Extension
return;
}
if ($event->count_args() == 0) {
$search_terms = [];
} elseif ($event->count_args() == 1) {
$search_terms = explode(' ', $event->get_arg(0));
} else {
throw new SCoreException("Error: too many arguments.");
$search_terms = [];
if ($event->page_matches("random/{search}")) {
$search_terms = explode(' ', $event->get_arg('search'));
}
// set vars

View file

@ -21,25 +21,23 @@ class RegenThumb extends Extension
{
global $page, $user;
if ($event->page_matches("regen_thumb", method: "POST", permission: Permissions::DELETE_IMAGE)) {
if ($event->page_matches("regen_thumb/one")) {
$image = Image::by_id(int_escape($event->get_arg(0)));
if ($event->page_matches("regen_thumb/one/{image_id}", method: "POST", permission: Permissions::DELETE_IMAGE)) {
$image = Image::by_id($event->get_iarg('image_id'));
$this->regenerate_thumbnail($image);
$this->theme->display_results($page, $image);
}
if ($event->page_matches("regen_thumb/mass", method: "POST", permission: Permissions::DELETE_IMAGE)) {
$tags = Tag::explode(strtolower($event->req_POST('tags')), false);
$images = Search::find_images(limit: 10000, tags: $tags);
foreach ($images as $image) {
$this->regenerate_thumbnail($image);
$this->theme->display_results($page, $image);
}
if ($event->page_matches("regen_thumb/mass")) {
$tags = Tag::explode(strtolower($event->req_POST('tags')), false);
$images = Search::find_images(limit: 10000, tags: $tags);
foreach ($images as $image) {
$this->regenerate_thumbnail($image);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
}

View file

@ -50,7 +50,7 @@ class RegenThumbTheme extends Themelet
<tr><td colspan='2'><input type='submit' value='Regenerate Thumbnails'></td></tr>
</table>
</form></p>
<p>".make_form(make_link("admin/delete_thumbs"), "POST", false, "", "return confirm('Are you sure you want to delete all thumbnails?')")."
<p>".make_form(make_link("admin/delete_thumbs"), onsubmit: "return confirm('Are you sure you want to delete all thumbnails?')")."
<table class='form'>
<tr><th><label for='delete_thumb_mime'>MIME</label></th><td>
<select name='delete_thumb_mime' id='delete_thumb_mime'>

View file

@ -13,31 +13,35 @@ class ReplaceFile extends Extension
{
global $cache, $page, $user;
if ($event->page_matches("replace", permission: Permissions::REPLACE_IMAGE)) {
$image_id = int_escape($event->get_arg(0));
if ($event->page_matches("replace/{image_id}", method: "GET", permission: Permissions::REPLACE_IMAGE)) {
$image_id = $event->get_iarg('image_id');
$image = Image::by_id($image_id);
if (is_null($image)) {
throw new UploadException("Can not replace Post: No post with ID $image_id");
}
if($event->method == "GET") {
$this->theme->display_replace_page($page, $image_id);
} elseif($event->method == "POST") {
$user->ensure_authed();
if (!empty($event->get_POST("url"))) {
$tmp_filename = shm_tempnam("transload");
fetch_url($event->req_POST("url"), $tmp_filename);
send_event(new ImageReplaceEvent($image, $tmp_filename));
} elseif (count($_FILES) > 0) {
send_event(new ImageReplaceEvent($image, $_FILES["data"]['tmp_name']));
}
if($event->get_POST("source")) {
send_event(new SourceSetEvent($image, $event->req_POST("source")));
}
$cache->delete("thumb-block:{$image_id}");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
$this->theme->display_replace_page($page, $image_id);
}
if ($event->page_matches("replace/{image_id}", method: "POST", permission: Permissions::REPLACE_IMAGE)) {
$image_id = $event->get_iarg('image_id');
$image = Image::by_id($image_id);
if (is_null($image)) {
throw new UploadException("Can not replace Post: No post with ID $image_id");
}
if (!empty($event->get_POST("url"))) {
$tmp_filename = shm_tempnam("transload");
fetch_url($event->req_POST("url"), $tmp_filename);
send_event(new ImageReplaceEvent($image, $tmp_filename));
} elseif (count($_FILES) > 0) {
send_event(new ImageReplaceEvent($image, $_FILES["data"]['tmp_name']));
}
if($event->get_POST("source")) {
send_event(new SourceSetEvent($image, $event->req_POST("source")));
}
$cache->delete("thumb-block:{$image_id}");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
}

View file

@ -28,7 +28,7 @@ class ReplaceFileTheme extends Themelet
$image = Image::by_id($image_id);
$thumbnail = $this->build_thumb_html($image);
$form = SHM_FORM("replace/".$image_id, "POST", true);
$form = SHM_FORM("replace/".$image_id, multipart: true);
$form->appendChild(emptyHTML(
TABLE(
["id" => "large_upload_form", "class" => "form"],

View file

@ -51,26 +51,24 @@ class ReportImage extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("image_report")) {
if ($event->page_matches("image_report/add")) {
$image_id = int_escape($event->req_POST('image_id'));
send_event(new AddReportedImageEvent(new ImageReport($image_id, $user->id, $event->req_POST('reason'))));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
if ($event->page_matches("image_report/remove", method: "POST", permission: Permissions::VIEW_IMAGE_REPORT)) {
send_event(new RemoveReportedImageEvent(int_escape($event->req_POST('id'))));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("image_report/list"));
}
if ($event->page_matches("image_report/remove_reports_by", method: "POST", permission: Permissions::VIEW_IMAGE_REPORT)) {
$this->delete_reports_by(int_escape($event->req_POST('user_id')));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
if ($event->page_matches("image_report/list", permission: Permissions::VIEW_IMAGE_REPORT)) {
$this->theme->display_reported_images($page, $this->get_reported_images());
}
if ($event->page_matches("image_report/add")) {
$image_id = int_escape($event->req_POST('image_id'));
send_event(new AddReportedImageEvent(new ImageReport($image_id, $user->id, $event->req_POST('reason'))));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
if ($event->page_matches("image_report/remove", method: "POST", permission: Permissions::VIEW_IMAGE_REPORT)) {
send_event(new RemoveReportedImageEvent(int_escape($event->req_POST('id'))));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("image_report/list"));
}
if ($event->page_matches("image_report/remove_reports_by", method: "POST", permission: Permissions::VIEW_IMAGE_REPORT)) {
$this->delete_reports_by(int_escape($event->req_POST('user_id')));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
if ($event->page_matches("image_report/list", permission: Permissions::VIEW_IMAGE_REPORT)) {
$this->theme->display_reported_images($page, $this->get_reported_images());
}
}

View file

@ -141,9 +141,9 @@ class ResizeImage extends Extension
{
global $page, $user;
if ($event->page_matches("resize", method: "POST", permission: Permissions::EDIT_FILES)) {
if ($event->page_matches("resize/{image_id}", method: "POST", permission: Permissions::EDIT_FILES)) {
// Try to get the image ID
$image_id = int_escape(null_throws($event->get_arg(0)));
$image_id = $event->get_iarg('image_id');
$image = Image::by_id($image_id);
if (is_null($image)) {
$this->theme->display_error(404, "Post not found", "No image in the database has the ID #$image_id");

View file

@ -59,9 +59,9 @@ class RotateImage extends Extension
{
global $page, $user;
if ($event->page_matches("rotate", method: "POST", permission: Permissions::EDIT_FILES)) {
if ($event->page_matches("rotate/{image_id}", method: "POST", permission: Permissions::EDIT_FILES)) {
// Try to get the image ID
$image_id = int_escape(null_throws($event->get_arg(0)));
$image_id = $event->get_iarg('image_id');
$image = Image::by_id($image_id);
if (is_null($image)) {
$this->theme->display_error(404, "Post not found", "No image in the database has the ID #$image_id");

View file

@ -23,10 +23,19 @@ class RSSImages extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $config;
if ($event->page_matches("rss/images")) {
$search_terms = $event->get_search_terms();
$page_number = $event->get_page_number();
$page_size = $event->get_page_size();
if ($event->page_matches("rss/images/{search}/{page}")) {
$search_terms = Tag::explode($event->get_arg('search'));
$page_number = int_escape($event->get_arg('page'));
} elseif ($event->page_matches("rss/images/{page}")) {
$search_terms = [];
$page_number = int_escape($event->get_arg('page'));
} else {
$search_terms = [];
$page_number = 1;
}
$page_size = $config->get_int(IndexConfig::IMAGES);
if (SPEED_HAX && $page_number > 9) {
return;
}

View file

@ -129,8 +129,8 @@ class S3 extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $config, $page, $user;
if ($event->page_matches("s3/sync", method: "POST", permission: Permissions::DELETE_IMAGE)) {
$id = int_escape($event->get_arg(0));
if ($event->page_matches("s3/sync/{image_id}", method: "POST", permission: Permissions::DELETE_IMAGE)) {
$id = $event->get_iarg('image_id');
$this->sync_post(Image::by_id($id));
log_info("s3", "Manual resync for >>$id", "File re-sync'ed");
$page->set_mode(PageMode::REDIRECT);

View file

@ -336,20 +336,18 @@ class Setup extends Extension
$page->set_data("ok");
}
if ($event->page_matches("setup", permission: Permissions::CHANGE_SETTING)) {
if ($event->count_args() == 0) {
$panel = new SetupPanel($config);
send_event(new SetupBuildingEvent($panel));
$this->theme->display_page($page, $panel);
} elseif ($event->get_arg(0) == "save" && $user->check_auth_token()) {
send_event(new ConfigSaveEvent($config, $event->POST));
$config->save();
$page->flash("Config saved");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("setup"));
} elseif ($event->get_arg(0) == "advanced") {
$this->theme->display_advanced($page, $config->values);
}
if ($event->page_matches("setup/advanced", method: "GET", permission: Permissions::CHANGE_SETTING)) {
$this->theme->display_advanced($page, $config->values);
} elseif ($event->page_matches("setup", method: "GET", permission: Permissions::CHANGE_SETTING)) {
$panel = new SetupPanel($config);
send_event(new SetupBuildingEvent($panel));
$this->theme->display_page($page, $panel);
} elseif ($event->page_matches("setup/save", method: "POST", permission: Permissions::CHANGE_SETTING)) {
send_event(new ConfigSaveEvent($config, $event->POST));
$config->save();
$page->flash("Config saved");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("setup"));
}
}

View file

@ -37,12 +37,12 @@ class SourceHistory extends Extension
$this->process_revert_request((int)$event->req_POST('revert'));
} elseif ($event->page_matches("source_history/bulk_revert", method: "POST", permission: Permissions::BULK_EDIT_IMAGE_TAG)) {
$this->process_bulk_revert_request();
} elseif ($event->page_matches("source_history/all")) {
$page_id = int_escape($event->get_arg(0));
} elseif ($event->page_matches("source_history/all/{page}")) {
$page_id = $event->get_iarg('page');
$this->theme->display_global_page($page, $this->get_global_source_history($page_id), $page_id);
} elseif ($event->page_matches("source_history") && $event->count_args() == 1) {
} elseif ($event->page_matches("source_history/{image_id}")) {
// must be an attempt to view a source history
$image_id = int_escape($event->get_arg(0));
$image_id = $event->get_iarg('image_id');
$this->theme->display_history_page($page, $image_id, $this->get_source_history_from_id($image_id));
}
}

View file

@ -146,19 +146,15 @@ class TagEdit extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $user, $page;
if ($event->page_matches("tag_edit", method: "POST", permission: Permissions::MASS_TAG_EDIT)) {
if ($event->get_arg(0) == "replace") {
$search = $event->req_POST('search');
$replace = $event->req_POST('replace');
$this->mass_tag_edit($search, $replace, true);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
if ($event->get_arg(0) == "mass_source_set") {
$this->mass_source_edit($event->req_POST('tags'), $event->req_POST('source'));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(search_link());
}
if ($event->page_matches("tag_edit/replace", method: "POST", permission: Permissions::MASS_TAG_EDIT)) {
$this->mass_tag_edit($event->req_POST('search'), $event->req_POST('replace'), true);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
if ($event->page_matches("tag_edit/mass_source_set", method: "POST", permission: Permissions::MASS_TAG_EDIT)) {
$this->mass_source_edit($event->req_POST('tags'), $event->req_POST('source'));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(search_link());
}
}

View file

@ -31,12 +31,12 @@ class TagHistory extends Extension
$this->process_revert_request((int)$event->req_POST('revert'));
} elseif ($event->page_matches("tag_history/bulk_revert", method: "POST", permission: Permissions::BULK_EDIT_IMAGE_TAG)) {
$this->process_bulk_revert_request();
} elseif ($event->page_matches("tag_history/all")) {
$page_id = int_escape($event->get_arg(0));
} elseif ($event->page_matches("tag_history/all/{page}")) {
$page_id = $event->get_iarg('page');
$this->theme->display_global_page($page, $this->get_global_tag_history($page_id), $page_id);
} elseif ($event->page_matches("tag_history") && $event->count_args() == 1) {
} elseif ($event->page_matches("tag_history/{image_id}")) {
// must be an attempt to view a tag history
$image_id = int_escape($event->get_arg(0));
$image_id = $event->get_iarg('image_id');
$this->theme->display_history_page($page, $image_id, $this->get_tag_history_from_id($image_id));
}
}

View file

@ -67,7 +67,7 @@ class TagHistoryTheme extends Themelet
Revert tag changes by a specific IP address or username, optionally limited to recent changes.
'.$validation_msg.'
<br><br>'.make_form(make_link("tag_history/bulk_revert"), 'POST')."
<br><br>'.make_form(make_link("tag_history/bulk_revert"))."
<table class='form'>
<tr><th>Username</th> <td><input type='text' name='revert_name' size='15'></td></tr>
<tr><th>IP&nbsp;Address</th> <td><input type='text' name='revert_ip' size='15'></td></tr>

View file

@ -31,13 +31,9 @@ class TagList extends Extension
{
global $config, $page;
if ($event->page_matches("tags")) {
if ($event->page_matches("tags/{sub}")) {
$this->theme->set_navigation($this->build_navigation());
if ($event->count_args() == 0) {
$sub = "map";
} else {
$sub = $event->get_arg(0);
}
$sub = $event->get_arg('sub');
if ($event->get_GET('starts_with')) {
$starts_with = $event->get_GET('starts_with') . "%";
@ -72,6 +68,9 @@ class TagList extends Extension
break;
}
$this->theme->display_page($page);
} elseif ($event->page_matches("tags")) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tags/map"));
}
}

View file

@ -11,7 +11,7 @@ class TagToolsTheme extends Themelet
protected function button(string $name, string $action, bool $protected = false): string
{
$c_protected = $protected ? " protected" : "";
$html = make_form(make_link("admin/$action"), "POST", false, "admin$c_protected");
$html = make_form(make_link("admin/$action"), multipart: false, form_id: "admin$c_protected");
if ($protected) {
$html .= "<input type='submit' id='$action' value='$name' disabled='disabled'>";
$html .= "<input type='checkbox' onclick='$(\"#$action\").attr(\"disabled\", !$(this).is(\":checked\"))'>";

View file

@ -23,9 +23,9 @@ class TaggerXML extends Extension
if ($event->get_GET('s')) { // tagger/tags[/...]?s=$string
// return matching tags in XML form
$tags = $this->match_tag_list($event->get_GET('s'));
} elseif ($event->get_arg(0)) { // tagger/tags/$int
} elseif ($event->page_matches("tagger/tags/{image_id}")) { // tagger/tags/$int
// return arg[1] AS image_id's tag list in XML form
$tags = $this->image_tag_list(int_escape($event->get_arg(0)));
$tags = $this->image_tag_list($event->get_iarg('image_id'));
}
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".
@ -55,7 +55,7 @@ class TaggerXML extends Extension
// Match
$match = "concat(:p, tag) LIKE :sq";
// Exclude
// $exclude = $event->get_arg(1)? "AND NOT IN ".$this->image_tags($event->get_arg(1)) : null;
// $exclude = $event->get_arg('exclude')? "AND NOT IN ".$this->image_tags($event->get_arg('exclude')) : null;
// Hidden Tags
$hidden = $config->get_string('ext-tagger_show-hidden', 'N') == 'N' ?

View file

@ -80,16 +80,16 @@ class Tips extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));
}
if ($event->page_matches("tips/status", permission: Permissions::TIPS_ADMIN)) {
if ($event->page_matches("tips/status/{tipID}", permission: Permissions::TIPS_ADMIN)) {
// FIXME: HTTP GET CSRF
$tipID = int_escape($event->get_arg(1));
$tipID = $event->get_iarg('tipID');
$this->setStatus($tipID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));
}
if ($event->page_matches("tips/delete", permission: Permissions::TIPS_ADMIN)) {
if ($event->page_matches("tips/delete/{tipID}", permission: Permissions::TIPS_ADMIN)) {
// FIXME: HTTP GET CSRF
$tipID = int_escape($event->get_arg(1));
$tipID = $event->get_iarg('tipID');
send_event(new DeleteTipEvent($tipID));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));

View file

@ -207,8 +207,8 @@ class TranscodeImage extends Extension
{
global $page, $user;
if ($event->page_matches("transcode", method: "POST", permission: Permissions::EDIT_FILES)) {
$image_id = int_escape($event->get_arg(0));
if ($event->page_matches("transcode/{image_id}", method: "POST", permission: Permissions::EDIT_FILES)) {
$image_id = $event->get_iarg('image_id');
$image_obj = Image::by_id($image_id);
if (is_null($image_obj)) {
$this->theme->display_error(404, "Post not found", "No image in the database has the ID #$image_id");

View file

@ -101,8 +101,8 @@ class TranscodeVideo extends Extension
{
global $page, $user;
if ($event->page_matches("transcode_video", method: "POST", permission: Permissions::EDIT_FILES)) {
$image_id = int_escape($event->get_arg(0));
if ($event->page_matches("transcode_video/{image_id}", method: "POST", permission: Permissions::EDIT_FILES)) {
$image_id = $event->get_iarg('image_id');
$image_obj = Image::by_id($image_id);
if (is_null($image_obj)) {
$this->theme->display_error(404, "Post not found", "No post in the database has the ID #$image_id");

View file

@ -29,8 +29,8 @@ class Trash extends Extension
{
global $page, $user;
if ($event->page_matches("trash_restore", method: "POST", permission: Permissions::VIEW_TRASH)) {
$image_id = int_escape(null_throws($event->get_arg(0)));
if ($event->page_matches("trash_restore/{image_id}", method: "POST", permission: Permissions::VIEW_TRASH)) {
$image_id = $event->get_iarg('image_id');
self::set_trash($image_id, false);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$image_id));

View file

@ -216,39 +216,41 @@ class Upload extends Extension
}
}
if ($event->page_matches("upload", permission: Permissions::CREATE_IMAGE)) {
if ($event->page_matches("upload", method: "GET", permission: Permissions::CREATE_IMAGE)) {
if ($this->is_full) {
$this->theme->display_error(507, "Error", "Can't upload images: disk nearly full");
return;
}
if($event->method == "GET") {
$this->theme->display_page($page);
} elseif($event->method == "POST") {
$results = [];
$files = array_filter($_FILES, function ($file) {
return !empty($file['name']);
});
foreach ($files as $name => $file) {
$slot = int_escape(substr($name, 4));
$tags = $this->tags_for_upload_slot($event->POST, $slot);
$source = $this->source_for_upload_slot($event->POST, $slot);
$results = array_merge($results, $this->try_upload($file, $tags, $source));
}
$urls = array_filter($event->POST, function ($value, $key) {
return str_starts_with($key, "url") && is_string($value) && strlen($value) > 0;
}, ARRAY_FILTER_USE_BOTH);
foreach ($urls as $name => $value) {
$slot = int_escape(substr($name, 3));
$tags = $this->tags_for_upload_slot($event->POST, $slot);
$source = $this->source_for_upload_slot($event->POST, $slot);
$results = array_merge($results, $this->try_transload($value, $tags, $source));
}
$this->theme->display_upload_status($page, $results);
$this->theme->display_page($page);
}
if ($event->page_matches("upload", method: "POST", permission: Permissions::CREATE_IMAGE)) {
if ($this->is_full) {
$this->theme->display_error(507, "Error", "Can't upload images: disk nearly full");
return;
}
$results = [];
$files = array_filter($_FILES, function ($file) {
return !empty($file['name']);
});
foreach ($files as $name => $file) {
$slot = int_escape(substr($name, 4));
$tags = $this->tags_for_upload_slot($event->POST, $slot);
$source = $this->source_for_upload_slot($event->POST, $slot);
$results = array_merge($results, $this->try_upload($file, $tags, $source));
}
$urls = array_filter($event->POST, function ($value, $key) {
return str_starts_with($key, "url") && is_string($value) && strlen($value) > 0;
}, ARRAY_FILTER_USE_BOTH);
foreach ($urls as $name => $value) {
$slot = int_escape(substr($name, 3));
$tags = $this->tags_for_upload_slot($event->POST, $slot);
$source = $this->source_for_upload_slot($event->POST, $slot);
$results = array_merge($results, $this->try_transload($value, $tags, $source));
}
$this->theme->display_upload_status($page, $results);
}
}

View file

@ -44,7 +44,7 @@ class UploadTheme extends Themelet
$max_total_kb = to_shorthand_int($max_total_size);
$upload_list = $this->build_upload_list();
$form = SHM_FORM("upload", "POST", true, "file_upload");
$form = SHM_FORM("upload", multipart: true, form_id: "file_upload");
$form->appendChild(
TABLE(
["id" => "large_upload_form", "class" => "form"],
@ -257,7 +257,7 @@ class UploadTheme extends Themelet
$max_total_kb = to_shorthand_int($max_total_size);
// <input type='hidden' name='max_file_size' value='$max_size' />
$form = SHM_FORM("upload", "POST", true);
$form = SHM_FORM("upload", multipart: true);
$form->appendChild(
emptyHTML(
INPUT(["id" => "data[]", "name" => "data[]", "size" => "16", "type" => "file", "accept" => $accept, "multiple" => true]),

View file

@ -314,15 +314,9 @@ class UserPage extends Extension
);
}
if ($event->page_matches("user")) {
$display_user = ($event->count_args() == 0) ? $user : User::by_name($event->get_arg(0));
if ($event->count_args() == 0 && $user->is_anonymous()) {
$this->theme->display_error(
401,
"Not Logged In",
"You aren't logged in. First do that, then you can see your stats."
);
} elseif (!is_null($display_user) && ($display_user->id != $config->get_int("anon_id"))) {
if ($event->page_matches("user/{name}")) {
$display_user = User::by_name($event->get_arg('name'));
if (!is_null($display_user) && ($display_user->id != $config->get_int("anon_id"))) {
$e = send_event(new UserPageBuildingEvent($display_user));
$this->display_stats($e);
} else {
@ -333,6 +327,9 @@ class UserPage extends Extension
"site, it might be bug report time..."
);
}
} elseif($event->page_matches("user")) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user/" . $user->name));
}
}

View file

@ -8,9 +8,8 @@ class UserPageTest extends ShimmiePHPUnitTestCase
{
public function testUserPage(): void
{
$this->get_page('user');
$this->assert_title("Not Logged In");
$this->assert_no_text("Stats");
$page = $this->get_page('user');
$this->assertEquals(PageMode::REDIRECT, $page->mode);
$this->get_page('user/demo');
$this->assert_title("demo's Page");

View file

@ -133,27 +133,26 @@ class UserConfig extends Extension
}
}
if ($event->page_matches("user_config", permission: Permissions::CHANGE_USER_SETTING)) {
if ($event->count_args() == 0) {
$uobe = send_event(new UserOptionsBuildingEvent($user, new SetupPanel($user_config)));
$this->theme->display_user_config_page($page, $uobe->user, $uobe->panel);
} elseif ($event->get_arg(0) == "save" && $user->check_auth_token()) {
$input = validate_input([
'id' => 'user_id,exists'
]);
$duser = User::by_id($input['id']);
if ($event->page_matches("user_config", method: "GET", permission: Permissions::CHANGE_USER_SETTING)) {
$uobe = send_event(new UserOptionsBuildingEvent($user, new SetupPanel($user_config)));
$this->theme->display_user_config_page($page, $uobe->user, $uobe->panel);
}
if ($event->page_matches("user_config/save", method: "POST", permission: Permissions::CHANGE_USER_SETTING)) {
$input = validate_input([
'id' => 'user_id,exists'
]);
$duser = User::by_id($input['id']);
if ($user->id != $duser->id && !$user->can(Permissions::CHANGE_OTHER_USER_SETTING)) {
throw new PermissionDeniedException("You do not have permission to change other user's settings");
}
$target_config = UserConfig::get_for_user($duser->id);
send_event(new ConfigSaveEvent($target_config, $event->POST));
$target_config->save();
$page->flash("Config saved");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user_config"));
if ($user->id != $duser->id && !$user->can(Permissions::CHANGE_OTHER_USER_SETTING)) {
throw new PermissionDeniedException("You do not have permission to change other user's settings");
}
$target_config = UserConfig::get_for_user($duser->id);
send_event(new ConfigSaveEvent($target_config, $event->POST));
$target_config->save();
$page->flash("Config saved");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user_config"));
}
}

View file

@ -22,8 +22,8 @@ class ViewPost extends Extension
{
global $page, $user;
if ($event->page_matches("post/prev") || $event->page_matches("post/next")) {
$image_id = int_escape($event->get_arg(0));
if ($event->page_matches("post/prev/{image_id}") || $event->page_matches("post/next/{image_id}")) {
$image_id = $event->get_iarg('image_id');
$search = $event->get_GET('search');
if ($search) {
@ -40,7 +40,7 @@ class ViewPost extends Extension
return;
}
if ($event->page_matches("post/next")) {
if ($event->page_matches("post/next/{image_id}")) {
$image = $image->get_next($search_terms);
} else {
$image = $image->get_prev($search_terms);
@ -53,8 +53,8 @@ class ViewPost extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/{$image->id}", $query));
} elseif ($event->page_matches("post/view")) {
if (!is_numeric($event->get_arg(0))) {
} elseif ($event->page_matches("post/view/{image_id}")) {
if (!is_numeric($event->get_arg('image_id'))) {
// For some reason there exists some very broken mobile client
// who follows up every request to '/post/view/123' with
// '/post/view/12300000000000Image 123: tags' which spams the
@ -63,8 +63,7 @@ class ViewPost extends Extension
return;
}
$image_id = int_escape($event->get_arg(0));
$image_id = $event->get_iarg('image_id');
$image = Image::by_id($image_id);
if (!is_null($image)) {

View file

@ -176,20 +176,11 @@ class Wiki extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("wiki")) {
if ($event->count_args() == 0 || strlen(trim($event->get_arg(0))) === 0) {
$title = "Index";
} else {
$title = $event->get_arg(0);
}
$action = $event->count_args() > 1 ? $event->get_arg(1) : "view";
if ($event->page_matches("wiki/{title}/{action}", method: "GET")) {
$title = $event->get_arg('title');
$action = $event->get_arg('action');
if($action == "view") {
$revision = int_escape($event->get_GET('revision') ?? "-1");
$content = $this->get_page($title, $revision);
$this->theme->display_page($page, $content, $this->get_page("wiki:sidebar"));
} elseif($action == "history") {
if($action == "history") {
$history = $this->get_history($title);
$this->theme->display_page_history($page, $title, $history);
} elseif($action == "edit") {
@ -199,7 +190,13 @@ class Wiki extends Extension
} else {
throw new PermissionDeniedException("You are not allowed to edit this page");
}
} elseif($action == "save" && $user->check_auth_token()) {
}
}
if ($event->page_matches("wiki/{title}/{action}", method: "POST")) {
$title = $event->get_arg('title');
$action = $event->get_arg('action');
if($action == "save") {
$rev = int_escape($event->req_POST('revision'));
$body = $event->req_POST('body');
$lock = $user->can(Permissions::WIKI_ADMIN) && ($event->get_POST('lock') == "on");
@ -216,7 +213,7 @@ class Wiki extends Extension
} else {
throw new PermissionDeniedException("You are not allowed to edit this page");
}
} elseif($action == "delete_revision" && $user->check_auth_token()) {
} elseif($action == "delete_revision") {
$content = $this->get_page($title);
if ($user->can(Permissions::WIKI_ADMIN)) {
$revision = int_escape($event->req_POST('revision'));
@ -227,7 +224,7 @@ class Wiki extends Extension
} else {
throw new PermissionDeniedException("You are not allowed to edit this page");
}
} elseif($action == "delete_all" && $user->check_auth_token()) {
} elseif($action == "delete_all") {
if ($user->can(Permissions::WIKI_ADMIN)) {
send_event(new WikiDeletePageEvent($title));
$u_title = url_escape($title);
@ -235,6 +232,14 @@ class Wiki extends Extension
$page->set_redirect(make_link("wiki/$u_title"));
}
}
} elseif ($event->page_matches("wiki/{title}")) {
$title = $event->get_arg('title');
$revision = int_escape($event->get_GET('revision') ?? "-1");
$content = $this->get_page($title, $revision);
$this->theme->display_page($page, $content, $this->get_page("wiki:sidebar"));
} elseif ($event->page_matches("wiki")) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("wiki/Index"));
}
}
@ -262,16 +267,16 @@ class Wiki extends Extension
if ($config->get_bool(WikiConfig::ENABLE_REVISIONS) || !$exists) {
$database->execute(
"
INSERT INTO wiki_pages(owner_id, owner_ip, date, title, revision, locked, body)
VALUES (:owner_id, :owner_ip, now(), :title, :revision, :locked, :body)",
INSERT INTO wiki_pages(owner_id, owner_ip, date, title, revision, locked, body)
VALUES (:owner_id, :owner_ip, now(), :title, :revision, :locked, :body)",
["owner_id" => $event->user->id, "owner_ip" => get_real_ip(),
"title" => $wpage->title, "revision" => $wpage->revision, "locked" => $wpage->locked, "body" => $wpage->body]
);
} else {
$database->execute(
"
UPDATE wiki_pages SET owner_id=:owner_id, owner_ip=:owner_ip, date=now(), locked=:locked, body=:body
WHERE title = :title ORDER BY revision DESC LIMIT 1",
UPDATE wiki_pages SET owner_id=:owner_id, owner_ip=:owner_ip, date=now(), locked=:locked, body=:body
WHERE title = :title ORDER BY revision DESC LIMIT 1",
["owner_id" => $event->user->id, "owner_ip" => get_real_ip(),
"title" => $wpage->title, "locked" => $wpage->locked, "body" => $wpage->body]
);

View file

@ -8,9 +8,8 @@ class WikiTest extends ShimmiePHPUnitTestCase
{
public function testIndex(): void
{
$this->get_page("wiki");
$this->assert_title("Index");
$this->assert_text("This is a default page");
$page = $this->get_page("wiki");
$this->assertEquals(PageMode::REDIRECT, $page->mode);
}
// By default users are read-only

View file

@ -49,7 +49,7 @@ class CustomIndexTheme extends IndexTheme
$h_search_string = count($search_terms) == 0 ? "" : html_escape(implode(" ", $search_terms));
$h_search_link = search_link();
return "
<p><form action='$h_search_link' method='POST'>
<p><form action='$h_search_link' method='GET'>
<input name='search' type='text' value='$h_search_string' class='autocomplete_tags' placeholder='Search' />
<input type='submit' value='Find' style='display: none;' />
</form>

View file

@ -33,7 +33,7 @@ class CustomIndexTheme extends IndexTheme
$h_search_string = count($search_terms) == 0 ? "" : html_escape(implode(" ", $search_terms));
$h_search_link = search_link();
return "
<p><form action='$h_search_link' method='POST'>
<p><form action='$h_search_link' method='GET'>
<input name='search' type='text' value='$h_search_string' class='autocomplete_tags' placeholder='' style='width:75%'/>
<input type='submit' value='Go' style='width:20%'>
</form>