Merge pull request #679 from sanmadjack/etc

Etc Commits
This commit is contained in:
Shish 2019-08-06 17:45:24 -07:00 committed by GitHub
commit e6411c32aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
121 changed files with 2024 additions and 751 deletions

View File

@ -100,10 +100,10 @@ permissions like so:
```php
new UserClass("anonymous", "base", [
"create_comment" => True,
"edit_image_tag" => True,
"edit_image_source" => True,
"create_image_report" => True,
Permissions::CREATE_COMMENT => True,
Permissions::EDIT_IMAGE_TAG => True,
Permissions::EDIT_IMAGE_SOURCE => True,
Permissions::CREATE_IMAGE_REPORT => True,
]);
```
@ -111,12 +111,12 @@ For a moderator class, being a regular user who can delete images and comments:
```php
new UserClass("moderator", "user", [
"delete_image" => True,
"delete_comment" => True,
Permissions::DELETE_IMAGE => True,
Permissions::DELETE_COMMENT => True,
]);
```
For a list of permissions, see `core/userclass.php`
For a list of permissions, see `core/permissions.php`
# Development Info

View File

@ -15,6 +15,11 @@ require_once "vendor/autoload.php";
_version_check();
_sanitise_environment();
// The trace system has a certain amount of memory consumption every time it is used,
// so to prevent running out of memory during complex operations code that uses it should
// check if tracer output is enabled before making use of it.
$tracer_enabled = constant('TRACE_FILE')!==null;
// load base files
$_tracer->begin("Bootstrap");
$_tracer->begin("Opening files");

View File

@ -190,10 +190,12 @@ class Database
private function count_time(string $method, float $start, string $query, ?array $args): void
{
global $_tracer;
global $_tracer, $tracer_enabled;
$dur = microtime(true) - $start;
$query = trim(preg_replace('/^[\t ]+/m', '', $query)); // trim leading whitespace
$_tracer->complete($start * 1000000, $dur * 1000000, "DB Query", ["query"=>$query, "args"=>$args, "method"=>$method]);
if($tracer_enabled) {
$query = trim(preg_replace('/^[\t ]+/m', '', $query)); // trim leading whitespace
$_tracer->complete($start * 1000000, $dur * 1000000, "DB Query", ["query"=>$query, "args"=>$args, "method"=>$method]);
}
$this->query_count++;
$this->dbtime += $dur;
}

View File

@ -60,7 +60,7 @@ class PageRequestEvent extends Event
// if path is not specified, use the default front page
if (empty($path)) { /* empty is faster than strlen */
$path = $config->get_string('front_page');
$path = $config->get_string(SetupConfig::FRONT_PAGE);
}
// break the path into parts

View File

@ -129,7 +129,7 @@ class Image
}
if (SPEED_HAX) {
if (!$user->can("big_search") and count($tags) > 3) {
if (!$user->can(Permissions::BIG_SEARCH) and count($tags) > 3) {
throw new SCoreException("Anonymous users may only search for up to 3 tags at a time");
}
}
@ -813,7 +813,7 @@ class Image
$tmpl = str_replace('$size', "{$this->width}x{$this->height}", $tmpl);
$tmpl = str_replace('$filesize', to_shorthand_int($this->filesize), $tmpl);
$tmpl = str_replace('$filename', $_escape($base_fname), $tmpl);
$tmpl = str_replace('$title', $_escape($config->get_string("title")), $tmpl);
$tmpl = str_replace('$title', $_escape($config->get_string(SetupConfig::TITLE)), $tmpl);
$tmpl = str_replace('$date', $_escape(autodate($this->posted, false)), $tmpl);
// nothing seems to use this, sending the event out to 50 exts is a lot of overhead

View File

@ -299,9 +299,55 @@ class Page
$this->add_cookie("flash_message", "", -1, "/");
}
usort($this->blocks, "blockcmp");
$pnbe = new PageNavBuildingEvent();
send_event($pnbe);
$nav_links = $pnbe->links;
$active_link = null;
// To save on event calls, we check if one of the top-level links has already been marked as active
foreach ($nav_links as $link) {
if($link->active===true) {
$active_link = $link;
break;
}
}
$sub_links = null;
// If one is, we just query for sub-menu options under that one tab
if($active_link!==null) {
$psnbe = new PageSubNavBuildingEvent($active_link->name);
send_event($psnbe);
$sub_links = $psnbe->links;
} else {
// Otherwise we query for the sub-items under each of the tabs
foreach ($nav_links as $link) {
$psnbe = new PageSubNavBuildingEvent($link->name);
send_event($psnbe);
// Now we check for a current link so we can identify the sub-links to show
foreach ($psnbe->links as $sub_link) {
if($sub_link->active===true) {
$sub_links = $psnbe->links;
break;
}
}
// If the active link has been detected, we break out
if($sub_links!==null) {
$link->active = true;
break;
}
}
}
$sub_links = $sub_links??[];
usort($nav_links, "sort_nav_links");
usort($sub_links, "sort_nav_links");
$this->add_auto_html_headers();
$layout = new Layout();
$layout->display_page($page);
$layout->display_page($page, $nav_links, $sub_links);
break;
case PageMode::DATA:
header("Content-Length: " . strlen($this->data));
@ -405,7 +451,7 @@ class Page
global $config;
$data_href = get_base_href();
$theme_name = $config->get_string('theme', 'default');
$theme_name = $config->get_string(SetupConfig::THEME, 'default');
$this->add_html_header("<script type='text/javascript'>base_href = '$data_href';</script>", 40);
@ -471,3 +517,99 @@ class Page
$this->add_html_header("<script src='$data_href/$js_cache_file' type='text/javascript'></script>", 44);
}
}
class PageNavBuildingEvent extends Event
{
public $links = [];
public function add_nav_link(string $name, Link $link, string $desc, ?bool $active = null, int $order = 50)
{
$this->links[] = new NavLink($name, $link, $desc, $active, $order);
}
}
class PageSubNavBuildingEvent extends Event
{
public $parent;
public $links = [];
public function __construct(string $parent)
{
$this->parent= $parent;
}
public function add_nav_link(string $name, Link $link, string $desc, ?bool $active = null, int $order = 50)
{
$this->links[] = new NavLink($name, $link, $desc, $active,$order);
}
}
class NavLink
{
public $name;
public $link;
public $description;
public $order;
public $active = false;
public function __construct(String $name, Link $link, String $description, ?bool $active = null, int $order = 50)
{
global $config;
$this->name = $name;
$this->link = $link;
$this->description = $description;
$this->order = $order;
if($active==null) {
$query = ltrim(_get_query(), "/");
if ($query === "") {
// This indicates the front page, so we check what's set as the front page
$front_page = trim($config->get_string(SetupConfig::FRONT_PAGE), "/");
if ($front_page === $link->page) {
$this->active = true;
} else {
$this->active = self::is_active([$link->page], $front_page);
}
} elseif($query===$link->page) {
$this->active = true;
}else {
$this->active = self::is_active([$link->page]);
}
} else {
$this->active = $active;
}
}
public static function is_active(array $pages_matched, string $url = null): bool
{
/**
* Woo! We can actually SEE THE CURRENT PAGE!! (well... see it highlighted in the menu.)
*/
$url = $url??ltrim(_get_query(), "/");
$re1='.*?';
$re2='((?:[a-z][a-z_]+))';
if (preg_match_all("/".$re1.$re2."/is", $url, $matches)) {
$url=$matches[1][0];
}
$count_pages_matched = count($pages_matched);
for ($i=0; $i < $count_pages_matched; $i++) {
if ($url == $pages_matched[$i]) {
return true;
}
}
return false;
}
}
function sort_nav_links(NavLink $a, NavLink $b)
{
return $a->order - $b->order;
}

70
core/permissions.php Normal file
View File

@ -0,0 +1,70 @@
<?php
abstract class Permissions
{
public const CHANGE_SETTING = "change_setting"; # modify web-level settings, eg the config table
public const OVERRIDE_CONFIG = "override_config"; # modify sys-level settings, eg shimmie.conf.php
public const BIG_SEARCH = "big_search"; # search for more than 3 tags at once (speed mode only)
public const MANAGE_EXTENSION_LIST = "manage_extension_list";
public const MANAGE_ALIAS_LIST = "manage_alias_list";
public const MASS_TAG_EDIT = "mass_tag_edit";
public const VIEW_IP = "view_ip"; # view IP addresses associated with things
public const BAN_IP = "ban_ip";
public const EDIT_USER_NAME = "edit_user_name";
public const EDIT_USER_PASSWORD = "edit_user_password";
public const EDIT_USER_INFO = "edit_user_info"; # email address, etc
public const EDIT_USER_CLASS = "edit_user_class";
public const DELETE_USER = "delete_user";
public const CREATE_COMMENT = "create_comment";
public const DELETE_COMMENT = "delete_comment";
public const BYPASS_COMMENT_CHECKS = "bypass_comment_checks"; # spam etc
public const REPLACE_IMAGE = "replace_image";
public const CREATE_IMAGE = "create_image";
public const EDIT_IMAGE_TAG = "edit_image_tag";
public const EDIT_IMAGE_SOURCE = "edit_image_source";
public const EDIT_IMAGE_OWNER = "edit_image_owner";
public const EDIT_IMAGE_LOCK = "edit_image_lock";
public const EDIT_IMAGE_TITLE = "edit_image_title";
public const BULK_EDIT_IMAGE_TAG = "bulk_edit_image_tag";
public const BULK_EDIT_IMAGE_SOURCE = "bulk_edit_image_source";
public const DELETE_IMAGE = "delete_image";
public const BAN_IMAGE = "ban_image";
public const VIEW_EVENTLOG = "view_eventlog";
public const IGNORE_DOWNTIME = "ignore_downtime";
public const CREATE_IMAGE_REPORT = "create_image_report";
public const VIEW_IMAGE_REPORT = "view_image_report"; # deal with reported images
public const EDIT_WIKI_PAGE = "edit_wiki_page";
public const DELETE_WIKI_PAGE = "delete_wiki_page";
public const MANAGE_BLOCKS = "manage_blocks";
public const MANAGE_ADMINTOOLS = "manage_admintools";
public const VIEW_OTHER_PMS = "view_other_pms";
public const EDIT_FEATURE = "edit_feature";
public const BULK_EDIT_VOTE = "bulk_edit_vote";
public const EDIT_OTHER_VOTE = "edit_other_vote";
public const VIEW_SYSINTO = "view_sysinfo";
public const HELLBANNED = "hellbanned";
public const VIEW_HELLBANNED = "view_hellbanned";
public const PROTECTED = "protected"; # only admins can modify protected users (stops a moderator changing an admin's password)
public const EDIT_IMAGE_RATING = "edit_image_rating";
public const BULK_EDIT_IMAGE_RATING = "bulk_edit_image_rating";
public const VIEW_TRASH = "view_trash";
public const PERFORM_BULK_ACTIONS = "perform_bulk_actions";
}

View File

@ -108,6 +108,8 @@ $_shm_event_count = 0;
*/
function send_event(Event $event): void
{
global $tracer_enabled;
global $_shm_event_listeners, $_shm_event_count, $_tracer;
if (!isset($_shm_event_listeners[get_class($event)])) {
return;
@ -116,8 +118,6 @@ function send_event(Event $event): void
// send_event() is performance sensitive, and with the number
// of times tracer gets called the time starts to add up
$tracer_enabled = constant('TRACE_FILE');
if ($tracer_enabled) $_tracer->begin(get_class($event));
// SHIT: http://bugs.php.net/bug.php?id=35106
$my_event_listeners = $_shm_event_listeners[get_class($event)];

View File

@ -40,7 +40,7 @@ _d("SEARCH_ACCEL", false); // boolean use search accelerator
_d("WH_SPLITS", 1); // int how many levels of subfolders to put in the warehouse
_d("VERSION", '2.7-beta'); // string shimmie version
_d("TIMEZONE", null); // string timezone
_d("CORE_EXTS", "bbcode,user,mail,upload,image,view,handle_pixel,ext_manager,setup,upgrade,handle_404,handle_static,comment,tag_list,index,tag_edit,alias_editor,media"); // extensions to always enable
_d("CORE_EXTS", "bbcode,user,mail,upload,image,view,handle_pixel,ext_manager,setup,upgrade,handle_404,handle_static,comment,tag_list,index,tag_edit,alias_editor,media,help_pages,system"); // extensions to always enable
_d("EXTRA_EXTS", ""); // string optional extra extensions
_d("BASE_URL", null); // string force a specific base URL (default is auto-detect)
_d("MIN_PHP_VERSION", '7.1');// string minimum supported PHP version

View File

@ -3,6 +3,23 @@
* HTML Generation *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
class Link
{
public $page;
public $query;
public function __construct(?string $page=null, ?string $query=null)
{
$this->page = $page;
$this->query = $query;
}
public function make_link(): string
{
return make_link($this->page, $this->query);
}
}
/**
* Figure out the correct way to link to a page, taking into account
* things like the nice URLs setting.
@ -14,7 +31,7 @@ function make_link(?string $page=null, ?string $query=null): string
global $config;
if (is_null($page)) {
$page = $config->get_string('main_page');
$page = $config->get_string(SetupConfig::MAIN_PAGE);
}
if (!is_null(BASE_URL)) {

View File

@ -72,134 +72,138 @@ class UserClass
// action = create / view / edit / delete
// object = image / user / tag / setting
new UserClass("base", null, [
"change_setting" => false, # modify web-level settings, eg the config table
"override_config" => false, # modify sys-level settings, eg shimmie.conf.php
"big_search" => false, # search for more than 3 tags at once (speed mode only)
Permissions::CHANGE_SETTING => false, # modify web-level settings, eg the config table
Permissions::OVERRIDE_CONFIG => false, # modify sys-level settings, eg shimmie.conf.php
Permissions::BIG_SEARCH => false, # search for more than 3 tags at once (speed mode only)
"manage_extension_list" => false,
"manage_alias_list" => false,
"mass_tag_edit" => false,
Permissions::MANAGE_EXTENSION_LIST => false,
Permissions::MANAGE_ALIAS_LIST => false,
Permissions::MASS_TAG_EDIT => false,
"view_ip" => false, # view IP addresses associated with things
"ban_ip" => false,
Permissions::VIEW_IP => false, # view IP addresses associated with things
Permissions::BAN_IP => false,
"edit_user_name" => false,
"edit_user_password" => false,
"edit_user_info" => false, # email address, etc
"edit_user_class" => false,
"delete_user" => false,
Permissions::EDIT_USER_NAME => false,
Permissions::EDIT_USER_PASSWORD => false,
Permissions::EDIT_USER_INFO => false, # email address, etc
Permissions::EDIT_USER_CLASS => false,
Permissions::DELETE_USER => false,
"create_comment" => false,
"delete_comment" => false,
"bypass_comment_checks" => false, # spam etc
Permissions::CREATE_COMMENT => false,
Permissions::DELETE_COMMENT => false,
Permissions::BYPASS_COMMENT_CHECKS => false, # spam etc
"replace_image" => false,
"create_image" => false,
"edit_image_tag" => false,
"edit_image_source" => false,
"edit_image_owner" => false,
"edit_image_lock" => false,
"bulk_edit_image_tag" => false,
"bulk_edit_image_source" => false,
"delete_image" => false,
Permissions::REPLACE_IMAGE => false,
Permissions::CREATE_IMAGE => false,
Permissions::EDIT_IMAGE_TAG => false,
Permissions::EDIT_IMAGE_SOURCE => false,
Permissions::EDIT_IMAGE_OWNER => false,
Permissions::EDIT_IMAGE_LOCK => false,
Permissions::EDIT_IMAGE_TITLE => false,
Permissions::BULK_EDIT_IMAGE_TAG => false,
Permissions::BULK_EDIT_IMAGE_SOURCE => false,
Permissions::DELETE_IMAGE => false,
"ban_image" => false,
Permissions::BAN_IMAGE => false,
"view_eventlog" => false,
"ignore_downtime" => false,
Permissions::VIEW_EVENTLOG => false,
Permissions::IGNORE_DOWNTIME => false,
"create_image_report" => false,
"view_image_report" => false, # deal with reported images
Permissions::CREATE_IMAGE_REPORT => false,
Permissions::VIEW_IMAGE_REPORT => false, # deal with reported images
"edit_wiki_page" => false,
"delete_wiki_page" => false,
Permissions::EDIT_WIKI_PAGE => false,
Permissions::DELETE_WIKI_PAGE => false,
"manage_blocks" => false,
Permissions::MANAGE_BLOCKS => false,
"manage_admintools" => false,
Permissions::MANAGE_ADMINTOOLS => false,
"view_other_pms" => false,
"edit_feature" => false,
"bulk_edit_vote" => false,
"edit_other_vote" => false,
"view_sysinfo" => false,
Permissions::VIEW_OTHER_PMS => false,
Permissions::EDIT_FEATURE => false,
Permissions::BULK_EDIT_VOTE => false,
Permissions::EDIT_OTHER_VOTE => false,
Permissions::VIEW_SYSINTO => false,
"hellbanned" => false,
"view_hellbanned" => false,
Permissions::HELLBANNED => false,
Permissions::VIEW_HELLBANNED => false,
"protected" => false, # only admins can modify protected users (stops a moderator changing an admin's password)
Permissions::PROTECTED => false, # only admins can modify protected users (stops a moderator changing an admin's password)
"edit_image_rating" => false,
"bulk_edit_image_rating" => false,
Permissions::EDIT_IMAGE_RATING => false,
Permissions::BULK_EDIT_IMAGE_RATING => false,
"view_trash" => false,
"perform_bulk_actions" => false,
Permissions::VIEW_TRASH => false,
Permissions::PERFORM_BULK_ACTIONS => false,
]);
new UserClass("anonymous", "base", [
]);
new UserClass("user", "base", [
"big_search" => true,
"create_image" => true,
"create_comment" => true,
"edit_image_tag" => true,
"edit_image_source" => true,
"create_image_report" => true,
"edit_image_rating" => true,
Permissions::BIG_SEARCH => true,
Permissions::CREATE_IMAGE => true,
Permissions::CREATE_COMMENT => true,
Permissions::EDIT_IMAGE_TAG => true,
Permissions::EDIT_IMAGE_SOURCE => true,
Permissions::EDIT_IMAGE_TITLE => true,
Permissions::CREATE_IMAGE_REPORT => true,
Permissions::EDIT_IMAGE_RATING => true,
]);
new UserClass("admin", "base", [
"change_setting" => true,
"override_config" => true,
"big_search" => true,
"edit_image_lock" => true,
"view_ip" => true,
"ban_ip" => true,
"edit_user_name" => true,
"edit_user_password" => true,
"edit_user_info" => true,
"edit_user_class" => true,
"delete_user" => true,
"create_image" => true,
"delete_image" => true,
"ban_image" => true,
"create_comment" => true,
"delete_comment" => true,
"bypass_comment_checks" => true,
"replace_image" => true,
"manage_extension_list" => true,
"manage_alias_list" => true,
"edit_image_tag" => true,
"edit_image_source" => true,
"edit_image_owner" => true,
"bulk_edit_image_tag" => true,
"bulk_edit_image_source" => true,
"mass_tag_edit" => true,
"create_image_report" => true,
"view_image_report" => true,
"edit_wiki_page" => true,
"delete_wiki_page" => true,
"view_eventlog" => true,
"manage_blocks" => true,
"manage_admintools" => true,
"ignore_downtime" => true,
"view_other_pms" => true,
"edit_feature" => true,
"bulk_edit_vote" => true,
"edit_other_vote" => true,
"view_sysinfo" => true,
"view_hellbanned" => true,
"protected" => true,
"edit_image_rating" => true,
"bulk_edit_image_rating" => true,
"view_trash" => true,
"perform_bulk_actions" => true,
Permissions::CHANGE_SETTING => true,
Permissions::OVERRIDE_CONFIG => true,
Permissions::BIG_SEARCH => true,
Permissions::EDIT_IMAGE_LOCK => true,
Permissions::VIEW_IP => true,
Permissions::BAN_IP => true,
Permissions::EDIT_USER_NAME => true,
Permissions::EDIT_USER_PASSWORD => true,
Permissions::EDIT_USER_INFO => true,
Permissions::EDIT_USER_CLASS => true,
Permissions::DELETE_USER => true,
Permissions::CREATE_IMAGE => true,
Permissions::DELETE_IMAGE => true,
Permissions::BAN_IMAGE => true,
Permissions::CREATE_COMMENT => true,
Permissions::DELETE_COMMENT => true,
Permissions::BYPASS_COMMENT_CHECKS => true,
Permissions::REPLACE_IMAGE => true,
Permissions::MANAGE_EXTENSION_LIST => true,
Permissions::MANAGE_ALIAS_LIST => true,
Permissions::EDIT_IMAGE_TAG => true,
Permissions::EDIT_IMAGE_SOURCE => true,
Permissions::EDIT_IMAGE_OWNER => true,
Permissions::EDIT_IMAGE_TITLE => true,
Permissions::BULK_EDIT_IMAGE_TAG => true,
Permissions::BULK_EDIT_IMAGE_SOURCE => true,
Permissions::MASS_TAG_EDIT => true,
Permissions::CREATE_IMAGE_REPORT => true,
Permissions::VIEW_IMAGE_REPORT => true,
Permissions::EDIT_WIKI_PAGE => true,
Permissions::DELETE_WIKI_PAGE => true,
Permissions::VIEW_EVENTLOG => true,
Permissions::MANAGE_BLOCKS => true,
Permissions::MANAGE_ADMINTOOLS => true,
Permissions::IGNORE_DOWNTIME => true,
Permissions::VIEW_OTHER_PMS => true,
Permissions::EDIT_FEATURE => true,
Permissions::BULK_EDIT_VOTE => true,
Permissions::EDIT_OTHER_VOTE => true,
Permissions::VIEW_SYSINTO => true,
Permissions::VIEW_HELLBANNED => true,
Permissions::PROTECTED => true,
Permissions::EDIT_IMAGE_RATING => true,
Permissions::BULK_EDIT_IMAGE_RATING => true,
Permissions::VIEW_TRASH => true,
Permissions::PERFORM_BULK_ACTIONS => true,
]);
new UserClass("hellbanned", "user", [
"hellbanned" => true,
Permissions::HELLBANNED => true,
]);
@include_once "data/config/user-classes.conf.php";

View File

@ -16,7 +16,7 @@ function mtimefile(string $file): string
function get_theme(): string
{
global $config;
$theme = $config->get_string("theme", "default");
$theme = $config->get_string(SetupConfig::THEME, "default");
if (!file_exists("themes/$theme")) {
$theme = "default";
}
@ -588,8 +588,8 @@ function show_ip(string $ip, string $ban_reason): string
global $user;
$u_reason = url_escape($ban_reason);
$u_end = url_escape("+1 week");
$ban = $user->can("ban_ip") ? ", <a href='".make_link("ip_ban/list", "ip=$ip&reason=$u_reason&end=$u_end#add")."'>Ban</a>" : "";
$ip = $user->can("view_ip") ? $ip.$ban : "";
$ban = $user->can(Permissions::BAN_IP) ? ", <a href='".make_link("ip_ban/list", "ip=$ip&reason=$u_reason&end=$u_end#add")."'>Ban</a>" : "";
$ip = $user->can(Permissions::VIEW_IP) ? $ip.$ban : "";
return $ip;
}

View File

@ -54,7 +54,7 @@ class AdminPage extends Extension
global $page, $user;
if ($event->page_matches("admin")) {
if (!$user->can("manage_admintools")) {
if (!$user->can(Permissions::MANAGE_ADMINTOOLS)) {
$this->theme->display_permission_denied();
} else {
if ($event->count_args() == 0) {
@ -108,10 +108,20 @@ class AdminPage extends Extension
$this->theme->display_form();
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::MANAGE_ADMINTOOLS)) {
$event->add_nav_link("admin", new Link('admin'), "Board Admin");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("manage_admintools")) {
if ($user->can(Permissions::MANAGE_ADMINTOOLS)) {
$event->add_link("Board Admin", make_link("admin"));
}
}

View File

@ -36,7 +36,7 @@ class AliasEditor extends Extension
if ($event->page_matches("alias")) {
if ($event->get_arg(0) == "add") {
if ($user->can("manage_alias_list")) {
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
if (isset($_POST['oldtag']) && isset($_POST['newtag'])) {
try {
$aae = new AddAliasEvent($_POST['oldtag'], $_POST['newtag']);
@ -49,7 +49,7 @@ class AliasEditor extends Extension
}
}
} elseif ($event->get_arg(0) == "remove") {
if ($user->can("manage_alias_list")) {
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
if (isset($_POST['oldtag'])) {
$database->execute("DELETE FROM aliases WHERE oldtag=:oldtag", ["oldtag" => $_POST['oldtag']]);
log_info("alias_editor", "Deleted alias for ".$_POST['oldtag'], "Deleted alias");
@ -85,7 +85,7 @@ class AliasEditor extends Extension
$page->set_filename("aliases.csv");
$page->set_data($this->get_alias_csv($database));
} elseif ($event->get_arg(0) == "import") {
if ($user->can("manage_alias_list")) {
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
if (count($_FILES) > 0) {
$tmp = $_FILES['alias_file']['tmp_name'];
$contents = file_get_contents($tmp);
@ -117,10 +117,17 @@ class AliasEditor extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="tags") {
$event->add_nav_link("aliases", new Link('alias/list'), "Aliases", NavLink::is_active(["alias"]));
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("manage_alias_list")) {
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
$event->add_link("Alias Editor", make_link("alias/list"));
}
}

View File

@ -11,7 +11,7 @@ class AliasEditorTheme extends Themelet
{
global $page, $user;
$can_manage = $user->can("manage_alias_list");
$can_manage = $user->can(Permissions::MANAGE_ALIAS_LIST);
if ($can_manage) {
$h_action = "<th width='10%'>Action</th>";
$h_add = "

View File

@ -47,12 +47,23 @@ class Artists extends Extension
public function onSearchTermParse(SearchTermParseEvent $event)
{
$matches = [];
if (preg_match("/^author[=|:](.*)$/i", $event->term, $matches)) {
if (preg_match("/^(author|artist)[=|:](.*)$/i", $event->term, $matches)) {
$char = $matches[1];
$event->add_querylet(new Querylet("Author = :author_char", ["author_char"=>$char]));
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Artist";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
public function onInitExt(InitExtEvent $event)
{
global $config, $database;

View File

@ -545,4 +545,14 @@ class ArtistsTheme extends Themelet
}
return $html;
}
public function get_help_html()
{
return '<p>Search for images with a particular artist.</p>
<div class="command_example">
<pre>artist=leonardo</pre>
<p>Returns images with the artist "leonardo".</p>
</div>
';
}
}

View File

@ -58,7 +58,7 @@ xanax
public function onCommentPosting(CommentPostingEvent $event)
{
global $user;
if (!$user->can("bypass_comment_checks")) {
if (!$user->can(Permissions::BYPASS_COMMENT_CHECKS)) {
$this->test_text($event->comment, new CommentPostingException("Comment contains banned terms"));
}
}

View File

@ -26,10 +26,20 @@ class Blocks extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::MANAGE_BLOCKS)) {
$event->add_nav_link("blocks", new Link('blocks/list'), "Blocks Editor");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("manage_blocks")) {
if ($user->can(Permissions::MANAGE_BLOCKS)) {
$event->add_link("Blocks Editor", make_link("blocks/list"));
}
}
@ -52,7 +62,7 @@ class Blocks extends Extension
}
}
if ($event->page_matches("blocks") && $user->can("manage_blocks")) {
if ($event->page_matches("blocks") && $user->can(Permissions::MANAGE_BLOCKS)) {
if ($event->get_arg(0) == "add") {
if ($user->check_auth_token()) {
$database->execute("

View File

@ -56,6 +56,17 @@ class Blotter extends Extension
$event->panel->add_block($sb);
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->is_admin()) {
$event->add_nav_link("blotter", new Link('blotter/editor'), "Blotter Editor");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;

View File

@ -27,14 +27,14 @@ class BrowserSearch extends Extension
// Add in header code to let the browser know that the search plugin exists
// We need to build the data for the header
$search_title = $config->get_string('title');
$search_title = $config->get_string(SetupConfig::TITLE);
$search_file_url = make_link('browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml');
$page->add_html_header("<link rel='search' type='application/opensearchdescription+xml' title='$search_title' href='$search_file_url'>");
// The search.xml file that is generated on the fly
if ($event->page_matches("browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml")) {
// First, we need to build all the variables we'll need
$search_title = $config->get_string('title');
$search_title = $config->get_string(SetupConfig::TITLE);
$search_form_url = make_link('post/list/{searchTerms}');
$suggenton_url = make_link('browser_search/')."{searchTerms}";
$icon_b64 = base64_encode(file_get_contents("ext/handle_static/static/favicon.ico"));

View File

@ -85,11 +85,11 @@ class BulkActions extends Extension
{
global $user;
if ($user->can("delete_image")) {
if ($user->can(Permissions::DELETE_IMAGE)) {
$event->add_action("bulk_delete", "(D)elete", "d", "Delete selected images?", $this->theme->render_ban_reason_input(), 10);
}
if ($user->can("bulk_edit_image_tag")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG)) {
$event->add_action(
"bulk_tag",
@ -100,7 +100,7 @@ class BulkActions extends Extension
10);
}
if ($user->can("bulk_edit_image_source")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_SOURCE)) {
$event->add_action("bulk_source", "Set (S)ource", "s","", $this->theme->render_source_input(), 10);
}
}
@ -111,7 +111,7 @@ class BulkActions extends Extension
switch ($event->action) {
case "bulk_delete":
if ($user->can("delete_image")) {
if ($user->can(Permissions::DELETE_IMAGE)) {
$i = $this->delete_items($event->items);
flash_message("Deleted $i items");
}
@ -120,7 +120,7 @@ class BulkActions extends Extension
if (!isset($_POST['bulk_tags'])) {
return;
}
if ($user->can("bulk_edit_image_tag")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG)) {
$tags = $_POST['bulk_tags'];
$replace = false;
if (isset($_POST['bulk_tags_replace']) && $_POST['bulk_tags_replace'] == "true") {
@ -135,7 +135,7 @@ class BulkActions extends Extension
if (!isset($_POST['bulk_source'])) {
return;
}
if ($user->can("bulk_edit_image_source")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_SOURCE)) {
$source = $_POST['bulk_source'];
$i = $this->set_source($event->items, $source);
flash_message("Set source for $i items");
@ -147,7 +147,7 @@ class BulkActions extends Extension
public function onPageRequest(PageRequestEvent $event)
{
global $page, $user;
if ($event->page_matches("bulk_action") && $user->can("perform_bulk_actions")) {
if ($event->page_matches("bulk_action") && $user->can(Permissions::PERFORM_BULK_ACTIONS)) {
if (!isset($_POST['bulk_action'])) {
return;
}

View File

@ -157,6 +157,21 @@ class CommentList extends Extension
}
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
$event->add_nav_link("comment", new Link('comment/list'), "Comments");
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="comment") {
$event->add_nav_link("comment_list", new Link('comment/list'), "All");
$event->add_nav_link("comment_help", new Link('ext_doc/comment'), "Help");
}
}
public function onPageRequest(PageRequestEvent $event)
{
if ($event->page_matches("comment")) {
@ -189,7 +204,7 @@ class CommentList extends Extension
private function onPageRequest_delete(PageRequestEvent $event)
{
global $user, $page;
if ($user->can("delete_comment")) {
if ($user->can(Permissions::DELETE_COMMENT)) {
// FIXME: post, not args
if ($event->count_args() === 3) {
send_event(new CommentDeletionEvent($event->get_arg(1)));
@ -209,7 +224,7 @@ class CommentList extends Extension
private function onPageRequest_bulk_delete()
{
global $user, $database, $page;
if ($user->can("delete_comment") && !empty($_POST["ip"])) {
if ($user->can(Permissions::DELETE_COMMENT) && !empty($_POST["ip"])) {
$ip = $_POST['ip'];
$comment_ids = $database->get_col("
@ -288,7 +303,7 @@ class CommentList extends Extension
$this->theme->display_image_comments(
$event->image,
$this->get_comments($event->image->id),
$user->can("create_comment")
$user->can(Permissions::CREATE_COMMENT)
);
}
@ -351,6 +366,16 @@ class CommentList extends Extension
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Comments";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
// page building {{{
private function build_page(int $current_page)
{
@ -399,7 +424,7 @@ class CommentList extends Extension
}
}
$this->theme->display_comment_list($images, $current_page, $total_pages, $user->can("create_comment"));
$this->theme->display_comment_list($images, $current_page, $total_pages, $user->can(Permissions::CREATE_COMMENT));
}
// }}}
@ -574,7 +599,7 @@ class CommentList extends Extension
{
global $database, $page;
if (!$user->can("bypass_comment_checks")) {
if (!$user->can(Permissions::BYPASS_COMMENT_CHECKS)) {
// will raise an exception if anything is wrong
$this->comment_checks($image_id, $user, $comment);
}
@ -600,7 +625,7 @@ class CommentList extends Extension
global $config, $page;
// basic sanity checks
if (!$user->can("create_comment")) {
if (!$user->can(Permissions::CREATE_COMMENT)) {
throw new CommentPostingException("Anonymous posting has been disabled");
} elseif (is_null(Image::by_id($image_id))) {
throw new CommentPostingException("The image does not exist");

View File

@ -218,9 +218,9 @@ class CommentListTheme extends Themelet
if (!array_key_exists($comment->poster_ip, $this->anon_map)) {
$this->anon_map[$comment->poster_ip] = $this->anon_id;
}
#if($user->can("view_ip")) {
#if($user->can(UserAbilities::VIEW_IP)) {
#$style = " style='color: ".$this->get_anon_colour($comment->poster_ip).";'";
if ($user->can("view_ip") || $config->get_bool("comment_samefags_public", false)) {
if ($user->can(Permissions::VIEW_IP) || $config->get_bool("comment_samefags_public", false)) {
if ($this->anon_map[$comment->poster_ip] != $this->anon_id) {
$anoncode2 = '<sup>('.$this->anon_map[$comment->poster_ip].')</sup>';
}
@ -248,9 +248,9 @@ class CommentListTheme extends Themelet
$h_avatar = "<img src=\"//www.gravatar.com/avatar/$hash.jpg?cacheBreak=$cb\"><br>";
}
$h_reply = " - <a href='javascript: replyTo($i_image_id, $i_comment_id, \"$h_name\")'>Reply</a>";
$h_ip = $user->can("view_ip") ? "<br>".show_ip($comment->poster_ip, "Comment posted {$comment->posted}") : "";
$h_ip = $user->can(Permissions::VIEW_IP) ? "<br>".show_ip($comment->poster_ip, "Comment posted {$comment->posted}") : "";
$h_del = "";
if ($user->can("delete_comment")) {
if ($user->can(Permissions::DELETE_COMMENT)) {
$comment_preview = substr(html_unescape($tfe->stripped), 0, 50);
$j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview");
$h_delete_script = html_escape("return confirm($j_delete_confirm_message);");
@ -290,4 +290,28 @@ class CommentListTheme extends Themelet
</div>
';
}
public function get_help_html()
{
return '<p>Search for images containing a certain number of comments, or comments by a particular individual.</p>
<div class="command_example">
<pre>comments=1</pre>
<p>Returns images with exactly 1 comment.</p>
</div>
<div class="command_example">
<pre>comments>0</pre>
<p>Returns images with 1 or more comments. </p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =.</p>
<div class="command_example">
<pre>commented_by:username</pre>
<p>Returns images that have been commented on by "username". </p>
</div>
<div class="command_example">
<pre>commented_by_userno:123</pre>
<p>Returns images that have been commented on by user 123. </p>
</div>
';
}
}

View File

@ -65,7 +65,7 @@ class custom_html_headers extends Extension
global $config, $page;
// get config values
$site_title = $config->get_string("title");
$site_title = $config->get_string(SetupConfig::TITLE);
$sitename_in_title = $config->get_int("sitename_in_title");
// if feature is enabled & sitename isn't already in title

View File

@ -297,7 +297,7 @@ class DanbooruApi extends Extension
// Now we check if a file was uploaded or a url was provided to transload
// Much of this code is borrowed from /ext/upload
if (!$user->can("create_image")) {
if (!$user->can(Permissions::CREATE_IMAGE)) {
$page->set_code(409);
$page->add_http_header("X-Danbooru-Errors: authentication error");
return;

View File

@ -32,7 +32,7 @@ class Downtime extends Extension
global $config, $page, $user;
if ($config->get_bool("downtime")) {
if (!$user->can("ignore_downtime") && !$this->is_safe_page($event)) {
if (!$user->can(Permissions::IGNORE_DOWNTIME) && !$this->is_safe_page($event)) {
$msg = $config->get_string("downtime_message");
$this->theme->display_message($msg);
if (!defined("UNITTEST")) { // hax D:

View File

@ -21,7 +21,7 @@ class DowntimeTheme extends Themelet
public function display_message(string $message)
{
global $config, $user, $page;
$theme_name = $config->get_string('theme');
$theme_name = $config->get_string(SetupConfig::THEME);
$data_href = get_base_href();
$login_link = make_link("user_admin/login");
$auth = $user->get_auth_html();

View File

@ -18,16 +18,28 @@ class ET extends Extension
{
global $user;
if ($event->page_matches("system_info")) {
if ($user->can("view_sysinfo")) {
if ($user->can(Permissions::VIEW_SYSINTO)) {
$this->theme->display_info_page($this->get_info());
}
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::VIEW_SYSINTO)) {
$event->add_nav_link("system_info", new Link('system_info'), "System Info", null, 10);
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("view_sysinfo")) {
if ($user->can(Permissions::VIEW_SYSINTO)) {
$event->add_link("System Info", make_link("system_info"));
}
}
@ -40,8 +52,8 @@ class ET extends Extension
global $config, $database;
$info = [];
$info['site_title'] = $config->get_string("title");
$info['site_theme'] = $config->get_string("theme");
$info['site_title'] = $config->get_string(SetupConfig::TITLE);
$info['site_theme'] = $config->get_string(SetupConfig::THEME);
$info['site_url'] = "http://" . $_SERVER["HTTP_HOST"] . get_base_href();
$info['sys_shimmie'] = VERSION;

View File

@ -118,7 +118,7 @@ class ExtManager extends Extension
{
global $page, $user;
if ($event->page_matches("ext_manager")) {
if ($user->can("manage_extension_list")) {
if ($user->can(Permissions::MANAGE_EXTENSION_LIST)) {
if ($event->get_arg(0) == "set" && $user->check_auth_token()) {
if (is_writable("data/config")) {
$this->set_things($_POST);
@ -162,11 +162,22 @@ class ExtManager extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::MANAGE_EXTENSION_LIST)) {
$event->add_nav_link("ext_manager", new Link('ext_manager'), "Extension Manager");
} else {
$event->add_nav_link("ext_doc", new Link('ext_doc'), "Board Help");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("manage_extension_list")) {
if ($user->can(Permissions::MANAGE_EXTENSION_LIST)) {
$event->add_link("Extension Manager", make_link("ext_manager"));
} else {
$event->add_link("Help", make_link("ext_doc"));

View File

@ -155,6 +155,30 @@ class Favorites extends Extension
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Favorites";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent=="posts") {
$event->add_nav_link("posts_favorites", new Link("post/list/favorited_by={$user->name}/1"), "My Favorites");
}
if($event->parent==="user") {
if ($user->can(Permissions::MANAGE_ADMINTOOLS)) {
$username = url_escape($user->name);
$event->add_nav_link("favorites", new Link("post/list/favorited_by=$username/1"), "My Favorites");
}
}
}
private function install()
{

View File

@ -34,4 +34,28 @@ class FavoritesTheme extends Themelet
$page->add_block(new Block("Favorited By", $html, "left", 25));
}
public function get_help_html()
{
return '<p>Search for images that have been favorited a certain number of times, or favorited by a particular individual.</p>
<div class="command_example">
<pre>favorites=1</pre>
<p>Returns images that have been favorited once.</p>
</div>
<div class="command_example">
<pre>favorites>0</pre>
<p>Returns images that have been favorited 1 or more times</p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =.</p>
<div class="command_example">
<pre>favorited_by:username</pre>
<p>Returns images that have been favorited by "username". </p>
</div>
<div class="command_example">
<pre>favorited_by_userno:123</pre>
<p>Returns images that have been favorited by user 123. </p>
</div>
';
}
}

View File

@ -32,7 +32,7 @@ class Featured extends Extension
global $config, $page, $user;
if ($event->page_matches("featured_image")) {
if ($event->get_arg(0) == "set" && $user->check_auth_token()) {
if ($user->can("edit_feature") && isset($_POST['image_id'])) {
if ($user->can(Permissions::EDIT_FEATURE) && isset($_POST['image_id'])) {
$id = int_escape($_POST['image_id']);
if ($id > 0) {
$config->set_int("featured_id", $id);
@ -86,7 +86,7 @@ class Featured extends Extension
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $user;
if ($user->can("edit_feature")) {
if ($user->can(Permissions::EDIT_FEATURE)) {
$event->add_part($this->theme->get_buttons_html($event->image->id));
}
}

View File

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

View File

@ -9,9 +9,9 @@ class HellBan extends Extension
{
global $page, $user;
if ($user->can("hellbanned")) {
if ($user->can(Permissions::HELLBANNED)) {
$s = "";
} elseif ($user->can("view_hellbanned")) {
} elseif ($user->can(Permissions::VIEW_HELLBANNED)) {
$s = "DIV.hb, TR.hb TD {border: 1px solid red !important;}";
} else {
$s = ".hb {display: none !important;}";

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

94
ext/help_pages/main.php Normal file
View File

@ -0,0 +1,94 @@
<?php
/**
* Name: Help Pages
* Author: Matthew Barbour <matthew@darkholme.net>
* License: MIT
* Description: Provides documentation screens
*/
class HelpPageListBuildingEvent extends Event
{
public $pages = [];
public function add_page(string $key, string $name)
{
$this->pages[$key] = $name;
}
}
class HelpPageBuildingEvent extends Event
{
public $key;
public $blocks = [];
public function __construct(string $key)
{
$this->key = $key;
}
function add_block(Block $block, int $position = 50)
{
if(!array_key_exists("$position",$this->blocks))
{
$this->blocks["$position"] = [];
}
$this->blocks["$position"][] = $block;
}
}
class HelpPages extends Extension
{
public const SEARCH = "search";
public function onPageRequest(PageRequestEvent $event)
{
global $page, $user;
if ($event->page_matches("help")) {
$e = new HelpPageListBuildingEvent();
send_event($e);
$page->set_mode(PageMode::PAGE);
if ($event->count_args() == 0) {
$this->theme->display_list_page($e->pages);
} else {
$name = $event->get_arg(0);
$title = $name;
if(array_key_exists($name, $e->pages)) {
$title = $e->pages[$name];
}
$this->theme->display_help_page($title);
$hpbe = new HelpPageBuildingEvent($name);
send_event($hpbe);
asort($hpbe->blocks);
foreach ($hpbe->blocks as $key=>$value) {
foreach($value as $block) {
$page->add_block($block);
}
}
}
}
}
public function onHelpPageListBuilding(HelpPageListBuildingEvent $event)
{
$event->add_page("search", "Searching");
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
$event->add_nav_link("help", new Link('help'), "Help");
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
$event->add_link("Help", make_link("help"));
}
}

13
ext/help_pages/style.css Normal file
View File

@ -0,0 +1,13 @@
.command_example {
margin: 12pt;
padding-left: 16pt;
}
.command_example pre {
padding:4pt;
border: dashed 2px black;
}
.command_example p {
padding-left: 16pt;
}

31
ext/help_pages/theme.php Normal file
View File

@ -0,0 +1,31 @@
<?php
class HelpPagesTheme extends Themelet
{
public function display_list_page(array $pages)
{
global $page;
$page->set_title("Help Pages");
$page->set_heading("Help Pages");
$nav_block = new Block("Help", "", "left", 0);
foreach ($pages as $link=>$desc) {
$link = make_link("help/{$link}");
$nav_block->body .= "<a href='{$link}'>".html_escape($desc)."</a><br/>";
}
$page->add_block($nav_block);
$page->add_block(new Block("Help Pages", "See list of pages to left"));
}
public function display_help_page(String $title)
{
global $page;
$page->set_title("Help - $title");
$page->set_heading("Help - $title");
}
}

View File

@ -22,8 +22,8 @@ class Home extends Extension
global $config, $page;
if ($event->page_matches("home")) {
$base_href = get_base_href();
$sitename = $config->get_string('title');
$theme_name = $config->get_string('theme');
$sitename = $config->get_string(SetupConfig::TITLE);
$theme_name = $config->get_string(SetupConfig::THEME);
$body = $this->get_body();
@ -52,7 +52,7 @@ class Home extends Extension
// returns just the contents of the body
global $config;
$base_href = get_base_href();
$sitename = $config->get_string('title');
$sitename = $config->get_string(SetupConfig::TITLE);
$contact_link = contact_link();
if (is_null($contact_link)) {
$contact_link = "";

View File

@ -73,7 +73,7 @@ class ImageIO extends Extension
{
if ($event->page_matches("image/delete")) {
global $page, $user;
if ($user->can("delete_image") && isset($_POST['image_id']) && $user->check_auth_token()) {
if ($user->can(Permissions::DELETE_IMAGE) && isset($_POST['image_id']) && $user->check_auth_token()) {
$image = Image::by_id($_POST['image_id']);
if ($image) {
send_event(new ImageDeletionEvent($image));
@ -87,7 +87,7 @@ class ImageIO extends Extension
}
} elseif ($event->page_matches("image/replace")) {
global $page, $user;
if ($user->can("replace_image") && isset($_POST['image_id']) && $user->check_auth_token()) {
if ($user->can(Permissions::REPLACE_IMAGE) && isset($_POST['image_id']) && $user->check_auth_token()) {
$image = Image::by_id($_POST['image_id']);
if ($image) {
$page->set_mode(PageMode::REDIRECT);
@ -110,11 +110,11 @@ class ImageIO extends Extension
{
global $user;
if ($user->can("delete_image")) {
if ($user->can(Permissions::DELETE_IMAGE)) {
$event->add_part($this->theme->get_deleter_html($event->image->id));
}
/* In the future, could perhaps allow users to replace images that they own as well... */
if ($user->can("replace_image")) {
if ($user->can(Permissions::REPLACE_IMAGE)) {
$event->add_part($this->theme->get_replace_html($event->image->id));
}
}

View File

@ -64,7 +64,7 @@ class ImageBan extends Extension
global $database, $page, $user;
if ($event->page_matches("image_hash_ban")) {
if ($user->can("ban_image")) {
if ($user->can(Permissions::BAN_IMAGE)) {
if ($event->get_arg(0) == "add") {
$image = isset($_POST['image_id']) ? Image::by_id(int_escape($_POST['image_id'])) : null;
$hash = isset($_POST["hash"]) ? $_POST["hash"] : $image->hash;
@ -103,10 +103,21 @@ class ImageBan extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_nav_link("image_bans", new Link('image_hash_ban/list/1'), "Image Bans", NavLink::is_active(["image_hash_ban"]));
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("ban_image")) {
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_link("Image Bans", make_link("image_hash_ban/list/1"));
}
}
@ -130,7 +141,7 @@ class ImageBan extends Extension
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $user;
if ($user->can("ban_image")) {
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_part($this->theme->get_buttons_html($event->image));
}
}

View File

@ -332,6 +332,29 @@ class Index extends Extension
}
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
$event->add_nav_link("posts", new Link('post/list'), "Posts", NavLink::is_active(["post","view"]),20);
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="posts") {
$event->add_nav_link("posts_all", new Link('post/list'), "All");
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "General";
$block->body = $this->theme->get_help_html();
$event->add_block($block, 0);
}
}
public function onSearchTermParse(SearchTermParseEvent $event)
{
$matches = [];
@ -380,6 +403,7 @@ class Index extends Extension
$event->add_querylet(new Querylet('images.source LIKE :src', ["src"=>"%$source%"]));
}
} elseif (preg_match("/^posted([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9-]*)$/i", $event->term, $matches)) {
// TODO Make this able to search = without needing a time component.
$cmp = ltrim($matches[1], ":") ?: "=";
$val = $matches[2];
$event->add_querylet(new Querylet("images.posted $cmp :posted{$this->stpen}", ["posted{$this->stpen}"=>$val]));

View File

@ -110,7 +110,7 @@ and of course start organising your images :-)
global $config;
if (count($this->search_terms) == 0) {
$page_title = $config->get_string('title');
$page_title = $config->get_string(SetupConfig::TITLE);
} else {
$search_string = implode(' ', $this->search_terms);
$page_title = html_escape($search_string);
@ -144,4 +144,201 @@ and of course start organising your images :-)
$this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages, true);
}
}
public function get_help_html()
{
return '<p>Searching is largely based on tags, with a number of special keywords available that allow searching based on properties of the images.</p>
<div class="command_example">
<pre>tagname</pre>
<p>Returns images that are tagged with "tagname".</p>
</div>
<div class="command_example">
<pre>tagname othertagname</pre>
<p>Returns images that are tagged with "tagname" and "othertagname".</p>
</div>
<p>Most tags and keywords can be prefaced with a negative sign (-) to indicate that you want to search for images that do not match something.</p>
<div class="command_example">
<pre>-tagname</pre>
<p>Returns images that are not tagged with "tagname".</p>
</div>
<div class="command_example">
<pre>-tagname -othertagname</pre>
<p>Returns images that are not tagged with "tagname" and "othertagname". This is different than without the negative sign, as images with "tagname" or "othertagname" can still be returned as long as the other one is not present.</p>
</div>
<div class="command_example">
<pre>tagname -othertagname</pre>
<p>Returns images that are tagged with "tagname", but are not tagged with "othertagname".</p>
</div>
<p>Wildcard searches are possible as well using * for "any one, more, or none" and ? for "any one".</p>
<div class="command_example">
<pre>tagn*</pre>
<p>Returns images that are tagged with "tagname", "tagnot", or anything else that starts with "tagn".</p>
</div>
<div class="command_example">
<pre>tagn?me</pre>
<p>Returns images that are tagged with "tagname", "tagnome", or anything else that starts with "tagn", has one character, and ends with "me".</p>
</div>
<div class="command_example">
<pre>tags=1</pre>
<p>Returns images with exactly 1 tag.</p>
</div>
<div class="command_example">
<pre>tags>0</pre>
<p>Returns images with 1 or more tags. </p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =.</p>
<hr/>
<p>Search for images by aspect ratio</p>
<div class="command_example">
<pre>ratio=4:3</pre>
<p>Returns images with an aspect ratio of 4:3.</p>
</div>
<div class="command_example">
<pre>ratio>16:9</pre>
<p>Returns images with an aspect ratio greater than 16:9. </p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =. The relation is calculated by dividing width by height.</p>
<hr/>
<p>Search for images by file size</p>
<div class="command_example">
<pre>filesize=1</pre>
<p>Returns images exactly 1 byte in size.</p>
</div>
<div class="command_example">
<pre>filesize>100mb</pre>
<p>Returns images greater than 100 megabytes in size. </p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =. Supported suffixes are kb, mb, and gb. Uses multiples of 1024.</p>
<hr/>
<p>Search for images by MD5 hash</p>
<div class="command_example">
<pre>hash=0D3512CAA964B2BA5D7851AF5951F33B</pre>
<p>Returns image with an MD5 hash 0D3512CAA964B2BA5D7851AF5951F33B.</p>
</div>
<hr/>
<p>Search for images by file type</p>
<div class="command_example">
<pre>filetype=jpg</pre>
<p>Returns images that are of type "jpg".</p>
</div>
<hr/>
<p>Search for images by file name</p>
<div class="command_example">
<pre>filename=picasso.jpg</pre>
<p>Returns images that are named "picasso.jpg".</p>
</div>
<hr/>
<p>Search for images by source</p>
<div class="command_example">
<pre>source=http://google.com/</pre>
<p>Returns images with a source of "http://google.com/".</p>
</div>
<div class="command_example">
<pre>source=any</pre>
<p>Returns images with a source set.</p>
</div>
<div class="command_example">
<pre>source=none</pre>
<p>Returns images without a source set.</p>
</div>
<hr/>
<p>Search for images by date posted.</p>
<div class="command_example">
<pre>posted>=07-19-2019</pre>
<p>Returns images posted on or after 07-19-2019.</p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =. Date format is mm-dd-yyyy. Date posted includes time component, so = will not work unless the time is exact.</p>
<hr/>
<p>Search for images by image dimensions</p>
<div class="command_example">
<pre>size=640x480</pre>
<p>Returns images exactly 640 pixels wide by 480 pixels high.</p>
</div>
<div class="command_example">
<pre>size>1920x1080</pre>
<p>Returns images with a width larger than 1920 and a height larger than 1080.</p>
</div>
<div class="command_example">
<pre>width=1000</pre>
<p>Returns images exactly 1000 pixels wide.</p>
</div>
<div class="command_example">
<pre>height=1000</pre>
<p>Returns images exactly 1000 pixels high.</p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =.</p>
<hr/>
<p>Sorting search results can be done using the pattern order:field_direction. _direction can be either _asc or _desc, indicating ascending (123) or descending (321) order.</p>
<div class="command_example">
<pre>order:id_asc</pre>
<p>Returns images sorted by ID, smallest first.</p>
</div>
<div class="command_example">
<pre>order:width_desc</pre>
<p>Returns images sorted by width, largest first.</p>
</div>
<p>These fields are supported:
<ul>
<li>id</li>
<li>width</li>
<li>height</li>
<li>filesize</li>
<li>filename</li>
</ul>
</p>
';
}
}

View File

@ -66,7 +66,7 @@ class IPBan extends Extension
{
if ($event->page_matches("ip_ban")) {
global $page, $user;
if ($user->can("ban_ip")) {
if ($user->can(Permissions::BAN_IP)) {
if ($event->get_arg(0) == "add" && $user->check_auth_token()) {
if (isset($_POST['ip']) && isset($_POST['reason']) && isset($_POST['end'])) {
if (empty($_POST['end'])) {
@ -105,10 +105,20 @@ class IPBan extends Extension
$event->panel->add_block($sb);
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::BAN_IP)) {
$event->add_nav_link("ip_bans", new Link('ip_ban/list'), "IP Bans", NavLink::is_active(["ip_ban"]));
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("ban_ip")) {
if ($user->can(Permissions::BAN_IP)) {
$event->add_link("IP Bans", make_link("ip_ban/list"));
}
}

View File

@ -48,7 +48,7 @@ class LogDatabase extends Extension
{
global $database, $user;
if ($event->page_matches("log/view")) {
if ($user->can("view_eventlog")) {
if ($user->can(Permissions::VIEW_EVENTLOG)) {
$wheres = [];
$args = [];
$page_num = int_escape($event->get_arg(0));
@ -120,10 +120,20 @@ class LogDatabase extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::VIEW_EVENTLOG)) {
$event->add_nav_link("event_log", new Link('log/view'), "Event Log");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("view_eventlog")) {
if ($user->can(Permissions::VIEW_EVENTLOG)) {
$event->add_link("Event Log", make_link("log/view"));
}
}

View File

@ -316,7 +316,7 @@ class Media extends Extension
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $user;
if ($user->can("delete_image")) {
if ($user->can(Permissions::DELETE_IMAGE)) {
$event->add_part($this->theme->get_buttons_html($event->image->id));
}
}
@ -419,6 +419,17 @@ class Media extends Extension
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Media";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
public function onTagTermParse(TagTermParseEvent $event)
{
$matches = [];

View File

@ -28,4 +28,20 @@ class MediaTheme extends Themelet
</form>
";
}
public function get_help_html()
{
return '<p>Search for items based on the type of media.</p>
<div class="command_example">
<pre>content:audio</pre>
<p>Returns items that contain audio, including videos and audio files.</p>
</div>
<div class="command_example">
<pre>content:video</pre>
<p>Returns items that contain video, including animated GIFs.</p>
</div>
<p>These search terms depend on the items being scanned for media content. Automatic scanning was implemented in mid-2019, so items uploaded before, or items uploaded on a system without ffmpeg, will require additional scanning before this will work.</p>
';
}
}

View File

@ -58,10 +58,20 @@ class NotATag extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="tags") {
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_nav_link("untags", new Link('untag/list/1'), "UnTags");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("ban_image")) {
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_link("UnTags", make_link("untag/list/1"));
}
}
@ -71,7 +81,7 @@ class NotATag extends Extension
global $database, $page, $user;
if ($event->page_matches("untag")) {
if ($user->can("ban_image")) {
if ($user->can(Permissions::BAN_IMAGE)) {
if ($event->get_arg(0) == "add") {
$tag = $_POST["tag"];
$redirect = isset($_POST['redirect']) ? $_POST['redirect'] : "DNP";

View File

@ -210,12 +210,22 @@ class Notes extends Extension
}
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)"));
} elseif (preg_match("/^notes_by_userno[=|:](\d+)$/i", $event->term, $matches)) {
$user_id = int_escape($matches[1]);
} elseif (preg_match("/^(notes_by_userno|notes_by_user_id)[=|:](\d+)$/i", $event->term, $matches)) {
$user_id = int_escape($matches[2]);
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)"));
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Notes";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
/**
* HERE WE GET ALL NOTES FOR DISPLAYED IMAGE.

View File

@ -247,4 +247,29 @@ class NotesTheme extends Themelet
$this->display_paginator($page, "note/updated", null, $pageNumber, $totalPages);
}
public function get_help_html()
{
return '<p>Search for images with notes.</p>
<div class="command_example">
<pre>note=noted</pre>
<p>Returns images with a note matching "noted".</p>
</div>
<div class="command_example">
<pre>notes>0</pre>
<p>Returns images with 1 or more notes.</p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =.</p>
<div class="command_example">
<pre>notes_by=username</pre>
<p>Returns images with note(s) by "username".</p>
</div>
<div class="command_example">
<pre>notes_by_user_id=123</pre>
<p>Returns images with note(s) by user 123.</p>
</div>
';
}
}

View File

@ -45,7 +45,7 @@ class NumericScore extends Extension
public function onUserPageBuilding(UserPageBuildingEvent $event)
{
global $user;
if ($user->can("edit_other_vote")) {
if ($user->can(Permissions::EDIT_OTHER_VOTE)) {
$this->theme->get_nuller($event->display_user);
}
@ -98,7 +98,7 @@ class NumericScore extends Extension
$page->set_redirect(make_link("post/view/$image_id"));
}
} elseif ($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) {
if ($user->can("edit_other_vote")) {
if ($user->can(Permissions::EDIT_OTHER_VOTE)) {
$image_id = int_escape($_POST['image_id']);
$database->execute(
"DELETE FROM numeric_score_votes WHERE image_id=?",
@ -112,7 +112,7 @@ class NumericScore extends Extension
$page->set_redirect(make_link("post/view/$image_id"));
}
} elseif ($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) {
if ($user->can("edit_other_vote")) {
if ($user->can(Permissions::EDIT_OTHER_VOTE)) {
$this->delete_votes_by(int_escape($_POST['user_id']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
@ -228,6 +228,16 @@ class NumericScore extends Extension
$event->replace('$score', $event->image->numeric_score);
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Numeric Score";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
public function onSearchTermParse(SearchTermParseEvent $event)
{
$matches = [];
@ -294,6 +304,16 @@ class NumericScore extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="posts") {
$event->add_nav_link("numeric_score_day", new Link('popular_by_day'), "Popular by Day");
$event->add_nav_link("numeric_score_month", new Link('popular_by_month'), "Popular by Month");
$event->add_nav_link("numeric_score_year", new Link('popular_by_year'), "Popular by Year");
}
}
private function install()
{
global $database;

View File

@ -32,7 +32,7 @@ class NumericScoreTheme extends Themelet
<input type='submit' value='Vote Down'>
</form>
";
if ($user->can("edit_other_vote")) {
if ($user->can(Permissions::EDIT_OTHER_VOTE)) {
$html .= "
<form action='".make_link("numeric_score/remove_votes_on")."' method='POST'>
".$user->get_auth_html()."
@ -87,8 +87,51 @@ class NumericScoreTheme extends Themelet
$nav_html = "<a href=".make_link().">Index</a>";
$page->set_heading($config->get_string('title'));
$page->set_heading($config->get_string(SetupConfig::TITLE));
$page->add_block(new Block("Navigation", $nav_html, "left", 10));
$page->add_block(new Block(null, $html, "main", 30));
}
public function get_help_html()
{
return '<p>Search for images that have received numeric scores by the score or by the scorer.</p>
<div class="command_example">
<pre>score=1</pre>
<p>Returns images with a score of 1.</p>
</div>
<div class="command_example">
<pre>score>0</pre>
<p>Returns images with a score of 1 or more.</p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =.</p>
<div class="command_example">
<pre>upvoted_by=username</pre>
<p>Returns images upvoted by "username".</p>
</div>
<div class="command_example">
<pre>upvoted_by_id=123</pre>
<p>Returns images upvoted by user 123.</p>
</div>
<div class="command_example">
<pre>downvoted_by=username</pre>
<p>Returns images downvoted by "username".</p>
</div>
<div class="command_example">
<pre>downvoted_by_id=123</pre>
<p>Returns images downvoted by user 123.</p>
</div>
<div class="command_example">
<pre>order:score_desc</pre>
<p>Sorts the search results by score, descending.</p>
</div>
<div class="command_example">
<pre>order:score_asc</pre>
<p>Sorts the search results by score, ascending.</p>
</div>
';
}
}

View File

@ -12,7 +12,7 @@ class Oekaki extends Extension
global $user, $page;
if ($event->page_matches("oekaki")) {
if ($user->can("create_image")) {
if ($user->can(Permissions::CREATE_IMAGE)) {
if ($event->get_arg(0) == "create") {
$this->theme->display_page();
$this->theme->display_block();
@ -84,7 +84,7 @@ class Oekaki extends Extension
public function onPostListBuilding(PostListBuildingEvent $event)
{
global $user;
if ($user->can("create_image")) {
if ($user->can(Permissions::CREATE_IMAGE)) {
$this->theme->display_block();
}
}

View File

@ -410,7 +410,7 @@ class OuroborosAPI extends Extension
if ($event->page_matches('post')) {
if ($this->match('create')) {
// Create
if ($user->can("create_image")) {
if ($user->can(Permissions::CREATE_IMAGE)) {
$md5 = !empty($_REQUEST['md5']) ? filter_var($_REQUEST['md5'], FILTER_SANITIZE_STRING) : null;
$this->postCreate(new OuroborosPost($_REQUEST['post']), $md5);
} else {

View File

@ -93,6 +93,19 @@ class PrivMsg extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="user") {
if (!$user->is_anonymous()) {
$count = $this->count_pms($user);
$h_count = $count > 0 ? " <span class='unread'>($count)</span>" : "";
$event->add_nav_link("pm", new Link('user#private-messages'), "Private Messages$h_count");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
@ -108,7 +121,7 @@ class PrivMsg extends Extension
global $page, $user;
$duser = $event->display_user;
if (!$user->is_anonymous() && !$duser->is_anonymous()) {
if (($user->id == $duser->id) || $user->can("view_other_pms")) {
if (($user->id == $duser->id) || $user->can(Permissions::VIEW_OTHER_PMS)) {
$this->theme->display_pms($page, $this->get_pms($duser));
}
if ($user->id != $duser->id) {
@ -128,7 +141,7 @@ class PrivMsg extends Extension
$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");
} elseif (($pm["to_id"] == $user->id) || $user->can("view_other_pms")) {
} elseif (($pm["to_id"] == $user->id) || $user->can(Permissions::VIEW_OTHER_PMS)) {
$from_user = User::by_id(int_escape($pm["from_id"]));
if ($pm["to_id"] == $user->id) {
$database->execute("UPDATE private_message SET is_read='Y' WHERE id = :id", ["id" => $pm_id]);
@ -145,7 +158,7 @@ class PrivMsg extends Extension
$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");
} elseif (($pm["to_id"] == $user->id) || $user->can("view_other_pms")) {
} elseif (($pm["to_id"] == $user->id) || $user->can(Permissions::VIEW_OTHER_PMS)) {
$database->execute("DELETE FROM private_message WHERE id = :id", ["id" => $pm_id]);
$database->cache->delete("pm-count-{$user->id}");
log_info("pm", "Deleted PM #$pm_id", "PM deleted");

View File

@ -27,7 +27,7 @@ class PrivMsgTheme extends Themelet
$h_subject = "<b>$h_subject</b>";
$readYN = "N";
}
$hb = $from->can("hellbanned") ? "hb" : "";
$hb = $from->can(Permissions::HELLBANNED) ? "hb" : "";
$html .= "<tr class='$hb'>
<td>$readYN</td>
<td><a href='$pm_url'>$h_subject</a></td>

View File

@ -145,6 +145,23 @@ class Pools extends Extension
$event->panel->add_block($sb);
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
$event->add_nav_link("pool", new Link('pool/list'), "Pools");
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="pool") {
$event->add_nav_link("pool_list", new Link('pool/list'), "List");
$event->add_nav_link("pool_new", new Link('pool/new'), "Create");
$event->add_nav_link("pool_updated", new Link('pool/updated'), "Changes");
$event->add_nav_link("pool_help", new Link('ext_doc/pools'), "Help");
}
}
public function onPageRequest(PageRequestEvent $event)
{
global $page, $user, $database;
@ -355,6 +372,17 @@ class Pools extends Extension
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Pools";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
public function onSearchTermParse(SearchTermParseEvent $event)
{
$matches = [];

View File

@ -403,4 +403,32 @@ class PoolsTheme extends Themelet
{
return "<input type='text' name='bulk_pool_new' placeholder='New pool' required='required' value='".(implode(" ",$search_terms))."' />";
}
public function get_help_html()
{
return '<p>Search for images that are in a pool.</p>
<div class="command_example">
<pre>pool=1</pre>
<p>Returns images in pool #1.</p>
</div>
<div class="command_example">
<pre>pool=any</pre>
<p>Returns images in any pool.</p>
</div>
<div class="command_example">
<pre>pool=none</pre>
<p>Returns images not in any pool.</p>
</div>
<div class="command_example">
<pre>pool_by_name=swimming</pre>
<p>Returns images in the "swimming" pool.</p>
</div>
<div class="command_example">
<pre>pool_by_name=swimming_pool</pre>
<p>Returns images in the "swimming pool" pool. Note that the underscore becomes a space</p>
</div>
';
}
}

View File

@ -0,0 +1,9 @@
<?php
abstract class PostTitlesConfig
{
public const VERSION = "ext_post_titles_version";
public const DEFAULT_TO_FILENAME = "post_titles_default_to_filename";
public const SHOW_IN_WINDOW_TITLE = "post_titles_show_in_window_title";
}

View File

@ -0,0 +1,13 @@
<?php
class PostTitleSetEvent extends Event
{
public $image;
public $title;
public function __construct(Image $image, String $title)
{
$this->image = $image;
$this->title = $title;
}
}

107
ext/post_titles/main.php Normal file
View File

@ -0,0 +1,107 @@
<?php
/**
* Name: Post Titles
* Author: Matthew Barbour <matthew@darkholme.net>
* License: MIT
* Description: Add titles to media posts
*/
require_once "config.php";
require_once "events/post_title_set_event.php";
class PostTitles extends Extension
{
public function get_priority(): int
{
return 60;
}
public function onInitExt(InitExtEvent $event)
{
global $config, $database;
$config->set_default_bool(PostTitlesConfig::DEFAULT_TO_FILENAME, false);
$config->set_default_bool(PostTitlesConfig::SHOW_IN_WINDOW_TITLE, false);
if ($config->get_int(PostTitlesConfig::VERSION) < 1) {
$this->install();
}
}
private function install()
{
global $config, $database;
if ($config->get_int(PostTitlesConfig::VERSION) < 1) {
$database->Execute("ALTER TABLE images ADD COLUMN title varchar(255) NULL");
$config->set_int(PostTitlesConfig::VERSION, 1);
}
}
public function onDisplayingImage(DisplayingImageEvent $event)
{
global $config;
if($config->get_bool(PostTitlesConfig::SHOW_IN_WINDOW_TITLE)) {
$event->set_title(self::get_title($event->get_image()));
}
}
public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event)
{
global $user;
$event->add_part($this->theme->get_title_set_html(self::get_title($event->image), $user->can(Permissions::EDIT_IMAGE_TITLE)), 10);
}
public function onImageInfoSet(ImageInfoSetEvent $event)
{
global $user;
if ($user->can(Permissions::EDIT_IMAGE_TITLE) && isset($_POST["post_title"])) {
$title = $_POST["post_title"];
send_event(new PostTitleSetEvent($event->image, $title));
}
}
public function onPostTitleSet(PostTitleSetEvent $event)
{
$this->set_title($event->image->id, $event->title);
}
public function onSetupBuilding(SetupBuildingEvent $event)
{
$sb = new SetupBlock("Post Titles");
$sb->start_table();
$sb->add_bool_option(PostTitlesConfig::DEFAULT_TO_FILENAME,"Default to filename", true);
$sb->add_bool_option(PostTitlesConfig::SHOW_IN_WINDOW_TITLE,"Show in window title", true);
$sb->end_table();
$event->panel->add_block($sb);
}
private function set_title(int $image_id, string $title)
{
global $database;
$database->Execute("UPDATE images SET title=? WHERE id=?", [$title, $image_id]);
log_info("post_titles", "Title for Image #{$image_id} set to: ".$title);
}
public static function get_title(Image $image): string
{
global $config;
$title = $image->title??"";
if(empty($title) && $config->get_bool(PostTitlesConfig::DEFAULT_TO_FILENAME)) {
$info = pathinfo($image->filename);
if(array_key_exists("extension",$info)) {
$title = basename($image->filename, '.' . $info['extension']);
} else {
$title = $image->filename;
}
}
return $title;
}
}

25
ext/post_titles/theme.php Normal file
View File

@ -0,0 +1,25 @@
<?php
class PostTitlesTheme extends Themelet
{
public function get_title_set_html(string $title, bool $can_set): string
{
$html = "
<tr>
<th>Title</th>
<td>
".($can_set ? "
<span class='view'>".html_escape($title)."</span>
<span class='edit'>
<input class='edit' type='text' name='post_title' value='".html_escape($title)."' />
</span>
" : html_escape("
$title
"))."
</td>
</tr>
";
return $html;
}
}

View File

@ -75,4 +75,11 @@ class RandomImage extends Extension
}
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="posts") {
$event->add_nav_link("posts_random", new Link('random_image/view'), "Random Image");
}
}
}

View File

@ -74,4 +74,11 @@ class RandomList extends Extension
$event->panel->add_block($sb);
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="posts") {
$event->add_nav_link("posts_random", new Link('random'), "Shuffle");
}
}
}

View File

@ -126,6 +126,21 @@ class Ratings extends Extension
$event->replace('$rating', $this->rating_to_human($event->image->rating));
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
global $user;
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Ratings";
$ratings = self::get_sorted_ratings();
$block->body = $this->theme->get_help_html($ratings);
$event->add_block($block);
}
}
public function onSearchTermParse(SearchTermParseEvent $event)
{
global $user;
@ -169,7 +184,7 @@ class Ratings extends Extension
{
global $user;
if ($user->can("bulk_edit_image_rating")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_RATING)) {
$event->add_action("bulk_rate","Set (R)ating", "r","",$this->theme->get_selection_rater_html("u","bulk_rating"));
}
}
@ -183,7 +198,7 @@ class Ratings extends Extension
if (!isset($_POST['bulk_rating'])) {
return;
}
if ($user->can("bulk_edit_image_rating")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_RATING)) {
$rating = $_POST['bulk_rating'];
$total = 0;
foreach ($event->items as $image) {
@ -201,7 +216,7 @@ class Ratings extends Extension
global $user, $page;
if ($event->page_matches("admin/bulk_rate")) {
if (!$user->can("bulk_edit_image_rating")) {
if (!$user->can(Permissions::BULK_EDIT_IMAGE_RATING)) {
throw new PermissionDeniedException();
} else {
$n = 0;

View File

@ -55,4 +55,32 @@ class RatingsTheme extends Themelet
<option value='u'>Unrated</option>
</select>";
}
public function get_help_html(array $ratings)
{
$output = '<p>Search for images with one or more possible ratings.</p>
<div class="command_example">
<pre>rating:'.$ratings[0]->search_term.'</pre>
<p>Returns images with the '.$ratings[0]->name.' rating.</p>
</div>
<p>Ratings can be abbreviated to a single letter as well</p>
<div class="command_example">
<pre>rating:'.$ratings[0]->code.'</pre>
<p>Returns images with the '.$ratings[0]->name.' rating.</p>
</div>
<p>If abbreviations are used, multiple ratings can be searched for.</p>
<div class="command_example">
<pre>rating:'.$ratings[0]->code.$ratings[1]->code.'</pre>
<p>Returns images with the '.$ratings[0]->name.' or '.$ratings[1]->name.' rating.</p>
</div>
<p>Available ratings:</p>
<table>
<tr><th>Name</th><th>Search Term</th><th>Abbreviation</th></tr>
';
foreach ($ratings as $rating) {
$output .= "<tr><td>{$rating->name}</td><td>{$rating->search_term}</td><td>{$rating->code}</td></tr>";
}
$output .= "</table>";
return $output;
}
}

View File

@ -28,14 +28,14 @@ class RegenThumb extends Extension
{
global $database, $page, $user;
if ($event->page_matches("regen_thumb/one") && $user->can("delete_image") && isset($_POST['image_id'])) {
if ($event->page_matches("regen_thumb/one") && $user->can(Permissions::DELETE_IMAGE) && isset($_POST['image_id'])) {
$image = Image::by_id(int_escape($_POST['image_id']));
$this->regenerate_thumbnail($image);
$this->theme->display_results($page, $image);
}
if ($event->page_matches("regen_thumb/mass") && $user->can("delete_image") && isset($_POST['tags'])) {
if ($event->page_matches("regen_thumb/mass") && $user->can(Permissions::DELETE_IMAGE) && isset($_POST['tags'])) {
$tags = Tag::explode(strtolower($_POST['tags']), false);
$images = Image::find_images(0, 10000, $tags);
@ -51,7 +51,7 @@ class RegenThumb extends Extension
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $user;
if ($user->can("delete_image")) {
if ($user->can(Permissions::DELETE_IMAGE)) {
$event->add_part($this->theme->get_buttons_html($event->image->id));
}
}
@ -59,7 +59,7 @@ class RegenThumb extends Extension
// public function onPostListBuilding(PostListBuildingEvent $event)
// {
// global $user;
// if ($user->can("delete_image") && !empty($event->search_terms)) {
// if ($user->can(UserAbilities::DELETE_IMAGE) && !empty($event->search_terms)) {
// $event->add_control($this->theme->mtr_html(Tag::implode($event->search_terms)));
// }
// }
@ -68,7 +68,7 @@ class RegenThumb extends Extension
{
global $user;
if ($user->can("delete_image")) {
if ($user->can(Permissions::DELETE_IMAGE)) {
$event->add_action("bulk_regen", "Regen Thumbnails", "","", $this->theme->bulk_html());
}
}
@ -79,7 +79,7 @@ class RegenThumb extends Extension
switch ($event->action) {
case "bulk_regen":
if ($user->can("delete_image")) {
if ($user->can(Permissions::DELETE_IMAGE)) {
$force = true;
if (isset($_POST["bulk_regen_thumb_missing_only"])
&&$_POST["bulk_regen_thumb_missing_only"]=="true") {

View File

@ -81,6 +81,17 @@ class Relationships extends Extension
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Relationships";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
public function onTagTermParse(TagTermParseEvent $event)
{
$matches = [];

View File

@ -46,4 +46,32 @@ class RelationshipsTheme extends Themelet
"</tr>\n";
return $html;
}
public function get_help_html()
{
return '<p>Search for images that have parent/child relationships.</p>
<div class="command_example">
<pre>parent=any</pre>
<p>Returns images that have a parent.</p>
</div>
<div class="command_example">
<pre>parent=none</pre>
<p>Returns images that have no parent.</p>
</div>
<div class="command_example">
<pre>parent=123</pre>
<p>Returns images that have image 123 set as parent.</p>
</div>
<div class="command_example">
<pre>child=any</pre>
<p>Returns images that have at least 1 child.</p>
</div>
<div class="command_example">
<pre>child=none</pre>
<p>Returns images that have no children.</p>
</div>
';
}
}

View File

@ -74,7 +74,7 @@ class ReportImage extends Extension
}
} elseif ($event->get_arg(0) == "remove") {
if (!empty($_POST['id'])) {
if ($user->can("view_image_report")) {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
send_event(new RemoveReportedImageEvent($_POST['id']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("image_report/list"));
@ -83,13 +83,13 @@ class ReportImage extends Extension
$this->theme->display_error(500, "Missing input", "Missing image ID");
}
} elseif ($event->get_arg(0) == "remove_reports_by" && $user->check_auth_token()) {
if ($user->can("view_image_report")) {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
$this->delete_reports_by(int_escape($_POST['user_id']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
} elseif ($event->get_arg(0) == "list") {
if ($user->can("view_image_report")) {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
$this->theme->display_reported_images($page, $this->get_reported_images());
}
}
@ -118,7 +118,7 @@ class ReportImage extends Extension
public function onUserPageBuilding(UserPageBuildingEvent $event)
{
global $user;
if ($user->can("view_image_report")) {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
$this->theme->get_nuller($event->display_user);
}
}
@ -126,16 +126,30 @@ class ReportImage extends Extension
public function onDisplayingImage(DisplayingImageEvent $event)
{
global $user;
if ($user->can('create_image_report')) {
if ($user->can(Permissions::CREATE_IMAGE_REPORT)) {
$reps = $this->get_reports($event->image);
$this->theme->display_image_banner($event->image, $reps);
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
$count = $this->count_reported_images();
$h_count = $count > 0 ? " ($count)" : "";
$event->add_nav_link("image_report", new Link('image_report/list'), "Reported Images$h_count");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("view_image_report")) {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
$count = $this->count_reported_images();
$h_count = $count > 0 ? " ($count)" : "";
$event->add_link("Reported Images$h_count", make_link("image_report/list"));

View File

@ -14,7 +14,7 @@ class RSS_Comments extends Extension
public function onPostListBuilding(PostListBuildingEvent $event)
{
global $config, $page;
$title = $config->get_string('title');
$title = $config->get_string(SetupConfig::TITLE);
$page->add_html_header("<link rel=\"alternate\" type=\"application/rss+xml\" ".
"title=\"$title - Comments\" href=\"".make_link("rss/comments")."\" />");
@ -60,7 +60,7 @@ class RSS_Comments extends Extension
";
}
$title = $config->get_string('title');
$title = $config->get_string(SetupConfig::TITLE);
$base_href = make_http(get_base_href());
$version = $config->get_string('version');
$xml = <<<EOD
@ -79,4 +79,12 @@ EOD;
$page->set_data($xml);
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="comment") {
$event->add_nav_link("comment_rss", new Link('rss/comments'), "Feed");
}
}
}

View File

@ -12,7 +12,7 @@ class RSS_Images extends Extension
public function onPostListBuilding(PostListBuildingEvent $event)
{
global $config, $page;
$title = $config->get_string('title');
$title = $config->get_string(SetupConfig::TITLE);
if (count($event->search_terms) > 0) {
$search = html_escape(implode(' ', $event->search_terms));
@ -47,7 +47,7 @@ class RSS_Images extends Extension
$data .= $this->thumb($image);
}
$title = $config->get_string('title');
$title = $config->get_string(SetupConfig::TITLE);
$base_href = make_http(get_base_href());
$search = "";
if (count($search_terms) > 0) {
@ -116,4 +116,11 @@ class RSS_Images extends Extension
return $data;
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="posts") {
$event->add_nav_link("posts_rss", new Link('rss/images'), "Feed");
}
}
}

View File

@ -50,7 +50,7 @@ class Rule34 extends Extension
public function onUserPageBuilding(UserPageBuildingEvent $event)
{
global $database, $user, $config;
if ($user->can("change_setting") && $config->get_bool('r34_comic_integration')) {
if ($user->can(Permissions::CHANGE_SETTING) && $config->get_bool('r34_comic_integration')) {
$current_state = bool_escape($database->get_one("SELECT comic_admin FROM users WHERE id=?", [$event->display_user->id]));
$this->theme->show_comic_changer($event->display_user, $current_state);
}
@ -59,7 +59,7 @@ class Rule34 extends Extension
public function onThumbnailGeneration(ThumbnailGenerationEvent $event)
{
global $database, $user;
if ($user->can("manage_admintools")) {
if ($user->can(Permissions::MANAGE_ADMINTOOLS)) {
$database->execute("NOTIFY shm_image_bans, '{$event->hash}';");
}
}
@ -72,7 +72,7 @@ class Rule34 extends Extension
{
global $database, $page, $user;
if ($user->can("delete_user")) { // deleting users can take a while
if ($user->can(Permissions::DELETE_USER)) { // deleting users can take a while
$database->execute("SET statement_timeout TO ".(DATABASE_TIMEOUT+15000).";");
}
@ -81,7 +81,7 @@ class Rule34 extends Extension
}
if ($event->page_matches("rule34/comic_admin")) {
if ($user->can("change_setting") && $user->check_auth_token()) {
if ($user->can(Permissions::CHANGE_SETTING) && $user->check_auth_token()) {
$input = validate_input([
'user_id' => 'user_id,exists',
'is_admin' => 'bool',
@ -102,7 +102,7 @@ class Rule34 extends Extension
}
if ($event->page_matches("admin/cache_purge")) {
if (!$user->can("manage_admintools")) {
if (!$user->can(Permissions::MANAGE_ADMINTOOLS)) {
$this->theme->display_permission_denied();
} else {
if ($user->check_auth_token()) {
@ -130,7 +130,7 @@ class Rule34 extends Extension
if ($event->page_matches("sys_ip_ban")) {
global $page, $user;
if ($user->can("ban_ip")) {
if ($user->can(Permissions::BAN_IP)) {
if ($event->get_arg(0) == "list") {
$bans = (isset($_GET["all"])) ? $this->get_bans() : $this->get_active_bans();
$this->theme->display_bans($page, $bans);

12
ext/setup/config.php Normal file
View File

@ -0,0 +1,12 @@
<?php
class SetupConfig
{
public const TITLE = "title";
public const FRONT_PAGE = "front_page";
public const MAIN_PAGE = "main_page";
public const THEME = "theme";
public const WORD_WRAP = "word_wrap";
public const COMMENT_CAPTCHA = "comment_captcha";
}

View File

@ -6,6 +6,8 @@
* Description: Allows the site admin to configure the board to his or her taste
*/
include_once "config.php";
/* ConfigSaveEvent {{{
*
* Sent when the setup screen's 'set' button has been
@ -275,12 +277,11 @@ class Setup extends Extension
public function onInitExt(InitExtEvent $event)
{
global $config;
$config->set_default_string("title", "Shimmie");
$config->set_default_string("front_page", "post/list");
$config->set_default_string("main_page", "post/list");
$config->set_default_string("theme", "default");
$config->set_default_bool("word_wrap", true);
$config->set_default_bool("comment_captcha", false);
$config->set_default_string(SetupConfig::TITLE, "Shimmie");
$config->set_default_string(SetupConfig::FRONT_PAGE, "post/list");
$config->set_default_string(SetupConfig::MAIN_PAGE, "post/list");
$config->set_default_string(SetupConfig::THEME, "default");
$config->set_default_bool(SetupConfig::WORD_WRAP, true);
}
public function onPageRequest(PageRequestEvent $event)
@ -293,7 +294,7 @@ class Setup extends Extension
}
if ($event->page_matches("setup")) {
if (!$user->can("change_setting")) {
if (!$user->can(Permissions::CHANGE_SETTING)) {
$this->theme->display_permission_denied();
} else {
if ($event->get_arg(0) == "save" && $user->check_auth_token()) {
@ -368,11 +369,11 @@ class Setup extends Extension
</script>";
$sb = new SetupBlock("General");
$sb->position = 0;
$sb->add_text_option("title", "Site title: ");
$sb->add_text_option("front_page", "<br>Front page: ");
$sb->add_text_option("main_page", "<br>Main page: ");
$sb->add_text_option(SetupConfig::TITLE, "Site title: ");
$sb->add_text_option(SetupConfig::FRONT_PAGE, "<br>Front page: ");
$sb->add_text_option(SetupConfig::MAIN_PAGE, "<br>Main page: ");
$sb->add_text_option("contact_link", "<br>Contact URL: ");
$sb->add_choice_option("theme", $themes, "<br>Theme: ");
$sb->add_choice_option(SetupConfig::THEME, $themes, "<br>Theme: ");
//$sb->add_multichoice_option("testarray", array("a" => "b", "c" => "d"), "<br>Test Array: ");
$sb->add_bool_option("nice_urls", "<br>Nice URLs: ");
$sb->add_label("<span id='nicetest'>(Javascript inactive, can't test!)</span>$nicescript");
@ -410,10 +411,20 @@ class Setup extends Extension
log_warning("setup", "Cache cleared");
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::CHANGE_SETTING)) {
$event->add_nav_link("setup", new Link('setup'), "Board Config", null, 0);
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("change_setting")) {
if ($user->can(Permissions::CHANGE_SETTING)) {
$event->add_link("Board Config", make_link("setup"));
}
}

View File

@ -74,7 +74,7 @@ class XMLSitemap extends Extension
// add index
$index = [];
$index[0] = $config->get_string("front_page");
$index[0] = $config->get_string(SetupConfig::FRONT_PAGE);
$this->add_sitemap_queue($index, "weekly", "1");
/* --- Add 20 most used tags --- */

View File

@ -35,13 +35,13 @@ class Source_History extends Extension
if ($event->page_matches("source_history/revert")) {
// this is a request to revert to a previous version of the source
if ($user->can("edit_image_tag")) {
if ($user->can(Permissions::EDIT_IMAGE_TAG)) {
if (isset($_POST['revert'])) {
$this->process_revert_request($_POST['revert']);
}
}
} elseif ($event->page_matches("source_history/bulk_revert")) {
if ($user->can("bulk_edit_image_tag") && $user->check_auth_token()) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG) && $user->check_auth_token()) {
$this->process_bulk_revert_request();
}
} elseif ($event->page_matches("source_history/all")) {
@ -82,10 +82,20 @@ class Source_History extends Extension
$this->add_source_history($event->image, $event->source);
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG)) {
$event->add_nav_link("source_history", new Link('source_history/all/1'), "Source Changes", NavLink::is_active(["source_history"]));
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("bulk_edit_image_tag")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG)) {
$event->add_link("Source Changes", make_link("source_history/all/1"));
}
}

View File

@ -20,7 +20,7 @@ class Source_HistoryTheme extends Themelet
$current_source = html_escape($fields['source']);
$name = $fields['name'];
$date_set = autodate($fields['date_set']);
$h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Sourcing Image #$image_id as '$current_source'") : "";
$h_ip = $user->can(Permissions::VIEW_IP) ? " ".show_ip($fields['user_ip'], "Sourcing Image #$image_id as '$current_source'") : "";
$setter = "<a href='".make_link("user/".url_escape($name))."'>".html_escape($name)."</a>$h_ip";
$selected = ($n == 2) ? " checked" : "";
@ -72,7 +72,7 @@ class Source_HistoryTheme extends Themelet
$image_id = $fields['image_id'];
$current_source = html_escape($fields['source']);
$name = $fields['name'];
$h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Sourcing Image #$image_id as '$current_source'") : "";
$h_ip = $user->can(Permissions::VIEW_IP) ? " ".show_ip($fields['user_ip'], "Sourcing Image #$image_id as '$current_source'") : "";
$setter = "<a href='".make_link("user/".url_escape($name))."'>".html_escape($name)."</a>$h_ip";
$history_list .= '

31
ext/system/main.php Normal file
View File

@ -0,0 +1,31 @@
<?php
/**
* Name: System
* Author: Matthew Barbour <matthew@darkholme.net>
* License: MIT
* Description: Provides system screen
*/
class System extends Extension
{
public function onPageRequest(PageRequestEvent $event)
{
global $page, $user;
if ($event->page_matches("system")) {
$e = new PageSubNavBuildingEvent("system");
send_event($e);
usort($e->links, "sort_nav_links");
$link = $e->links[0]->link;
$page->set_redirect($link->make_link());
$page->set_mode(PageMode::REDIRECT);
}
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
$event->add_nav_link("system", new Link('system'), "System");
}
}

View File

@ -0,0 +1,8 @@
<?php
abstract class TagCategoriesConfig
{
public const VERSION = "ext_tag_categories_version";
public const SPLIT_ON_VIEW = "tag_categories_split_on_view";
}

View File

@ -6,6 +6,8 @@
* Description: Let tags be split into 'categories', like Danbooru's tagging
*/
require_once "config.php";
class TagCategories extends Extension
{
public function onInitExt(InitExtEvent $event)
@ -14,9 +16,9 @@ class TagCategories extends Extension
// whether we split out separate categories on post view by default
// note: only takes effect if /post/view shows the image's exact tags
$config->set_default_bool("tag_categories_split_on_view", true);
$config->set_default_bool(TagCategoriesConfig::SPLIT_ON_VIEW, true);
if ($config->get_int("ext_tag_categories_version") < 1) {
if ($config->get_int(TagCategoriesConfig::VERSION) < 1) {
// primary extension database, holds all our stuff!
$database->create_table(
'image_tag_categories',
@ -26,7 +28,7 @@ class TagCategories extends Extension
color VARCHAR(7)'
);
$config->set_int("ext_tag_categories_version", 1);
$config->set_int(TagCategoriesConfig::VERSION, 1);
log_info("tag_categories", "extension installed");
}
@ -68,11 +70,12 @@ class TagCategories extends Extension
if (preg_match("/^(.+)tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9]+)$/i", $event->term, $matches)) {
global $database;
$type = $matches[1];
$type = strtolower($matches[1]);
$cmp = ltrim($matches[2], ":") ?: "=";
$count = $matches[3];
$types = $database->get_col('SELECT category FROM image_tag_categories');
$types = $database->get_col(
$database->scoreql_to_sql('SELECT SCORE_STRNORM(category) FROM image_tag_categories'));
if (in_array($type, $types)) {
$event->add_querylet(
new Querylet($database->scoreql_to_sql("EXISTS (
@ -88,6 +91,16 @@ class TagCategories extends Extension
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Tag Categories";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
public function getDict()
{
global $database;

View File

@ -98,4 +98,21 @@ class TagCategoriesTheme extends Themelet
// add html to stuffs
$page->add_block(new Block("Editing", $html, "main", 10));
}
public function get_help_html()
{
return '<p>Search for images containing a certain number of tags with the specified tag category.</p>
<div class="command_example">
<pre>persontags=1</pre>
<p>Returns images with exactly 1 tag with the tag category "person".</p>
</div>
<div class="command_example">
<pre>cattags>0</pre>
<p>Returns images with 1 or more tags with the tag category "cat". </p>
</div>
<p>Can use &lt;, &lt;=, &gt;, &gt;=, or =.</p>
<p>Category name is not case sensitive, category must exist for search to work.</p>
';
}
}

View File

@ -161,7 +161,7 @@ class TagEdit extends Extension
global $user, $page;
if ($event->page_matches("tag_edit")) {
if ($event->get_arg(0) == "replace") {
if ($user->can("mass_tag_edit") && isset($_POST['search']) && isset($_POST['replace'])) {
if ($user->can(Permissions::MASS_TAG_EDIT) && isset($_POST['search']) && isset($_POST['replace'])) {
$search = $_POST['search'];
$replace = $_POST['replace'];
$this->mass_tag_edit($search, $replace);
@ -170,7 +170,7 @@ class TagEdit extends Extension
}
}
if ($event->get_arg(0) == "mass_source_set") {
if ($user->can("mass_tag_edit") && isset($_POST['tags']) && isset($_POST['source'])) {
if ($user->can(Permissions::MASS_TAG_EDIT) && isset($_POST['tags']) && isset($_POST['source'])) {
$this->mass_source_edit($_POST['tags'], $_POST['source']);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
@ -182,7 +182,7 @@ class TagEdit extends Extension
// public function onPostListBuilding(PostListBuildingEvent $event)
// {
// global $user;
// if ($user->can("bulk_edit_image_source") && !empty($event->search_terms)) {
// if ($user->can(UserAbilities::BULK_EDIT_IMAGE_SOURCE) && !empty($event->search_terms)) {
// $event->add_control($this->theme->mss_html(Tag::implode($event->search_terms)));
// }
// }
@ -190,7 +190,7 @@ class TagEdit extends Extension
public function onImageInfoSet(ImageInfoSetEvent $event)
{
global $user;
if ($user->can("edit_image_owner") && isset($_POST['tag_edit__owner'])) {
if ($user->can(Permissions::EDIT_IMAGE_OWNER) && isset($_POST['tag_edit__owner'])) {
$owner = User::by_name($_POST['tag_edit__owner']);
if ($owner instanceof User) {
send_event(new OwnerSetEvent($event->image, $owner));
@ -206,7 +206,7 @@ class TagEdit extends Extension
send_event(new SourceSetEvent($event->image, $_POST['tag_edit__source']));
}
}
if ($user->can("edit_image_lock")) {
if ($user->can(Permissions::EDIT_IMAGE_LOCK)) {
$locked = isset($_POST['tag_edit__locked']) && $_POST['tag_edit__locked']=="on";
send_event(new LockSetEvent($event->image, $locked));
}
@ -215,7 +215,7 @@ class TagEdit extends Extension
public function onOwnerSet(OwnerSetEvent $event)
{
global $user;
if ($user->can("edit_image_owner") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) {
if ($user->can(Permissions::EDIT_IMAGE_OWNER) && (!$event->image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK))) {
$event->image->set_owner($event->owner);
}
}
@ -223,7 +223,7 @@ class TagEdit extends Extension
public function onTagSet(TagSetEvent $event)
{
global $user;
if ($user->can("edit_image_tag") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) {
if ($user->can(Permissions::EDIT_IMAGE_TAG) && (!$event->image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK))) {
$event->image->set_tags($event->tags);
}
$event->image->parse_metatags($event->metatags, $event->image->id);
@ -232,7 +232,7 @@ class TagEdit extends Extension
public function onSourceSet(SourceSetEvent $event)
{
global $user;
if ($user->can("edit_image_source") && (!$event->image->is_locked() || $user->can("edit_image_lock"))) {
if ($user->can(Permissions::EDIT_IMAGE_SOURCE) && (!$event->image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK))) {
$event->image->set_source($event->source);
}
}
@ -240,7 +240,7 @@ class TagEdit extends Extension
public function onLockSet(LockSetEvent $event)
{
global $user;
if ($user->can("edit_image_lock")) {
if ($user->can(Permissions::EDIT_IMAGE_LOCK)) {
$event->image->set_locked($event->locked);
}
}
@ -255,6 +255,15 @@ class TagEdit extends Extension
$this->theme->display_mass_editor();
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="tags") {
$event->add_nav_link("tags_help", new Link('ext_doc/tag_edit'), "Help");
}
}
/**
* When an alias is added, oldtag becomes inaccessible.
*/
@ -288,13 +297,13 @@ class TagEdit extends Extension
private function can_tag(Image $image): bool
{
global $user;
return ($user->can("edit_image_tag") || !$image->is_locked());
return ($user->can(Permissions::EDIT_IMAGE_TAG) || !$image->is_locked());
}
private function can_source(Image $image): bool
{
global $user;
return ($user->can("edit_image_source") || !$image->is_locked());
return ($user->can(Permissions::EDIT_IMAGE_SOURCE) || !$image->is_locked());
}
private function mass_tag_edit(string $search, string $replace)

View File

@ -51,7 +51,7 @@ class TagEditTheme extends Themelet
<tr>
<th width='50px'>Tags</th>
<td>
".($user->can("edit_image_tag") ? "
".($user->can(Permissions::EDIT_IMAGE_TAG) ? "
<span class='view'>$h_tag_links</span>
<input class='edit autocomplete_tags' type='text' name='tag_edit__tags' value='$h_tags' id='tag_editor' autocomplete='off'>
" : "
@ -68,12 +68,12 @@ class TagEditTheme extends Themelet
$h_owner = html_escape($image->get_owner()->name);
$h_av = $image->get_owner()->get_avatar_html();
$h_date = autodate($image->posted);
$h_ip = $user->can("view_ip") ? " (".show_ip($image->owner_ip, "Image posted {$image->posted}").")" : "";
$h_ip = $user->can(Permissions::VIEW_IP) ? " (".show_ip($image->owner_ip, "Image posted {$image->posted}").")" : "";
return "
<tr>
<th>Uploader</th>
<td>
".($user->can("edit_image_owner") ? "
".($user->can(Permissions::EDIT_IMAGE_OWNER) ? "
<span class='view'><a class='username' href='".make_link("user/$h_owner")."'>$h_owner</a>$h_ip, $h_date</span>
<input class='edit' type='text' name='tag_edit__owner' value='$h_owner'>
" : "
@ -95,7 +95,7 @@ class TagEditTheme extends Themelet
<tr>
<th>Source</th>
<td>
".($user->can("edit_image_source") ? "
".($user->can(Permissions::EDIT_IMAGE_SOURCE) ? "
<div class='view' style='$style'>$f_source</div>
<input class='edit' type='text' name='tag_edit__source' value='$h_source'>
" : "
@ -132,7 +132,7 @@ class TagEditTheme extends Themelet
<tr>
<th>Locked</th>
<td>
".($user->can("edit_image_lock") ? "
".($user->can(Permissions::EDIT_IMAGE_LOCK) ? "
<span class='view'>$b_locked</span>
<input class='edit' type='checkbox' name='tag_edit__locked'$h_locked>
" : "

View File

@ -180,6 +180,6 @@ class TagEditCloud extends Extension
private function can_tag(Image $image): bool
{
global $user;
return ($user->can("edit_image_tag") && (!$image->is_locked() || $user->can("edit_image_lock")));
return ($user->can(Permissions::EDIT_IMAGE_TAG) && (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)));
}
}

View File

@ -35,13 +35,13 @@ class Tag_History extends Extension
if ($event->page_matches("tag_history/revert")) {
// this is a request to revert to a previous version of the tags
if ($user->can("edit_image_tag")) {
if ($user->can(Permissions::EDIT_IMAGE_TAG)) {
if (isset($_POST['revert'])) {
$this->process_revert_request($_POST['revert']);
}
}
} elseif ($event->page_matches("tag_history/bulk_revert")) {
if ($user->can("bulk_edit_image_tag") && $user->check_auth_token()) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG) && $user->check_auth_token()) {
$this->process_bulk_revert_request();
}
} elseif ($event->page_matches("tag_history/all")) {
@ -82,10 +82,21 @@ class Tag_History extends Extension
$this->add_tag_history($event->image, $event->tags);
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG)) {
$event->add_nav_link("tag_history", new Link('tag_history/all/1'), "Tag Changes", NavLink::is_active(["tag_history"]));
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
if ($user->can("bulk_edit_image_tag")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG)) {
$event->add_link("Tag Changes", make_link("tag_history/all/1"));
}
}

View File

@ -25,7 +25,7 @@ class Tag_HistoryTheme extends Themelet
$current_tags = html_escape($fields['tags']);
$name = $fields['name'];
$date_set = autodate($fields['date_set']);
$h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Tagging Image #$image_id as '$current_tags'") : "";
$h_ip = $user->can(Permissions::VIEW_IP) ? " ".show_ip($fields['user_ip'], "Tagging Image #$image_id as '$current_tags'") : "";
$setter = "<a href='".make_link("user/".url_escape($name))."'>".html_escape($name)."</a>$h_ip";
$selected = ($n == 2) ? " checked" : "";
@ -84,7 +84,7 @@ class Tag_HistoryTheme extends Themelet
$image_id = $fields['image_id'];
$current_tags = html_escape($fields['tags']);
$name = $fields['name'];
$h_ip = $user->can("view_ip") ? " ".show_ip($fields['user_ip'], "Tagging Image #$image_id as '$current_tags'") : "";
$h_ip = $user->can(Permissions::VIEW_IP) ? " ".show_ip($fields['user_ip'], "Tagging Image #$image_id as '$current_tags'") : "";
$setter = "<a href='".make_link("user/".url_escape($name))."'>".html_escape($name)."</a>$h_ip";
$history_list .= '

View File

@ -93,6 +93,21 @@ class TagList extends Extension
}
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
$event->add_nav_link("tags", new Link('tags/map'), "Tags");
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="tags") {
$event->add_nav_link("tags_map", new Link('tags/map'), "Map");
$event->add_nav_link("tags_alphabetic", new Link('tags/alphabetic'), "Alphabetic");
$event->add_nav_link("tags_popularity", new Link('tags/popularity'), "Popularity");
$event->add_nav_link("tags_categories", new Link('tags/categories'), "Categories");
}
}
public function onDisplayingImage(DisplayingImageEvent $event)
{
global $config, $page;
@ -100,7 +115,7 @@ class TagList extends Extension
if ($config->get_string('tag_list_image_type') == 'related') {
$this->add_related_block($page, $event->image);
} else {
if (class_exists("TagCategories") and $config->get_bool('tag_categories_split_on_view')) {
if (class_exists("TagCategories") and $config->get_bool(TagCategoriesConfig::SPLIT_ON_VIEW)) {
$this->add_split_tags_block($page, $event->image);
} else {
$this->add_tags_block($page, $event->image);

View File

@ -12,7 +12,7 @@ class Tagger extends Extension
{
global $page, $user;
if ($user->can("edit_image_tag") && ($event->image->is_locked() || $user->can("edit_image_lock"))) {
if ($user->can(Permissions::EDIT_IMAGE_TAG) && ($event->image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK))) {
$this->theme->build_tagger($page, $event);
}
}

View File

@ -73,6 +73,16 @@ class Tips extends Extension
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->is_admin()) {
$event->add_nav_link("tips", new Link('tips/list'), "Tips Editor");
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;

View File

@ -37,7 +37,7 @@ class Trash extends Extension
{
global $page, $user;
if ($event->page_matches("trash_restore") && $user->can("view_trash")) {
if ($event->page_matches("trash_restore") && $user->can(Permissions::VIEW_TRASH)) {
// Try to get the image ID
$image_id = int_escape($event->get_arg(0));
if (empty($image_id)) {
@ -59,7 +59,7 @@ class Trash extends Extension
{
global $user, $page;
if($event->image->trash===true && !$user->can("view_trash")) {
if($event->image->trash===true && !$user->can(Permissions::VIEW_TRASH)) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
}
@ -87,12 +87,26 @@ class Trash extends Extension
if (preg_match(self::SEARCH_REGEXP, strtolower($event->term), $matches)) {
if($user->can("view_trash")) {
if($user->can(Permissions::VIEW_TRASH)) {
$event->add_querylet(new Querylet($database->scoreql_to_sql("trash = SCORE_BOOL_Y ")));
}
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
global $user;
if($event->key===HelpPages::SEARCH) {
if($user->can(Permissions::VIEW_TRASH)) {
$block = new Block();
$block->header = "Trash";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
}
private function no_trash_query(array $context): bool
{
foreach ($context as $term) {
@ -114,7 +128,7 @@ class Trash extends Extension
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $config, $database, $user;
if($event->image->trash===true && $user->can("view_trash")) {
if($event->image->trash===true && $user->can(Permissions::VIEW_TRASH)) {
$event->add_part($this->theme->get_image_admin_html($event->image->id));
}
}
@ -123,7 +137,7 @@ class Trash extends Extension
{
global $user;
if ($user->can("view_trash")&&in_array("in:trash", $event->search_terms)) {
if ($user->can(Permissions::VIEW_TRASH)&&in_array("in:trash", $event->search_terms)) {
$event->add_action("bulk_trash_restore","(U)ndelete", "u");
}
}
@ -134,7 +148,7 @@ class Trash extends Extension
switch ($event->action) {
case "bulk_trash_restore":
if ($user->can("view_trash")) {
if ($user->can(Permissions::VIEW_TRASH)) {
$total = 0;
foreach ($event->items as $image) {
self::set_trash($image->id, false);

View File

@ -11,4 +11,16 @@ class TrashTheme extends Themelet
";
return $html; }
public function get_help_html()
{
return '<p>Search for images in the trash.</p>
<div class="command_example">
<pre>in:trash</pre>
<p>Returns images that are in the trash.</p>
</div>
';
}
}

View File

@ -138,6 +138,21 @@ class Upload extends Extension
$event->panel->add_block($sb);
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
$event->add_nav_link("upload",new Link('upload'), "Upload");
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
if($event->parent=="upload") {
if (class_exists("Wiki")) {
$event->add_nav_link("upload_guidelines", new Link('wiki/upload_guidelines'), "Guidelines");
}
}
}
public function onDataUpload(DataUploadEvent $event)
{
global $config;
@ -155,7 +170,7 @@ class Upload extends Extension
{
global $database, $page, $user;
if ($user->can("create_image")) {
if ($user->can(Permissions::CREATE_IMAGE)) {
if ($this->is_full) {
$this->theme->display_full($page);
} else {
@ -165,7 +180,7 @@ class Upload extends Extension
if ($event->page_matches("upload/replace")) {
// check if the user is an administrator and can upload files.
if (!$user->can("replace_image")) {
if (!$user->can(Permissions::REPLACE_IMAGE)) {
$this->theme->display_permission_denied();
} else {
if ($this->is_full) {
@ -221,7 +236,7 @@ class Upload extends Extension
}
}
} elseif ($event->page_matches("upload")) {
if (!$user->can("create_image")) {
if (!$user->can(Permissions::CREATE_IMAGE)) {
$this->theme->display_permission_denied();
} else {
/* Regular Upload Image */
@ -371,7 +386,7 @@ class Upload extends Extension
$ok = true;
// Checks if user is admin > check if you want locked.
if ($user->can("edit_image_lock") && !empty($_GET['locked'])) {
if ($user->can(Permissions::EDIT_IMAGE_LOCK) && !empty($_GET['locked'])) {
$locked = bool_escape($_GET['locked']);
}

View File

@ -189,7 +189,7 @@ class UploadTheme extends Themelet
global $config;
$link = make_http(make_link("upload"));
$main_page = make_http(make_link());
$title = $config->get_string('title');
$title = $config->get_string(SetupConfig::TITLE);
$max_size = $config->get_int('upload_size');
$max_kb = to_shorthand_int($max_size);
$delimiter = $config->get_bool('nice_urls') ? '?' : '&amp;';
@ -235,7 +235,7 @@ class UploadTheme extends Themelet
if (class_exists("VideoFileHandler")) {
$supported_ext .= " flv mp4 ogv webm m4v";
}
$title = "Booru to " . $config->get_string('title');
$title = "Booru to " . $config->get_string(SetupConfig::TITLE);
// CA=0: Ask to use current or new tags | CA=1: Always use current tags | CA=2: Always use new tags
$html .= '<p><a href="javascript:
var ste=&quot;'. $link . $delimiter .'url=&quot;;

View File

@ -127,7 +127,7 @@ class UserPage extends Extension
$a["name"] = '%' . $_GET['username'] . '%';
}
if ($user->can('delete_user') && @$_GET['email']) {
if ($user->can(Permissions::DELETE_USER) && @$_GET['email']) {
$q .= " AND SCORE_STRNORM(email) LIKE SCORE_STRNORM(:email)";
$a["email"] = '%' . $_GET['email'] . '%';
}
@ -212,7 +212,7 @@ class UserPage extends Extension
global $user, $config;
$h_join_date = autodate($event->display_user->join_date);
if ($event->display_user->can("hellbanned")) {
if ($event->display_user->can(Permissions::HELLBANNED)) {
$h_class = $event->display_user->class->parent->name;
} else {
$h_class = $event->display_user->class->name;
@ -237,6 +237,17 @@ class UserPage extends Extension
}
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
global $user;
if ($user->is_anonymous()) {
$event->add_nav_link("user", new Link('user_admin/login'), "Account", null, 10);
} else {
$event->add_nav_link("user", new Link('user'), "Account", null, 10);
}
}
private function display_stats(UserPageBuildingEvent $event)
{
global $user, $page, $config;
@ -250,7 +261,7 @@ class UserPage extends Extension
$this->theme->display_user_links($page, $user, $ubbe->parts);
}
if (
($user->can("view_ip") || ($user->is_logged_in() && $user->id == $event->display_user->id)) && # admin or self-user
($user->can(Permissions::VIEW_IP) || ($user->is_logged_in() && $user->id == $event->display_user->id)) && # admin or self-user
($event->display_user->id != $config->get_int('anon_id')) # don't show anon's IP list, it is le huge
) {
$this->theme->display_ip_list(
@ -305,11 +316,21 @@ class UserPage extends Extension
$event->panel->add_block($sb);
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)
{
global $user;
if($event->parent==="system") {
if ($user->can(Permissions::EDIT_USER_CLASS)) {
$event->add_nav_link("user_admin", new Link('user_admin/list'), "User List", NavLink::is_active(["user_admin"]));
}
}
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event)
{
global $user;
$event->add_link("My Profile", make_link("user"));
if ($user->can("edit_user_class")) {
if ($user->can(Permissions::EDIT_USER_CLASS)) {
$event->add_link("User List", make_link("user_admin/list"), 98);
}
$event->add_link("Log Out", make_link("user_admin/logout"), 99);
@ -337,12 +358,23 @@ class UserPage extends Extension
} elseif (preg_match("/^(?:poster|user)_id[=|:]([0-9]+)$/i", $event->term, $matches)) {
$user_id = int_escape($matches[1]);
$event->add_querylet(new Querylet("images.owner_id = $user_id"));
} elseif ($user->can("view_ip") && preg_match("/^(?:poster|user)_ip[=|:]([0-9\.]+)$/i", $event->term, $matches)) {
} elseif ($user->can(Permissions::VIEW_IP) && preg_match("/^(?:poster|user)_ip[=|:]([0-9\.]+)$/i", $event->term, $matches)) {
$user_ip = $matches[1]; // FIXME: ip_escape?
$event->add_querylet(new Querylet("images.owner_ip = '$user_ip'"));
}
}
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if($event->key===HelpPages::SEARCH) {
$block = new Block();
$block->header = "Users";
$block->body = $this->theme->get_help_html();
$event->add_block($block);
}
}
private function show_user_info()
{
global $user, $page;
@ -517,8 +549,8 @@ class UserPage extends Extension
if (
($a->name == $b->name) ||
($b->can("protected") && $a->class->name == "admin") ||
(!$b->can("protected") && $a->can("edit_user_info"))
($b->can(Permissions::PROTECTED) && $a->class->name == "admin") ||
(!$b->can(Permissions::PROTECTED) && $a->can(Permissions::EDIT_USER_INFO))
) {
return true;
} else {
@ -544,7 +576,7 @@ class UserPage extends Extension
{
global $user;
if ($user->can('edit_user_name') && $this->user_can_edit_user($user, $duser)) {
if ($user->can(Permissions::EDIT_USER_NAME) && $this->user_can_edit_user($user, $duser)) {
$duser->set_name($name);
flash_message("Username changed");
// TODO: set login cookie if user changed themselves
@ -652,7 +684,7 @@ class UserPage extends Extension
$page->set_heading("Error");
$page->add_block(new NavBlock());
if (!$user->can("delete_user")) {
if (!$user->can(Permissions::DELETE_USER)) {
$page->add_block(new Block("Not Admin", "Only admins can delete accounts"));
} elseif (!isset($_POST['id']) || !is_numeric($_POST['id'])) {
$page->add_block(new Block(

View File

@ -26,7 +26,7 @@ class UserPageTheme extends Themelet
$html .= "<tr>";
$html .= "<td>Name</td>";
if ($user->can('delete_user')) {
if ($user->can(Permissions::DELETE_USER)) {
$html .= "<td>Email</td>";
}
$html .= "<td>Class</td>";
@ -39,7 +39,7 @@ class UserPageTheme extends Themelet
$html .= "<tr>" . make_form("user_admin/list", "GET");
$html .= "<td><input type='text' name='username' value='$h_username'/></td>";
if ($user->can('delete_user')) {
if ($user->can(Permissions::DELETE_USER)) {
$html .= "<td><input type='text' name='email' value='$h_email'/></td>";
}
$html .= "<td><input type='text' name='class' value='$h_class'/></td>";
@ -55,7 +55,7 @@ class UserPageTheme extends Themelet
$html .= "<tr>";
$html .= "<td><a href='$u_link'>$h_name</a></td>";
if ($user->can('delete_user')) {
if ($user->can(Permissions::DELETE_USER)) {
$html .= "<td>$h_email</td>";
}
$html .= "<td>$h_class</td>";
@ -256,7 +256,7 @@ class UserPageTheme extends Themelet
$html = "";
if ($duser->id != $config->get_int('anon_id')) { //justa fool-admin protection so they dont mess around with anon users.
if ($user->can('edit_user_name')) {
if ($user->can(Permissions::EDIT_USER_NAME)) {
$html .= "
<p>".make_form(make_link("user_admin/change_name"))."
<input type='hidden' name='id' value='{$duser->id}'>
@ -298,7 +298,7 @@ class UserPageTheme extends Themelet
$i_user_id = int_escape($duser->id);
if ($user->can("edit_user_class")) {
if ($user->can(Permissions::EDIT_USER_CLASS)) {
global $_shm_user_classes;
$class_html = "";
foreach ($_shm_user_classes as $name => $values) {
@ -319,7 +319,7 @@ class UserPageTheme extends Themelet
";
}
if ($user->can("delete_user")) {
if ($user->can(Permissions::DELETE_USER)) {
$html .= "
<p>".make_form(make_link("user_admin/delete_user"))."
<input type='hidden' name='id' value='$i_user_id'>
@ -343,4 +343,30 @@ class UserPageTheme extends Themelet
return $html;
}
// }}}
public function get_help_html()
{
global $user;
$output = '<p>Search for images posted by particular individuals.</p>
<div class="command_example">
<pre>poster=username</pre>
<p>Returns images posted by "username".</p>
</div>
<div class="command_example">
<pre>poster_id=123</pre>
<p>Returns images posted by user 123.</p>
</div>
';
if ($user->can(Permissions::VIEW_IP)) {
$output .="
<div class=\"command_example\">
<pre>poster_ip=127.0.0.1</pre>
<p>Returns images posted from IP 127.0.0.1.</p>
</div>
";
}
return $output;
}
}

View File

@ -0,0 +1,23 @@
<?php
class DisplayingImageEvent extends Event
{
/** @var Image */
public $image;
public $title;
public function __construct(Image $image)
{
$this->image = $image;
}
public function get_image(): Image
{
return $this->image;
}
public function set_title(String $title) {
$this->title = $title;
}
}

View File

@ -0,0 +1,25 @@
<?php
class ImageAdminBlockBuildingEvent extends Event
{
/** @var string[] */
public $parts = [];
/** @var ?Image */
public $image = null;
/** @var ?User */
public $user = null;
public function __construct(Image $image, User $user)
{
$this->image = $image;
$this->user = $user;
}
public function add_part(string $html, int $position=50)
{
while (isset($this->parts[$position])) {
$position++;
}
$this->parts[$position] = $html;
}
}

View File

@ -0,0 +1,25 @@
<?php
class ImageInfoBoxBuildingEvent extends Event
{
/** @var array */
public $parts = [];
/** @var Image */
public $image;
/** @var User */
public $user;
public function __construct(Image $image, User $user)
{
$this->image = $image;
$this->user = $user;
}
public function add_part(string $html, int $position=50)
{
while (isset($this->parts[$position])) {
$position++;
}
$this->parts[$position] = $html;
}
}

Some files were not shown because too many files have changed in this diff Show More