missed a word

This commit is contained in:
Shish 2012-02-09 10:51:24 +00:00
commit 1c89632ab2
93 changed files with 1314 additions and 4539 deletions

6
.gitignore vendored
View File

@ -1,8 +1,10 @@
.svn .svn
backup
config.php config.php
images
thumbs
data data
images
imgdump-*.zip
thumbs
sql.log sql.log
shimmie.log shimmie.log
!lib/images !lib/images

View File

@ -30,13 +30,13 @@
*/ */
class AdminBuildingEvent extends Event { class AdminBuildingEvent extends Event {
var $page; var $page;
public function AdminBuildingEvent($page) { public function AdminBuildingEvent(Page $page) {
$this->page = $page; $this->page = $page;
} }
} }
class AdminPage extends SimpleExtension { class AdminPage extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;
if($event->page_matches("admin")) { if($event->page_matches("admin")) {
@ -78,6 +78,13 @@ class AdminPage extends SimpleExtension {
case 'database dump': case 'database dump':
$this->dbdump($page); $this->dbdump($page);
break; break;
case 'reset image ids':
$this->reset_imageids();
$redirect = true;
break;
case 'image dump':
$this->imgdump($page);
break;
} }
if($redirect) { if($redirect) {
@ -88,20 +95,20 @@ class AdminPage extends SimpleExtension {
} }
} }
public function onAdminBuilding($event) { public function onAdminBuilding(AdminBuildingEvent $event) {
global $page; global $page;
$this->theme->display_page($page); $this->theme->display_page($page);
$this->theme->display_form($page); $this->theme->display_form($page);
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_link("Board Admin", make_link("admin")); $event->add_link("Board Admin", make_link("admin"));
} }
} }
private function delete_by_query($query) { private function delete_by_query(/*array(string)*/ $query) {
global $page, $user; global $page, $user;
assert(strlen($query) > 1); assert(strlen($query) > 1);
foreach(Image::find_images(0, 1000000, Tag::explode($query)) as $image) { foreach(Image::find_images(0, 1000000, Tag::explode($query)) as $image) {
@ -175,5 +182,67 @@ class AdminPage extends SimpleExtension {
} }
} }
*/ */
private function reset_imageids() {
global $database;
//This might be a bit laggy on boards with lots of images (?)
//Seems to work fine with 1.2k~ images though.
$i = 0;
$image = $database->get_all("SELECT * FROM images ORDER BY images.id ASC");
/*$score_log = $database->get_all("SELECT message FROM score_log");*/
foreach($image as $img){
$xid = $img[0];
$i = $i + 1;
$table = array( //Might be missing some tables?
"image_tags", "tag_histories", "image_reports", "comments", "user_favorites", "tag_histories",
"numeric_score_votes", "pool_images", "slext_progress_cache", "notes");
$sql =
"SET FOREIGN_KEY_CHECKS=0;
UPDATE images
SET id=".$i.
" WHERE id=".$xid.";"; //id for images
foreach($table as $tbl){
$sql .= "
UPDATE ".$tbl."
SET image_id=".$i."
WHERE image_id=".$xid.";";
}
/*foreach($score_log as $sl){
//This seems like a bad idea.
//TODO: Might be better for log_info to have an $id option (which would then affix the id to the table?)
preg_replace(".Image \\#[0-9]+.", "Image #".$i, $sl);
}*/
$sql .= " SET FOREIGN_KEY_CHECKS=1;";
$database->execute($sql);
}
$count = (count($image)) + 1;
$database->execute("ALTER TABLE images AUTO_INCREMENT=".$count);
}
private function imgdump($page) {
global $database;
$zip = new ZipArchive;
$images = $database->get_all("SELECT * FROM images");
$filename = 'imgdump-'.date('Ymd').'.zip';
if($zip->open($filename, 1 ? ZIPARCHIVE::OVERWRITE:ZIPARCHIVE::CREATE)===TRUE){
foreach($images as $img){
$hash = $img["hash"];
preg_match("^[A-Za-z0-9]{2}^", $hash, $matches);
$img_loc = "images/".$matches[0]."/".$hash;
if(file_exists($img_loc)){
$zip->addFile($img_loc, $hash.".".$img["ext"]);
}
}
$zip->close();
}
$page->set_mode("redirect");
$page->set_redirect(make_link($filename)); //Fairly sure there is better way to do this..
//TODO: Delete file after downloaded?
}
} }
?> ?>

View File

@ -19,13 +19,26 @@ class AdminPageTheme extends Themelet {
public function display_form(Page $page) { public function display_form(Page $page) {
global $user; global $user;
$html = " $html = '
".make_form(make_link("admin_utils"))." <script type="text/javascript">
<select name='action'> function imgidconfirm(){
if(document.getElementById("misc").selectedIndex == 4){
if(confirm("This function WILL break any bookmarks & links.\n The event log will also not be updated with new ids. \n Are you sure you wish to continue?")){
return true;
}else{
return false;
}
}
}
</script>
'.make_form(make_link("admin_utils"),"post", false, false, "return imgidconfirm()")."
<select name='action' id='misc'>
<option value='lowercase all tags'>All tags to lowercase</option> <option value='lowercase all tags'>All tags to lowercase</option>
<option value='recount tag use'>Recount tag use</option> <option value='recount tag use'>Recount tag use</option>
<option value='purge unused tags'>Purge unused tags</option> <option value='purge unused tags'>Purge unused tags</option>
<option value='database dump'>Download database contents</option> <option value='database dump'>Download database contents</option>
<option value='reset image ids'>Reset image ids</option>
<option value='image dump'>Download all images</option>
<!--<option value='convert to innodb'>Convert database to InnoDB (MySQL only)</option>--> <!--<option value='convert to innodb'>Convert database to InnoDB (MySQL only)</option>-->
</select> </select>
<input type='submit' value='Go'> <input type='submit' value='Go'>

View File

@ -9,7 +9,7 @@
require_once "lib/S3.php"; require_once "lib/S3.php";
class UploadS3 extends SimpleExtension { class UploadS3 extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_string("amazon_s3_access", ""); $config->set_default_string("amazon_s3_access", "");

View File

@ -11,7 +11,7 @@
class AuthorSetEvent extends Event { class AuthorSetEvent extends Event {
var $image, $user, $author; var $image, $user, $author;
public function AuthorSetEvent(Image $image, User $user, $author) public function AuthorSetEvent(Image $image, User $user, /*string*/ $author)
{ {
$this->image = $image; $this->image = $image;
$this->user = $user; $this->user = $user;
@ -19,41 +19,37 @@ class AuthorSetEvent extends Event {
} }
} }
class Artists implements Extension { class Artists extends Extension {
var $theme; public function onImageInfoSet(ImageInfoSetEvent $event) {
public function get_priority() {return 50;}
public function receive_event(Event $event)
{
global $user; global $user;
if (isset($_POST["tag_edit__author"])) {
if(is_null($this->theme)) $this->theme = get_theme_object($this); send_event(new AuthorSetEvent($event->image, $user, $_POST["tag_edit__author"]));
if ($event instanceof ImageInfoSetEvent)
if (isset($_POST["tag_edit__author"]))
send_event(new AuthorSetEvent($event->image, $user, $_POST["tag_edit__author"]));
if ($event instanceof AuthorSetEvent)
$this->update_author($event);
if($event instanceof InitExtEvent)
$this->try_install();
if ($event instanceof ImageInfoBoxBuildingEvent)
$this->add_author_field_to_image($event);
if ($event instanceof PageRequestEvent)
$this->handle_commands($event);
if ($event instanceof SearchTermParseEvent) {
$matches = array();
if(preg_match("/^author=(.*)$/", $event->term, $matches)) {
$char = $matches[1];
$event->add_querylet(new Querylet("Author = :author_char", array("author_char"=>$char)));
}
} }
} }
public function onAuthorSet(AuthorSetEvent $event) {
$this->update_author($event);
}
public function onInitExt(InitExtEvent $event) {
$this->try_install();
}
public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) {
$this->add_author_field_to_image($event);
}
public function onPageRequest(PageRequestEvent $event) {
$this->handle_commands($event);
}
public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array();
if(preg_match("/^author=(.*)$/", $event->term, $matches)) {
$char = $matches[1];
$event->add_querylet(new Querylet("Author = :author_char", array("author_char"=>$char)));
}
}
public function try_install() { public function try_install() {
global $config, $database; global $config, $database;

View File

@ -2,6 +2,7 @@
/* /*
* Name: Comment Word Ban * Name: Comment Word Ban
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: For stopping spam and other comment abuse * Description: For stopping spam and other comment abuse
* Documentation: * Documentation:
@ -19,7 +20,7 @@
* from Essex" * from Essex"
*/ */
class BanWords extends SimpleExtension { class BanWords extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_string('banned_words', " $config->set_default_string('banned_words', "

View File

@ -27,8 +27,8 @@
* </pre> * </pre>
*/ */
class Blocks extends SimpleExtension { class Blocks extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $page; global $config, $page;
$all = $config->get_string("blocks_text"); $all = $config->get_string("blocks_text");
$blocks = explode("----", $all); $blocks = explode("----", $all);
@ -70,7 +70,7 @@ class Blocks extends SimpleExtension {
} }
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Blocks"); $sb = new SetupBlock("Blocks");
$sb->add_label("See <a href='".make_link("ext_doc/blocks")."'>the docs</a> for formatting"); $sb->add_label("See <a href='".make_link("ext_doc/blocks")."'>the docs</a> for formatting");
$sb->add_longtext_option("blocks_text"); $sb->add_longtext_option("blocks_text");

View File

@ -8,8 +8,8 @@
* *
* Development TODO at http://github.com/zshall/shimmie2/issues * Development TODO at http://github.com/zshall/shimmie2/issues
*/ */
class Blotter extends SimpleExtension { class Blotter extends Extension {
public function onInitExt(Event $event) { public function onInitExt(InitExtEvent $event) {
/** /**
* I love re-using this installer don't I... * I love re-using this installer don't I...
*/ */
@ -43,7 +43,7 @@ class Blotter extends SimpleExtension {
$config->set_default_string("blotter_position", "subheading"); $config->set_default_string("blotter_position", "subheading");
} }
public function onSetupBuilding(Event $event) { public function onSetupBuilding(SetupBuildingEvent $event) {
global $config; global $config;
$sb = new SetupBlock("Blotter"); $sb = new SetupBlock("Blotter");
$sb->add_int_option("blotter_recent", "<br />Number of recent entries to display: "); $sb->add_int_option("blotter_recent", "<br />Number of recent entries to display: ");
@ -51,13 +51,13 @@ class Blotter extends SimpleExtension {
$sb->add_choice_option("blotter_position", array("Top of page" => "subheading", "In navigation bar" => "left"), "<br>Position: "); $sb->add_choice_option("blotter_position", array("Top of page" => "subheading", "In navigation bar" => "left"), "<br>Position: ");
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onUserBlockBuilding(Event $event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_link("Blotter Editor", make_link("blotter/editor")); $event->add_link("Blotter Editor", make_link("blotter/editor"));
} }
} }
public function onPageRequest(Event $event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $database, $user; global $page, $database, $user;
if($event->page_matches("blotter")) { if($event->page_matches("blotter")) {
switch($event->get_arg(0)) { switch($event->get_arg(0)) {

View File

@ -6,16 +6,15 @@
* Description: Allow users to bookmark searches * Description: Allow users to bookmark searches
*/ */
class Bookmarks implements Extension { class Bookmarks extends Extension {
var $theme; public function onInitExt(InitExtEvent $event) {
$this->install();
}
public function get_priority() {return 50;} public function onPageRequest(PageRequestEvent $event) {
global $page;
public function receive_event(Event $event) { if($event->page_matches("bookmark")) {
global $config, $database, $page, $user;
if(is_null($this->theme)) $this->theme = get_theme_object($this);
if(($event instanceof PageRequestEvent) && $event->page_matches("bookmark")) {
if($event->get_arg(0) == "add") { if($event->get_arg(0) == "add") {
if(isset($_POST['url'])) { if(isset($_POST['url'])) {
$page->set_mode("redirect"); $page->set_mode("redirect");

View File

@ -13,36 +13,29 @@
* engine" notification they have * engine" notification they have
*/ */
class BrowserSearch implements Extension { class BrowserSearch extends Extension {
public function onInitExt(InitExtEvent $event) {
global $config;
$config->set_default_string("search_suggestions_results_order", 'a');
}
public function get_priority() {return 50;} public function onPageRequest(PageRequestEvent $event) {
public function receive_event(Event $event) { global $config, $database, $page;
global $page;
global $config;
if($event instanceof InitExtEvent) {
$config->set_default_string("search_suggestions_results_order", 'a');
}
// Add in header code to let the browser know that the search plugin exists // Add in header code to let the browser know that the search plugin exists
if($event instanceof PageRequestEvent) { // We need to build the data for the header
// We need to build the data for the header $search_title = $config->get_string('title');
global $config; $search_file_url = make_link('browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml');
$search_title = $config->get_string('title'); $page->add_html_header("<link rel='search' type='application/opensearchdescription+xml' title='$search_title' href='$search_file_url'>");
$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 // The search.xml file that is generated on the fly
if(($event instanceof PageRequestEvent) && $event->page_matches("browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml")) { 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 // First, we need to build all the variables we'll need
$search_title = $config->get_string('title'); $search_title = $config->get_string('title');
$search_form_url = make_link('post/list/{searchTerms}'); $search_form_url = make_link('post/list/{searchTerms}');
$suggenton_url = make_link('browser_search/')."{searchTerms}"; $suggenton_url = make_link('browser_search/')."{searchTerms}";
$icon_b64 = base64_encode(file_get_contents("favicon.ico")); $icon_b64 = base64_encode(file_get_contents("favicon.ico"));
// Now for the XML // Now for the XML
$xml = " $xml = "
<SearchPlugin xmlns='http://www.mozilla.org/2006/browser/search/' xmlns:os='http://a9.com/-/spec/opensearch/1.1/'> <SearchPlugin xmlns='http://www.mozilla.org/2006/browser/search/' xmlns:os='http://a9.com/-/spec/opensearch/1.1/'>
@ -63,12 +56,10 @@ class BrowserSearch implements Extension {
$page->set_data($xml); $page->set_data($xml);
} }
else if(($event instanceof PageRequestEvent) && ( else if(
$event->page_matches("browser_search") && $event->page_matches("browser_search") &&
!$config->get_bool("disable_search_suggestions") !$config->get_bool("disable_search_suggestions")
)) { ) {
global $database;
// We have to build some json stuff // We have to build some json stuff
$tag_search = $event->get_arg(0); $tag_search = $event->get_arg(0);
@ -89,29 +80,25 @@ class BrowserSearch implements Extension {
array_push($tags_array,$tag['tag']); array_push($tags_array,$tag['tag']);
} }
$json_tag_list .= implode("\",\"", $tags_array); $json_tag_list .= implode("\",\"", $tags_array);
// $json_tag_list = implode($tags_array,", ");
// $json_tag_list = "\"".implode($tags_array,"\", \"")."\"";
// And now for the final output // And now for the final output
$json_string = "[\"$tag_search\",[\"$json_tag_list\"],[],[]]"; $json_string = "[\"$tag_search\",[\"$json_tag_list\"],[],[]]";
$page->set_mode("data"); $page->set_mode("data");
$page->set_data($json_string); $page->set_data($json_string);
} }
}
if($event instanceof SetupBuildingEvent) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sort_by = array(); $sort_by = array();
$sort_by['Alphabetical'] = 'a'; $sort_by['Alphabetical'] = 'a';
$sort_by['Tag Count'] = 't'; $sort_by['Tag Count'] = 't';
$sb = new SetupBlock("Browser Search"); $sb = new SetupBlock("Browser Search");
$sb->add_bool_option("disable_search_suggestions", "Disable search suggestions: "); $sb->add_bool_option("disable_search_suggestions", "Disable search suggestions: ");
$sb->add_label("<br>"); $sb->add_label("<br>");
$sb->add_choice_option("search_suggestions_results_order", $sort_by, "Sort the suggestions by:"); $sb->add_choice_option("search_suggestions_results_order", $sort_by, "Sort the suggestions by:");
$event->panel->add_block($sb); $event->panel->add_block($sb);
}
} }
} }
?> ?>

View File

@ -2,6 +2,7 @@
/* /*
* Name: Bulk Add * Name: Bulk Add
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: Bulk add server-side images * Description: Bulk add server-side images
* Documentation: * Documentation:
@ -14,8 +15,8 @@
* <p><b>Note:</b> requires the "admin" extension to be enabled * <p><b>Note:</b> requires the "admin" extension to be enabled
*/ */
class BulkAdd extends SimpleExtension { class BulkAdd extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;
if($event->page_matches("bulk_add")) { if($event->page_matches("bulk_add")) {
if($user->is_admin() && $user->check_auth_token() && isset($_POST['dir'])) { if($user->is_admin() && $user->check_auth_token() && isset($_POST['dir'])) {
@ -26,11 +27,13 @@ class BulkAdd extends SimpleExtension {
} }
} }
public function onAdminBuilding($event) { public function onAdminBuilding(AdminBuildingEvent $event) {
$this->theme->display_admin_block(); $this->theme->display_admin_block();
} }
/**
* Generate the necessary DataUploadEvent for a given image and tags.
*/
private function add_image($tmpname, $filename, $tags) { private function add_image($tmpname, $filename, $tags) {
assert(file_exists($tmpname)); assert(file_exists($tmpname));

View File

@ -47,33 +47,23 @@ Completely compatibility will probably involve a rewrite with a different URL
*/ */
class DanbooruApi implements Extension class DanbooruApi extends Extension {
{ public function onPageRequest(PageRequestEvent $event) {
if($event->page_matches("api") && ($event->get_arg(0) == 'danbooru')) {
public function get_priority() {return 50;}
// Receive the event
public function receive_event(Event $event)
{
// Check if someone is accessing /api/danbooru (us)
if(($event instanceof PageRequestEvent) && ($event->page_matches("api")) && ($event->get_arg(0) == 'danbooru'))
{
// execute the danbooru processing code
$this->api_danbooru($event); $this->api_danbooru($event);
} }
if($event instanceof SearchTermParseEvent) }
{
$matches = array(); public function onSearchTermParse(SearchTermParseEvent $event) {
if(preg_match("/^md5:([0-9a-fA-F]*)$/i", $event->term, $matches)) $matches = array();
{ if(preg_match("/^md5:([0-9a-fA-F]*)$/i", $event->term, $matches)) {
$hash = strtolower($matches[1]); $hash = strtolower($matches[1]);
$event->add_querylet(new Querylet("images.hash = '$hash'")); // :-O $event->add_querylet(new Querylet("images.hash = '$hash'")); // :-O
// $event->set_querylet(new Querylet("images.hash = '$hash'"));
}
} }
} }
// Danbooru API // Danbooru API
private function api_danbooru($event) private function api_danbooru(PageRequestEvent $event)
{ {
global $page; global $page;
global $config; global $config;

View File

@ -11,7 +11,7 @@
* message specified in the box. * message specified in the box.
*/ */
class Downtime extends SimpleExtension { class Downtime extends Extension {
public function get_priority() {return 10;} public function get_priority() {return 10;}
public function onSetupBuilding($event) { public function onSetupBuilding($event) {

View File

@ -13,19 +13,19 @@
*/ */
class Emoticons extends FormatterExtension { class Emoticons extends FormatterExtension {
public function format($text) { public function format(/*string*/ $text) {
$data_href = get_base_href(); $data_href = get_base_href();
$text = preg_replace("/:([a-z]*?):/s", "<img src='$data_href/ext/emoticons/default/\\1.gif'>", $text); $text = preg_replace("/:([a-z]*?):/s", "<img src='$data_href/ext/emoticons/default/\\1.gif'>", $text);
return $text; return $text;
} }
public function strip($text) { public function strip(/*string*/ $text) {
return $text; return $text;
} }
} }
class EmoticonList extends SimpleExtension { class EmoticonList extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
if($event->page_matches("emote/list")) { if($event->page_matches("emote/list")) {
$this->theme->display_emotes(glob("ext/emoticons/default/*")); $this->theme->display_emotes(glob("ext/emoticons/default/*"));
} }

View File

@ -12,8 +12,8 @@
* versions of PHP I should test with, etc. * versions of PHP I should test with, etc.
*/ */
class ET extends SimpleExtension { class ET extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $user; global $user;
if($event->page_matches("system_info")) { if($event->page_matches("system_info")) {
if($user->is_admin()) { if($user->is_admin()) {
@ -22,13 +22,16 @@ class ET extends SimpleExtension {
} }
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_link("System Info", make_link("system_info")); $event->add_link("System Info", make_link("system_info"));
} }
} }
/**
* Collect the information and return it in a keyed array.
*/
private function get_info() { private function get_info() {
global $config, $database; global $config, $database;
global $_event_listeners; // yay for using secret globals \o/ global $_event_listeners; // yay for using secret globals \o/
@ -46,9 +49,6 @@ class ET extends SimpleExtension {
$info['sys_disk'] = to_shorthand_int(disk_total_space("./") - disk_free_space("./")) . " / " . $info['sys_disk'] = to_shorthand_int(disk_total_space("./") - disk_free_space("./")) . " / " .
to_shorthand_int(disk_total_space("./")); to_shorthand_int(disk_total_space("./"));
$info['sys_server'] = $_SERVER["SERVER_SOFTWARE"]; $info['sys_server'] = $_SERVER["SERVER_SOFTWARE"];
$proto = preg_replace("#(.*)://.*#", "$1", DATABASE_DSN);
#$db = $database->db->ServerInfo();
#$info['sys_db'] = "$proto / {$db['version']}";
$info['stat_images'] = $database->get_one("SELECT COUNT(*) FROM images"); $info['stat_images'] = $database->get_one("SELECT COUNT(*) FROM images");
$info['stat_comments'] = $database->get_one("SELECT COUNT(*) FROM comments"); $info['stat_comments'] = $database->get_one("SELECT COUNT(*) FROM comments");

View File

@ -16,7 +16,7 @@
class FavoriteSetEvent extends Event { class FavoriteSetEvent extends Event {
var $image_id, $user, $do_set; var $image_id, $user, $do_set;
public function FavoriteSetEvent($image_id, User $user, $do_set) { public function FavoriteSetEvent(/*int*/ $image_id, User $user, /*boolean*/ $do_set) {
assert(is_numeric($image_id)); assert(is_numeric($image_id));
assert(is_bool($do_set)); assert(is_bool($do_set));
@ -26,15 +26,15 @@ class FavoriteSetEvent extends Event {
} }
} }
class Favorites extends SimpleExtension { class Favorites extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
if($config->get_int("ext_favorites_version", 0) < 1) { if($config->get_int("ext_favorites_version", 0) < 1) {
$this->install(); $this->install();
} }
} }
public function onImageAdminBlockBuilding($event) { public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) {
global $database, $page, $user; global $database, $page, $user;
if(!$user->is_anonymous()) { if(!$user->is_anonymous()) {
$user_id = $user->id; $user_id = $user->id;
@ -48,14 +48,14 @@ class Favorites extends SimpleExtension {
} }
} }
public function onDisplayingImage($event) { public function onDisplayingImage(DisplayingImageEvent $event) {
$people = $this->list_persons_who_have_favorited($event->image); $people = $this->list_persons_who_have_favorited($event->image);
if(count($people) > 0) { if(count($people) > 0) {
$html = $this->theme->display_people($people); $html = $this->theme->display_people($people);
} }
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;
if($event->page_matches("change_favorite") && !$user->is_anonymous() && $user->check_auth_token()) { if($event->page_matches("change_favorite") && !$user->is_anonymous() && $user->check_auth_token()) {
$image_id = int_escape($_POST['image_id']); $image_id = int_escape($_POST['image_id']);
@ -67,7 +67,7 @@ class Favorites extends SimpleExtension {
} }
} }
public function onUserPageBuilding($event) { public function onUserPageBuilding(UserPageBuildingEvent $event) {
$i_favorites_count = Image::count_images(array("favorited_by={$event->display_user->name}")); $i_favorites_count = Image::count_images(array("favorited_by={$event->display_user->name}"));
$i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1;
$h_favorites_rate = sprintf("%.1f", ($i_favorites_count / $i_days_old)); $h_favorites_rate = sprintf("%.1f", ($i_favorites_count / $i_days_old));
@ -75,7 +75,7 @@ class Favorites extends SimpleExtension {
$event->add_stats("<a href='$favorites_link'>Images favorited</a>: $i_favorites_count, $h_favorites_rate per day"); $event->add_stats("<a href='$favorites_link'>Images favorited</a>: $i_favorites_count, $h_favorites_rate per day");
} }
public function onImageInfoSet($event) { public function onImageInfoSet(ImageInfoSetEvent $event) {
global $user; global $user;
if( if(
in_array('favorite_action', $_POST) && in_array('favorite_action', $_POST) &&
@ -85,28 +85,30 @@ class Favorites extends SimpleExtension {
} }
} }
public function onFavoriteSet($event) { public function onFavoriteSet(FavoriteSetEvent $event) {
global $user; global $user;
$this->add_vote($event->image_id, $user->id, $event->do_set); $this->add_vote($event->image_id, $user->id, $event->do_set);
} }
public function onImageDeletion($event) { // FIXME: this should be handled by the foreign key. Check that it
// is, and then remove this
public function onImageDeletion(ImageDeletionEvent $event) {
global $database; global $database;
$database->execute("DELETE FROM user_favorites WHERE image_id=:image_id", array("image_id"=>$event->image->id)); $database->execute("DELETE FROM user_favorites WHERE image_id=:image_id", array("image_id"=>$event->image->id));
} }
public function onParseLinkTemplate($event) { public function onParseLinkTemplate(ParseLinkTemplateEvent $event) {
$event->replace('$favorites', $event->image->favorites); $event->replace('$favorites', $event->image->favorites);
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
$username = url_escape($user->name); $username = url_escape($user->name);
$event->add_link("My Favorites", make_link("post/list/favorited_by=$username/1"), 20); $event->add_link("My Favorites", make_link("post/list/favorited_by=$username/1"), 20);
} }
public function onSearchTermParse($event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/favorites(<|>|<=|>=|=)(\d+)/", $event->term, $matches)) { if(preg_match("/favorites(<|>|<=|>=|=)(\d+)/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = $matches[1];
@ -152,6 +154,17 @@ class Favorites extends SimpleExtension {
"); ");
$config->set_int("ext_favorites_version", 1); $config->set_int("ext_favorites_version", 1);
} }
if($config->get_int("ext_favorites_version") < 2) {
log_info("favorites", "Cleaning user favourites");
$database->Execute("DELETE FROM user_favorites WHERE user_id NOT IN (SELECT id FROM users)");
$database->Execute("DELETE FROM user_favorites WHERE image_id NOT IN (SELECT id FROM images)");
log_info("favorites", "Adding foreign keys to user favourites");
$database->Execute("ALTER TABLE user_favorites ADD CONSTRAINT foreign_user_favorites_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;");
$database->Execute("ALTER TABLE user_favorites ADD CONSTRAINT user_favorites_image_id FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE;");
$config->set_int("ext_favorites_version", 2);
}
} }
private function add_vote($image_id, $user_id, $do_set) { private function add_vote($image_id, $user_id, $do_set) {
@ -170,7 +183,7 @@ class Favorites extends SimpleExtension {
array("image_id"=>$image_id, "user_id"=>$user_id)); array("image_id"=>$image_id, "user_id"=>$user_id));
} }
private function list_persons_who_have_favorited($image) { private function list_persons_who_have_favorited(Image $image) {
global $database; global $database;
return $database->get_col( return $database->get_col(

View File

@ -24,6 +24,8 @@ class FavoritesTheme extends Themelet {
$i_favorites = count($username_array); $i_favorites = count($username_array);
$html = "$i_favorites people:"; $html = "$i_favorites people:";
reset($username_array); // rewind to first element in array.
foreach($username_array as $row) { foreach($username_array as $row) {
$username = html_escape($row); $username = html_escape($row);
$html .= "<br><a href='".make_link("user/$username")."'>$username</a>"; $html .= "<br><a href='".make_link("user/$username")."'>$username</a>";

View File

@ -2,6 +2,7 @@
/* /*
* Name: Featured Image * Name: Featured Image
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: Bring a specific image to the users' attentions * Description: Bring a specific image to the users' attentions
* Documentation: * Documentation:
@ -18,13 +19,13 @@
* every couple of hours. * every couple of hours.
*/ */
class Featured extends SimpleExtension { class Featured extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_int('featured_id', 0); $config->set_default_int('featured_id', 0);
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $page, $user; global $config, $page, $user;
if($event->page_matches("featured_image")) { if($event->page_matches("featured_image")) {
if($event->get_arg(0) == "set" && $user->check_auth_token()) { if($event->get_arg(0) == "set" && $user->check_auth_token()) {
@ -54,7 +55,7 @@ class Featured extends SimpleExtension {
} }
} }
public function onPostListBuilding($event) { public function onPostListBuilding(PostListBuildingEvent $event) {
global $config, $database, $page, $user; global $config, $database, $page, $user;
$fid = $config->get_int("featured_id"); $fid = $config->get_int("featured_id");
if($fid > 0) { if($fid > 0) {
@ -74,7 +75,7 @@ class Featured extends SimpleExtension {
} }
} }
public function onImageAdminBlockBuilding($event) { public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_part($this->theme->get_buttons_html($event->image->id)); $event->add_part($this->theme->get_buttons_html($event->image->id));

View File

@ -8,8 +8,8 @@
* Documentation: * Documentation:
*/ */
class Forum extends SimpleExtension { class Forum extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config, $database; global $config, $database;
// shortcut to latest // shortcut to latest
@ -57,7 +57,7 @@ class Forum extends SimpleExtension {
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onUserPageBuilding($event) { public function onUserPageBuilding(UserPageBuildingEvent $event) {
global $page, $user, $database; global $page, $user, $database;
$threads_count = $database->get_one("SELECT COUNT(*) FROM forum_threads WHERE user_id=?", array($event->display_user->id)); $threads_count = $database->get_one("SELECT COUNT(*) FROM forum_threads WHERE user_id=?", array($event->display_user->id));
@ -73,7 +73,7 @@ class Forum extends SimpleExtension {
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;
if($event->page_matches("forum")) { if($event->page_matches("forum")) {

View File

@ -10,13 +10,13 @@
* <br>7-zip: <code>7zr x -o"%d" "%f"</code> * <br>7-zip: <code>7zr x -o"%d" "%f"</code>
*/ */
class ArchiveFileHandler extends SimpleExtension { class ArchiveFileHandler extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_string('archive_extract_command', 'unzip -d "%d" "%f"'); $config->set_default_string('archive_extract_command', 'unzip -d "%d" "%f"');
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Archive Handler Options"); $sb = new SetupBlock("Archive Handler Options");
$sb->add_text_option("archive_tmp_dir", "Temporary folder: "); $sb->add_text_option("archive_tmp_dir", "Temporary folder: ");
$sb->add_text_option("archive_extract_command", "<br>Extraction command: "); $sb->add_text_option("archive_extract_command", "<br>Extraction command: ");
@ -24,7 +24,7 @@ class ArchiveFileHandler extends SimpleExtension {
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onDataUpload($event) { public function onDataUpload(DataUploadEvent $event) {
if($this->supported_ext($event->type)) { if($this->supported_ext($event->type)) {
global $config; global $config;
$tmp = sys_get_temp_dir(); $tmp = sys_get_temp_dir();

View File

@ -2,7 +2,8 @@
/* /*
* Name: Handle Flash * Name: Handle Flash
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Description: Handle Flash files * Link: http://code.shishnet.org/shimmie2/
* Description: Handle Flash files. (No thumbnail is generated for flash files)
*/ */
class FlashFileHandler extends DataHandlerExtension { class FlashFileHandler extends DataHandlerExtension {

View File

@ -5,8 +5,8 @@
* Description: Handle windows icons * Description: Handle windows icons
*/ */
class IcoFileHandler extends SimpleExtension { class IcoFileHandler extends Extension {
public function onDataUpload($event) { public function onDataUpload(DataUploadEvent $event) {
if($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) { if($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) {
$hash = $event->hash; $hash = $event->hash;
$ha = substr($hash, 0, 2); $ha = substr($hash, 0, 2);
@ -22,20 +22,20 @@ class IcoFileHandler extends SimpleExtension {
} }
} }
public function onThumbnailGeneration($event) { public function onThumbnailGeneration(ThumbnailGenerationEvent $event) {
if($this->supported_ext($event->type)) { if($this->supported_ext($event->type)) {
$this->create_thumb($event->hash); $this->create_thumb($event->hash);
} }
} }
public function onDisplayingImage($event) { public function onDisplayingImage(DisplayingImageEvent $event) {
global $page; global $page;
if($this->supported_ext($event->image->ext)) { if($this->supported_ext($event->image->ext)) {
$this->theme->display_image($page, $event->image); $this->theme->display_image($page, $event->image);
} }
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $database, $page; global $config, $database, $page;
if($event->page_matches("get_ico")) { if($event->page_matches("get_ico")) {
$id = int_escape($event->get_arg(0)); $id = int_escape($event->get_arg(0));

View File

@ -2,18 +2,13 @@
/* /*
* Name: Handle SVG * Name: Handle SVG
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Description: Handle SVG files * Link: http://code.shishnet.org/shimmie2/
* Description: Handle SVG files. (No thumbnail is generated for SVG files)
*/ */
class SVGFileHandler implements Extension { class SVGFileHandler extends Extension {
var $theme; public function onDataUpload(DataUploadEvent $event) {
if($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) {
public function get_priority() {return 50;}
public function receive_event(Event $event) {
if(is_null($this->theme)) $this->theme = get_theme_object($this);
if(($event instanceof DataUploadEvent) && $this->supported_ext($event->type) && $this->check_contents($event->tmpname)) {
$hash = $event->hash; $hash = $event->hash;
$ha = substr($hash, 0, 2); $ha = substr($hash, 0, 2);
if(!move_upload_to_archive($event)) return; if(!move_upload_to_archive($event)) return;
@ -26,33 +21,28 @@ class SVGFileHandler implements Extension {
send_event($iae); send_event($iae);
$event->image_id = $iae->image->id; $event->image_id = $iae->image->id;
} }
}
if(($event instanceof ThumbnailGenerationEvent) && $this->supported_ext($event->type)) { public function onThumbnailGeneration(ThumbnailGenerationEvent $event) {
global $config;
if($this->supported_ext($event->type)) {
$hash = $event->hash; $hash = $event->hash;
$ha = substr($hash, 0, 2); $ha = substr($hash, 0, 2);
global $config; copy("ext/handle_svg/thumb.jpg", warehouse_path("thumbs", $hash));
// if($config->get_string("thumb_engine") == "convert") {
// $w = $config->get_int("thumb_width");
// $h = $config->get_int("thumb_height");
// $q = $config->get_int("thumb_quality");
// $mem = $config->get_int("thumb_max_memory") / 1024 / 1024; // IM takes memory in MB
//
// exec("convert images/{$ha}/{$hash}[0] -geometry {$w}x{$h} -quality {$q} jpg:thumbs/{$ha}/{$hash}");
// }
// else {
copy("ext/handle_svg/thumb.jpg", warehouse_path("thumbs", $hash));
// }
} }
}
if(($event instanceof DisplayingImageEvent) && $this->supported_ext($event->image->ext)) { public function onDisplayingImage(DisplayingImageEvent $event) {
global $page; global $page;
if($this->supported_ext($event->image->ext)) {
$this->theme->display_image($page, $event->image); $this->theme->display_image($page, $event->image);
} }
}
if(($event instanceof PageRequestEvent) && $event->page_matches("get_svg")) { public function onPageRequest(PageRequestEvent $event) {
global $config, $database, $page; global $config, $database, $page;
if($event->page_matches("get_svg")) {
$id = int_escape($event->get_arg(0)); $id = int_escape($event->get_arg(0));
$image = Image::by_id($id); $image = Image::by_id($id);
$hash = $image->hash; $hash = $image->hash;

View File

@ -6,20 +6,20 @@
* License: GPLv2 * License: GPLv2
* Description: Use an additional stylesheet on certain holidays. * Description: Use an additional stylesheet on certain holidays.
*/ */
class Holiday extends SimpleExtension { class Holiday extends Extension {
public function onInitExt(Event $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_bool("holiday_aprilfools", false); $config->set_default_bool("holiday_aprilfools", false);
} }
public function onSetupBuilding(Event $event) { public function onSetupBuilding(SetupBuildingEvent $event) {
global $config; global $config;
$sb = new SetupBlock("Holiday Theme"); $sb = new SetupBlock("Holiday Theme");
$sb->add_bool_option("holiday_aprilfools", "Enable April Fools"); $sb->add_bool_option("holiday_aprilfools", "Enable April Fools");
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onPageRequest(Event $event) { public function onPageRequest(PageRequestEvent $event) {
global $config; global $config;
$date = /*date('d/m') == '01/01' ||date('d/m') == '14/02' || */date('d/m') == '01/04'/* || date('d/m') == '24/12' || date('d/m') == '25/12' || date('d/m') == '31/12'*/; $date = /*date('d/m') == '01/01' ||date('d/m') == '14/02' || */date('d/m') == '01/04'/* || date('d/m') == '24/12' || date('d/m') == '25/12' || date('d/m') == '31/12'*/;
if($date){ if($date){

View File

@ -15,7 +15,7 @@
* alongside the default choices. * alongside the default choices.
*/ */
class Home extends SimpleExtension { class Home extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_string("home_links", '[$base/post/list|Posts] $config->set_default_string("home_links", '[$base/post/list|Posts]

View File

@ -29,7 +29,7 @@ class AddImageHashBanEvent extends Event {
} }
} }
// }}} // }}}
class ImageBan extends SimpleExtension { class ImageBan extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config, $database; global $config, $database;
if($config->get_int("ext_imageban_version") < 1) { if($config->get_int("ext_imageban_version") < 1) {

View File

@ -2,6 +2,7 @@
/* /*
* Name: IP Ban * Name: IP Ban
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: Ban IP addresses * Description: Ban IP addresses
* Documentation: * Documentation:
@ -34,10 +35,10 @@ class AddIPBanEvent extends Event {
} }
// }}} // }}}
class IPBan extends SimpleExtension { class IPBan extends Extension {
public function get_priority() {return 10;} public function get_priority() {return 10;}
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
if($config->get_int("ext_ipban_version") < 5) { if($config->get_int("ext_ipban_version") < 5) {
$this->install(); $this->install();
@ -45,7 +46,7 @@ class IPBan extends SimpleExtension {
$this->check_ip_ban(); $this->check_ip_ban();
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
if($event->page_matches("ip_ban")) { if($event->page_matches("ip_ban")) {
global $config, $database, $page, $user; global $config, $database, $page, $user;
if($user->is_admin()) { if($user->is_admin()) {
@ -77,19 +78,19 @@ class IPBan extends SimpleExtension {
} }
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_link("IP Bans", make_link("ip_ban/list")); $event->add_link("IP Bans", make_link("ip_ban/list"));
} }
} }
public function onAddIPBan($event) { public function onAddIPBan(AddIPBanEvent $event) {
global $user; global $user;
$this->add_ip_ban($event->ip, $event->reason, $event->end, $user); $this->add_ip_ban($event->ip, $event->reason, $event->end, $user);
} }
public function onRemoveIPBan($event) { public function onRemoveIPBan(RemoveIPBanEvent $event) {
global $database; global $database;
$database->Execute("DELETE FROM bans WHERE id = :id", array("id"=>$event->id)); $database->Execute("DELETE FROM bans WHERE id = :id", array("id"=>$event->id));
$database->cache->delete("ip_bans_sorted"); $database->cache->delete("ip_bans_sorted");
@ -178,7 +179,7 @@ class IPBan extends SimpleExtension {
} }
} }
private function block($remote) { private function block(/*string*/ $remote) {
global $config, $database; global $config, $database;
$prefix = ($database->engine->name == "sqlite" ? "bans." : ""); $prefix = ($database->engine->name == "sqlite" ? "bans." : "");

View File

@ -4,29 +4,22 @@
* Author: Artanis <artanis.00@gmail.com> * Author: Artanis <artanis.00@gmail.com>
* Description: Show various forms of link to each image, for copy & paste * Description: Show various forms of link to each image, for copy & paste
*/ */
class LinkImage implements Extension { class LinkImage extends Extension {
var $theme; public function onDisplayingImage(DisplayingImageEvent $event) {
global $page;
$this->theme->links_block($page, $this->data($event->image));
}
public function get_priority() {return 50;} public function onSetupBuildingEvent(SetupBuildingEvent $event) {
$sb = new SetupBlock("Link to Image");
$sb->add_text_option("ext_link-img_text-link_format", "Text Link Format: ");
$event->panel->add_block($sb);
}
public function receive_event(Event $event) { public function onInitExtEvent(InitExtEvent $event) {
global $config, $database, $page, $user; global $config;
if(is_null($this->theme)) $this->theme = get_theme_object($this); $config->set_default_string("ext_link-img_text-link_format", '$title - $id ($ext $size $filesize)');
}
if(($event instanceof DisplayingImageEvent)) {
$this->theme->links_block($page, $this->data($event->image));
}
if($event instanceof SetupBuildingEvent) {
$sb = new SetupBlock("Link to Image");
$sb->add_text_option("ext_link-img_text-link_format", "Text Link Format: ");
$event->panel->add_block($sb);
}
if($event instanceof InitExtEvent) {
//just set default if empty.
$config->set_default_string("ext_link-img_text-link_format",
'$title - $id ($ext $size $filesize)');
}
}
private function hostify($str) { private function hostify($str) {
$str = str_replace(" ", "%20", $str); $str = str_replace(" ", "%20", $str);
@ -37,7 +30,8 @@ class LinkImage implements Extension {
return "http://" . $_SERVER["HTTP_HOST"] . $str; return "http://" . $_SERVER["HTTP_HOST"] . $str;
} }
} }
private function data($image) {
private function data(Image $image) {
global $config; global $config;
$text_link = $image->parse_link_template($config->get_string("ext_link-img_text-link_format")); $text_link = $image->parse_link_template($config->get_string("ext_link-img_text-link_format"));

View File

@ -1,13 +1,14 @@
<?php <?php
/* /*
* Name: Logging (Database) * Name: Logging (Database)
* Author: Shish * Author: Shish <webmaster@shishnet.org>
* Description: Keep a record of SCore events * Link: http://code.shishnet.org/shimmie2/
* Description: Keep a record of SCore events (in the database).
* Visibility: admin * Visibility: admin
*/ */
class LogDatabase extends SimpleExtension { class LogDatabase extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $database; global $database;
global $config; global $config;
@ -28,7 +29,7 @@ class LogDatabase extends SimpleExtension {
$config->set_default_int("log_db_priority", SCORE_LOG_INFO); $config->set_default_int("log_db_priority", SCORE_LOG_INFO);
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Logging (Database)"); $sb = new SetupBlock("Logging (Database)");
$sb->add_choice_option("log_db_priority", array( $sb->add_choice_option("log_db_priority", array(
"Debug" => SCORE_LOG_DEBUG, "Debug" => SCORE_LOG_DEBUG,
@ -40,7 +41,7 @@ class LogDatabase extends SimpleExtension {
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $database, $user; global $database, $user;
if($event->page_matches("log/view")) { if($event->page_matches("log/view")) {
if($user->is_admin()) { if($user->is_admin()) {
@ -104,14 +105,14 @@ class LogDatabase extends SimpleExtension {
} }
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_link("Event Log", make_link("log/view")); $event->add_link("Event Log", make_link("log/view"));
} }
} }
public function onLog($event) { public function onLog(LogEvent $event) {
global $config, $database, $user; global $config, $database, $user;
$username = ($user && $user->name) ? $user->name : "null"; $username = ($user && $user->name) ? $user->name : "null";

View File

@ -41,6 +41,8 @@ class LogDatabaseTheme extends Themelet {
</thead> </thead>
<tbody>\n"; <tbody>\n";
$n = 0; $n = 0;
reset($events); // rewind to first element in array.
foreach($events as $event) { foreach($events as $event) {
$oe = ($n++ % 2 == 0) ? "even" : "odd"; $oe = ($n++ % 2 == 0) ? "even" : "odd";
$c = $this->pri_to_col($event['priority']); $c = $this->pri_to_col($event['priority']);

View File

@ -14,8 +14,8 @@
* As of now only compatible with the lite theme. * As of now only compatible with the lite theme.
*/ */
class MassTagger extends SimpleExtension { class MassTagger extends Extension {
public function onPostListBuilding($event) { public function onPostListBuilding(PostListBuildingEvent $event) {
global $config, $page, $user; global $config, $page, $user;
if( !$user->is_admin() ) return; if( !$user->is_admin() ) return;
@ -23,7 +23,7 @@ class MassTagger extends SimpleExtension {
$this->theme->display_mass_tagger( $page, $event, $config ); $this->theme->display_mass_tagger( $page, $event, $config );
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $page, $user; global $config, $page, $user;
if( !$event->page_matches("mass_tagger") ) return; if( !$event->page_matches("mass_tagger") ) return;
if( !$user->is_admin() ) return; if( !$user->is_admin() ) return;

View File

@ -2,21 +2,22 @@
/* /*
* Name: News * Name: News
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: Show a short amount of text in a block on the post list * Description: Show a short amount of text in a block on the post list
* Documentation: * Documentation:
* Any HTML is allowed * Any HTML is allowed
*/ */
class News extends SimpleExtension { class News extends Extension {
public function onPostListBuilding($event) { public function onPostListBuilding(PostListBuildingEvent $event) {
global $config, $page; global $config, $page;
if(strlen($config->get_string("news_text")) > 0) { if(strlen($config->get_string("news_text")) > 0) {
$this->theme->display_news($page, $config->get_string("news_text")); $this->theme->display_news($page, $config->get_string("news_text"));
} }
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("News"); $sb = new SetupBlock("News");
$sb->add_longtext_option("news_text"); $sb->add_longtext_option("news_text");
$event->panel->add_block($sb); $event->panel->add_block($sb);

3408
contrib/notes/jquery.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,8 @@
* Documentation: * Documentation:
*/ */
class Notes extends SimpleExtension { class Notes extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config, $database; global $config, $database;
// shortcut to latest // shortcut to latest
@ -66,9 +66,7 @@ class Notes extends SimpleExtension {
} }
} }
public function onPageRequest(PageRequestEvent $event) {
public function onPageRequest($event) {
global $page, $user; global $page, $user;
if($event->page_matches("note")) { if($event->page_matches("note")) {
@ -179,7 +177,7 @@ class Notes extends SimpleExtension {
/* /*
* HERE WE LOAD THE NOTES IN THE IMAGE * HERE WE LOAD THE NOTES IN THE IMAGE
*/ */
public function onDisplayingImage($event) { public function onDisplayingImage(DisplayingImageEvent $event) {
global $page, $user; global $page, $user;
//display form on image event //display form on image event
@ -191,7 +189,7 @@ class Notes extends SimpleExtension {
/* /*
* HERE WE ADD THE BUTTONS ON SIDEBAR * HERE WE ADD THE BUTTONS ON SIDEBAR
*/ */
public function onImageAdminBlockBuilding($event) { public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) {
global $user; global $user;
if(!$user->is_anonymous()) { if(!$user->is_anonymous()) {
$event->add_part($this->theme->note_button($event->image->id)); $event->add_part($this->theme->note_button($event->image->id));
@ -207,7 +205,7 @@ class Notes extends SimpleExtension {
/* /*
* HERE WE ADD QUERYLETS TO ADD SEARCH SYSTEM * HERE WE ADD QUERYLETS TO ADD SEARCH SYSTEM
*/ */
public function onSearchTermParse($event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/note=(.*)/i", $event->term, $matches)) { if(preg_match("/note=(.*)/i", $event->term, $matches)) {
$notes = int_escape($matches[1]); $notes = int_escape($matches[1]);

View File

@ -2,6 +2,7 @@
/* /*
* Name: Image Scores (Numeric) * Name: Image Scores (Numeric)
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: Allow users to score images * Description: Allow users to score images
* Documentation: * Documentation:
@ -12,226 +13,227 @@
class NumericScoreSetEvent extends Event { class NumericScoreSetEvent extends Event {
var $image_id, $user, $score; var $image_id, $user, $score;
public function NumericScoreSetEvent($image_id, $user, $score) { public function NumericScoreSetEvent(/*int*/ $image_id, User $user, /*int*/ $score) {
$this->image_id = $image_id; $this->image_id = $image_id;
$this->user = $user; $this->user = $user;
$this->score = $score; $this->score = $score;
} }
} }
class NumericScore implements Extension { class NumericScore extends Extension {
var $theme; public function onInitExt(InitExtEvent $event) {
global $config;
public function get_priority() {return 50;} if($config->get_int("ext_numeric_score_version", 0) < 1) {
$this->install();
public function receive_event(Event $event) {
global $config, $database, $page, $user;
if(is_null($this->theme)) $this->theme = get_theme_object($this);
if($event instanceof InitExtEvent) {
if($config->get_int("ext_numeric_score_version", 0) < 1) {
$this->install();
}
} }
}
if($event instanceof DisplayingImageEvent) { public function onDisplayingImage(DisplayingImageEvent $event) {
global $user, $page;
if(!$user->is_anonymous()) {
$html = $this->theme->get_voter_html($event->image);
$page->add_block(new Block("Image Score", $html, "left", 20));
}
}
public function onUserPageBuilding(UserPageBuildingEvent $event) {
global $page;
$html = $this->theme->get_nuller_html($event->display_user);
$page->add_block(new Block("Votes", $html, "main", 60));
}
public function onPageRequest(PageRequestEvent $event) {
global $config, $database, $user, $page;
if($event->page_matches("numeric_score_votes")) {
$image_id = int_escape($event->get_arg(0));
$x = $database->get_all(
"SELECT users.name as username, user_id, score
FROM numeric_score_votes
JOIN users ON numeric_score_votes.user_id=users.id
WHERE image_id=?",
array($image_id));
$html = "<table>";
foreach($x as $vote) {
$html .= "<tr><td>";
$html .= "<a href='/user/{$vote['username']}'>{$vote['username']}</a>";
$html .= "</td><td>";
$html .= $vote['score'];
$html .= "</td></tr>";
}
die($html);
}
if($event->page_matches("numeric_score_vote") && $user->check_auth_token()) {
if(!$user->is_anonymous()) { if(!$user->is_anonymous()) {
$html = $this->theme->get_voter_html($event->image); $image_id = int_escape($_POST['image_id']);
$page->add_block(new Block("Image Score", $html, "left", 20)); $char = $_POST['vote'];
$score = null;
if($char == "up") $score = 1;
else if($char == "null") $score = 0;
else if($char == "down") $score = -1;
if(!is_null($score) && $image_id>0) send_event(new NumericScoreSetEvent($image_id, $user, $score));
$page->set_mode("redirect");
$page->set_redirect(make_link("post/view/$image_id"));
} }
} }
if($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) {
if($event instanceof UserPageBuildingEvent) { if($user->is_admin()) {
$html = $this->theme->get_nuller_html($event->display_user); $image_id = int_escape($_POST['image_id']);
$page->add_block(new Block("Votes", $html, "main", 60)); $database->execute(
"DELETE FROM numeric_score_votes WHERE image_id=?",
array($image_id));
$database->execute(
"UPDATE images SET numeric_score=0 WHERE id=?",
array($image_id));
$page->set_mode("redirect");
$page->set_redirect(make_link("post/view/$image_id"));
}
} }
if($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) {
if($user->is_admin()) {
$user_id = int_escape($_POST['user_id']);
$image_ids = $database->get_col("SELECT image_id FROM numeric_score_votes WHERE user_id=?", array($user_id));
if($event instanceof PageRequestEvent) { $database->execute(
if($event->page_matches("numeric_score_votes")) { "DELETE FROM numeric_score_votes WHERE user_id=? AND image_id IN ?",
$image_id = int_escape($event->get_arg(0)); array($user_id, $image_ids));
$x = $database->get_all( $database->execute(
"SELECT users.name as username, user_id, score "UPDATE images SET numeric_score=(SELECT SUM(score) FROM numeric_score_votes WHERE image_id=images.id) WHERE images.id IN ?",
FROM numeric_score_votes array($image_ids));
JOIN users ON numeric_score_votes.user_id=users.id $page->set_mode("redirect");
WHERE image_id=?", $page->set_redirect(make_link());
array($image_id));
$html = "<table>";
foreach($x as $vote) {
$html .= "<tr><td>";
$html .= "<a href='/user/{$vote['username']}'>{$vote['username']}</a>";
$html .= "</td><td>";
$html .= $vote['score'];
$html .= "</td></tr>";
}
die($html);
} }
if($event->page_matches("numeric_score_vote") && $user->check_auth_token()) { }
if(!$user->is_anonymous()) { if($event->page_matches("popular_by_day") || $event->page_matches("popular_by_month") || $event->page_matches("popular_by_year")) {
$image_id = int_escape($_POST['image_id']); $t_images = $config->get_int("index_height") * $config->get_int("index_width");
$char = $_POST['vote'];
$score = null; //TODO: Add Popular_by_week.
if($char == "up") $score = 1;
else if($char == "null") $score = 0; //year
else if($char == "down") $score = -1; if(empty($_GET['year'])){
if(!is_null($score) && $image_id>0) send_event(new NumericScoreSetEvent($image_id, $user, $score)); $year = date("Y");
$page->set_mode("redirect"); }else{
$page->set_redirect(make_link("post/view/$image_id")); $year = $_GET['year'];
}
} }
if($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) { //month
if($user->is_admin()) { if(empty($_GET['month']) || int_escape($_GET['month']) > 12){
$image_id = int_escape($_POST['image_id']); $month = date("m");
$database->execute( }else{
"DELETE FROM numeric_score_votes WHERE image_id=?", $month = $_GET['month'];
array($image_id));
$database->execute(
"UPDATE images SET numeric_score=0 WHERE id=?",
array($image_id));
$page->set_mode("redirect");
$page->set_redirect(make_link("post/view/$image_id"));
}
} }
if($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) { //day
if($user->is_admin()) { if(empty($_GET['day']) || int_escape($_GET['day']) > 31){
$user_id = int_escape($_POST['user_id']); $day = date("d");
$image_ids = $database->get_col("SELECT image_id FROM numeric_score_votes WHERE user_id=?", array($user_id)); }else{
$day = $_GET['day'];
$database->execute(
"DELETE FROM numeric_score_votes WHERE user_id=? AND image_id IN ?",
array($user_id, $image_ids));
$database->execute(
"UPDATE images SET numeric_score=(SELECT SUM(score) FROM numeric_score_votes WHERE image_id=images.id) WHERE images.id IN ?",
array($image_ids));
$page->set_mode("redirect");
$page->set_redirect(make_link());
}
} }
if($event->page_matches("popular_by_day") || $event->page_matches("popular_by_month") || $event->page_matches("popular_by_year")) { $totaldate = $year."/".$month."/".$day;
$t_images = $config->get_int("index_height") * $config->get_int("index_width");
//TODO: Add Popular_by_week. $sql =
"SELECT * FROM images
WHERE EXTRACT(YEAR FROM posted) = :year
";
//year $agrs = array("limit" => $t_images, "year" => $year);
if(empty($_GET['year'])){
$year = date("Y");
}else{
$year = $_GET['year'];
}
//month
if(empty($_GET['month']) || int_escape($_GET['month']) > 12){
$month = date("m");
}else{
$month = $_GET['month'];
}
//day
if(empty($_GET['day']) || int_escape($_GET['day']) > 31){
$day = date("d");
}else{
$day = $_GET['day'];
}
$totaldate = $year."/".$month."/".$day;
$sql = if($event->page_matches("popular_by_day")){
"SELECT * FROM images $sql .=
WHERE EXTRACT(YEAR FROM posted) = :year "AND EXTRACT(MONTH FROM posted) = :month
AND EXTRACT(DAY FROM posted) = :day
AND NOT numeric_score=0
"; ";
//array_push doesn't seem to like using double arrows
//this requires us to instead create two arrays and merge
$sgra = array("month" => $month, "day" => $day);
$args = array_merge($agrs, $sgra);
$agrs = array("limit" => $t_images, "year" => $year); $dte = array($totaldate, date("F jS, Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m\\&\\d\\a\\y\\=d", "day");
if($event->page_matches("popular_by_day")){
$sql .=
"AND EXTRACT(MONTH FROM posted) = :month
AND EXTRACT(DAY FROM posted) = :day
AND NOT numeric_score=0
";
//array_push doesn't seem to like using double arrows
//this requires us to instead create two arrays and merge
$sgra = array("month" => $month, "day" => $day);
$args = array_merge($agrs, $sgra);
$dte = array($totaldate, date("F jS, Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m\\&\\d\\a\\y\\=d", "day");
}
if($event->page_matches("popular_by_month")){
$sql .=
"AND EXTRACT(MONTH FROM posted) = :month
AND NOT numeric_score=0
";
$sgra = array("month" => $month);
$args = array_merge($agrs, $sgra);
$title = date("F Y", (strtotime($totaldate)));
$dte = array($totaldate, $title, "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m", "month");
}
if($event->page_matches("popular_by_year")){
$sql .= "AND NOT numeric_score=0";
$dte = array($totaldate, $year, "\y\e\a\\r\=Y", "year");
$args = $agrs;
}
$sql .= " ORDER BY numeric_score DESC LIMIT :limit OFFSET 0";
//filter images by year/score != 0 > limit to max images on one page > order from highest to lowest score
$result = $database->get_all($sql, $args);
$images = array();
foreach($result as $singleResult) {
$images[] = Image::by_id($singleResult["id"]);
}
$this->theme->view_popular($images, $dte);
} }
if($event->page_matches("popular_by_month")){
$sql .=
"AND EXTRACT(MONTH FROM posted) = :month
AND NOT numeric_score=0
";
$sgra = array("month" => $month);
$args = array_merge($agrs, $sgra);
$title = date("F Y", (strtotime($totaldate)));
$dte = array($totaldate, $title, "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m", "month");
}
if($event->page_matches("popular_by_year")){
$sql .= "AND NOT numeric_score=0";
$dte = array($totaldate, $year, "\y\e\a\\r\=Y", "year");
$args = $agrs;
}
$sql .= " ORDER BY numeric_score DESC LIMIT :limit OFFSET 0";
//filter images by year/score != 0 > limit to max images on one page > order from highest to lowest score
$result = $database->get_all($sql, $args);
$images = array();
foreach($result as $singleResult) {
$images[] = Image::by_id($singleResult["id"]);
}
$this->theme->view_popular($images, $dte);
} }
}
if($event instanceof NumericScoreSetEvent) { public function onNumericScoreSet(NumericScoreSetEvent $event) {
log_info("numeric_score", "Rated Image #{$event->image_id} as {$event->score}"); global $user;
$this->add_vote($event->image_id, $user->id, $event->score); log_info("numeric_score", "Rated Image #{$event->image_id} as {$event->score}");
$this->add_vote($event->image_id, $user->id, $event->score);
}
public function onImageDeletion(ImageDeletionEvent $event) {
global $database;
$database->execute("DELETE FROM numeric_score_votes WHERE image_id=:id", array("id" => $event->image->id));
}
// FIXME: on user deletion
// FIXME: on user vote nuke
public function onParseLinkTemplate(ParseLinkTemplateEvent $event) {
$event->replace('$score', $event->image->numeric_score);
}
public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array();
if(preg_match("/^score(<|<=|=|>=|>)(\d+)$/", $event->term, $matches)) {
$cmp = $matches[1];
$score = $matches[2];
$event->add_querylet(new Querylet("numeric_score $cmp $score"));
} }
if(preg_match("/^upvoted_by=(.*)$/", $event->term, $matches)) {
if($event instanceof ImageDeletionEvent) { $duser = User::by_name($matches[1]);
$database->execute("DELETE FROM numeric_score_votes WHERE image_id=:id", array("id" => $event->image->id)); if(is_null($duser)) {
throw new SearchTermParseException(
"Can't find the user named ".html_escape($matches[1]));
}
$event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)",
array("ns_user_id"=>$duser->id)));
} }
if(preg_match("/^downvoted_by=(.*)$/", $event->term, $matches)) {
if($event instanceof ParseLinkTemplateEvent) { $duser = User::by_name($matches[1]);
$event->replace('$score', $event->image->numeric_score); if(is_null($duser)) {
throw new SearchTermParseException(
"Can't find the user named ".html_escape($matches[1]));
}
$event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)",
array("ns_user_id"=>$duser->id)));
} }
if(preg_match("/^upvoted_by_id=(\d+)$/", $event->term, $matches)) {
if($event instanceof SearchTermParseEvent) { $iid = int_escape($matches[1]);
$matches = array(); $event->add_querylet(new Querylet(
if(preg_match("/^score(<|<=|=|>=|>)(\d+)$/", $event->term, $matches)) { "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)",
$cmp = $matches[1]; array("ns_user_id"=>$iid)));
$score = $matches[2]; }
$event->add_querylet(new Querylet("numeric_score $cmp $score")); if(preg_match("/^downvoted_by_id=(\d+)$/", $event->term, $matches)) {
} $iid = int_escape($matches[1]);
if(preg_match("/^upvoted_by=(.*)$/", $event->term, $matches)) { $event->add_querylet(new Querylet(
$duser = User::by_name($matches[1]); "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)",
if(is_null($duser)) { array("ns_user_id"=>$iid)));
throw new SearchTermParseException(
"Can't find the user named ".html_escape($matches[1]));
}
$event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)",
array("ns_user_id"=>$duser->id)));
}
if(preg_match("/^downvoted_by=(.*)$/", $event->term, $matches)) {
$duser = User::by_name($matches[1]);
if(is_null($duser)) {
throw new SearchTermParseException(
"Can't find the user named ".html_escape($matches[1]));
}
$event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)",
array("ns_user_id"=>$duser->id)));
}
if(preg_match("/^upvoted_by_id=(\d+)$/", $event->term, $matches)) {
$iid = int_escape($matches[1]);
$event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)",
array("ns_user_id"=>$iid)));
}
if(preg_match("/^downvoted_by_id=(\d+)$/", $event->term, $matches)) {
$iid = int_escape($matches[1]);
$event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)",
array("ns_user_id"=>$iid)));
}
} }
} }
@ -259,7 +261,7 @@ class NumericScore implements Extension {
} }
} }
private function add_vote($image_id, $user_id, $score) { private function add_vote(/*int*/ $image_id, /*int*/ $user_id, /*int*/ $score) {
global $database; global $database;
$database->execute( $database->execute(
"DELETE FROM numeric_score_votes WHERE image_id=:imageid AND user_id=:userid", "DELETE FROM numeric_score_votes WHERE image_id=:imageid AND user_id=:userid",

View File

@ -5,8 +5,8 @@
* Description: ChibiPaint-based Oekaki uploader * Description: ChibiPaint-based Oekaki uploader
*/ */
class Oekaki extends SimpleExtension { class Oekaki extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $user, $page; global $user, $page;
if($event->page_matches("oekaki")) { if($event->page_matches("oekaki")) {
@ -82,7 +82,7 @@ class Oekaki extends SimpleExtension {
} }
// FIXME: "edit this image" button on existing images? // FIXME: "edit this image" button on existing images?
function onPostListBuilding($event) { function onPostListBuilding(PostListBuildingEvent $event) {
global $user, $page; global $user, $page;
if($this->can_upload($user)) { if($this->can_upload($user)) {
$this->theme->display_block($page); $this->theme->display_block($page);

View File

@ -11,7 +11,7 @@
*/ */
class SendPMEvent extends Event { class SendPMEvent extends Event {
public function __construct($pm) { public function __construct(PM $pm) {
$this->pm = $pm; $this->pm = $pm;
} }
} }
@ -42,8 +42,8 @@ class PM {
} }
} }
class PrivMsg extends SimpleExtension { class PrivMsg extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config, $database; global $config, $database;
// shortcut to latest // shortcut to latest
@ -57,15 +57,28 @@ class PrivMsg extends SimpleExtension {
subject VARCHAR(64) NOT NULL, subject VARCHAR(64) NOT NULL,
message TEXT NOT NULL, message TEXT NOT NULL,
is_read SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N, is_read SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N,
INDEX (to_id) INDEX (to_id),
FOREIGN KEY (from_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (to_id) REFERENCES users(id) ON DELETE CASCADE
"); ");
$config->set_int("pm_version", 1); $config->set_int("pm_version", 1);
log_info("pm", "extension installed"); log_info("pm", "extension installed");
} }
if($config->get_int("pm_version") < 2) {
log_info("pm", "Adding foreign keys to private messages");
$database->Execute("delete from private_message where to_id not in (select id from users);");
$database->Execute("delete from private_message where from_id not in (select id from users);");
$database->Execute("ALTER TABLE private_message
ADD CONSTRAINT foreign_private_message_from_id FOREIGN KEY (from_id) REFERENCES users(id) ON DELETE CASCADE,
ADD CONSTRAINT foreign_private_message_to_id FOREIGN KEY (to_id) REFERENCES users(id) ON DELETE CASCADE;");
$config->set_int("pm_version", 2);
log_info("pm", "extension installed");
}
} }
/* /*
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuilding $event) {
global $user; global $user;
if(!$user->is_anonymous()) { if(!$user->is_anonymous()) {
$event->add_link("Private Messages", make_link("pm")); $event->add_link("Private Messages", make_link("pm"));
@ -73,7 +86,7 @@ class PrivMsg extends SimpleExtension {
} }
*/ */
public function onUserPageBuilding($event) { public function onUserPageBuilding(UserPageBuilding $event) {
global $page, $user; global $page, $user;
$duser = $event->display_user; $duser = $event->display_user;
if(!$user->is_anonymous() && !$duser->is_anonymous()) { if(!$user->is_anonymous() && !$duser->is_anonymous()) {
@ -86,7 +99,7 @@ class PrivMsg extends SimpleExtension {
} }
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $database, $page, $user; global $database, $page, $user;
if($event->page_matches("pm")) { if($event->page_matches("pm")) {
if(!$user->is_anonymous()) { if(!$user->is_anonymous()) {
@ -140,7 +153,7 @@ class PrivMsg extends SimpleExtension {
} }
} }
public function onSendPM($event) { public function onSendPM(SendPMEvent $event) {
global $database; global $database;
$database->execute(" $database->execute("
INSERT INTO private_message( INSERT INTO private_message(

View File

@ -10,8 +10,8 @@
class PoolCreationException extends SCoreException { class PoolCreationException extends SCoreException {
} }
class Pools extends SimpleExtension { class Pools extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config, $database; global $config, $database;
if ($config->get_int("ext_pools_version") < 1){ if ($config->get_int("ext_pools_version") < 1){
@ -65,7 +65,7 @@ class Pools extends SimpleExtension {
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $page, $user; global $config, $page, $user;
if($event->page_matches("pool")) { if($event->page_matches("pool")) {
@ -216,7 +216,7 @@ class Pools extends SimpleExtension {
} }
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
$event->add_link("Pools", make_link("pool/list")); $event->add_link("Pools", make_link("pool/list"));
} }
@ -224,7 +224,7 @@ class Pools extends SimpleExtension {
/* /*
* HERE WE GET THE POOLS WHERE THE IMAGE APPEARS WHEN THE IMAGE IS DISPLAYED * HERE WE GET THE POOLS WHERE THE IMAGE APPEARS WHEN THE IMAGE IS DISPLAYED
*/ */
public function onDisplayingImage($event) { public function onDisplayingImage(DisplayingImageEvent $event) {
global $config, $database, $page; global $config, $database, $page;
if($config->get_bool("poolsInfoOnViewImage")) { if($config->get_bool("poolsInfoOnViewImage")) {
@ -242,7 +242,7 @@ class Pools extends SimpleExtension {
} }
} }
public function onImageAdminBlockBuilding($event) { public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) {
global $config, $database, $user; global $config, $database, $user;
if($config->get_bool("poolsAdderOnViewImage") && !$user->is_anonymous()) { if($config->get_bool("poolsAdderOnViewImage") && !$user->is_anonymous()) {
if($user->is_admin()) { if($user->is_admin()) {
@ -261,7 +261,7 @@ class Pools extends SimpleExtension {
/* /*
* HERE WE GET THE LIST OF POOLS * HERE WE GET THE LIST OF POOLS
*/ */
private function list_pools(Page $page, $pageNumber) { private function list_pools(Page $page, /*int*/ $pageNumber) {
global $config, $database; global $config, $database;
if(is_null($pageNumber) || !is_numeric($pageNumber)) if(is_null($pageNumber) || !is_numeric($pageNumber))

View File

@ -7,8 +7,8 @@
* Further modified by Shish to remove the 7MB local QR generator * Further modified by Shish to remove the 7MB local QR generator
* and replace it with a link to google chart APIs * and replace it with a link to google chart APIs
*/ */
class QRImage extends SimpleExtension { class QRImage extends Extension {
public function onDisplayingImage($event) { public function onDisplayingImage(DisplayingImageEvent $event) {
$this->theme->links_block(make_http(make_link('image/'.$event->image->id.'.jpg'))); $this->theme->links_block(make_http(make_link('image/'.$event->image->id.'.jpg')));
} }
} }

View File

@ -2,6 +2,7 @@
/* /*
* Name: Random Image * Name: Random Image
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: Do things with a random image * Description: Do things with a random image
* Documentation: * Documentation:
@ -19,8 +20,8 @@
* <code>/random_image/download/size=1024x768+cute</code> * <code>/random_image/download/size=1024x768+cute</code>
*/ */
class RandomImage extends SimpleExtension { class RandomImage extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $database, $page, $user; global $config, $database, $page, $user;
if($event->page_matches("random_image")) { if($event->page_matches("random_image")) {
if($event->count_args() == 1) { if($event->count_args() == 1) {
@ -51,13 +52,13 @@ class RandomImage extends SimpleExtension {
} }
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Random Image"); $sb = new SetupBlock("Random Image");
$sb->add_bool_option("show_random_block", "Show Random Block: "); $sb->add_bool_option("show_random_block", "Show Random Block: ");
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onPostListBuilding($event) { public function onPostListBuilding(PostListBuildingEvent $event) {
global $config, $page; global $config, $page;
if($config->get_bool("show_random_block")) { if($config->get_bool("show_random_block")) {
$image = Image::by_random($event->search_terms); $image = Image::by_random($event->search_terms);

View File

@ -2,6 +2,7 @@
/* /*
* Name: Image Ratings * Name: Image Ratings
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: Allow users to rate images "safe", "questionable" or "explicit" * Description: Allow users to rate images "safe", "questionable" or "explicit"
*/ */
@ -17,20 +18,13 @@ class RatingSetEvent extends Event {
} }
} }
class Ratings implements Extension { class Ratings extends Extension {
var $theme; public function onAdminBuilding(AdminBuildingEvent $event) {
$this->theme->display_bulk_rater();
}
public function get_priority() {return 50;} public function onPageRequest(PageRequestEvent $event) {
if($event->page_matches("admin/bulk_rate")) {
public function receive_event(Event $event) {
global $config, $database, $page, $user;
if(is_null($this->theme)) $this->theme = get_theme_object($this);
if($event instanceof AdminBuildingEvent) {
$this->theme->display_bulk_rater();
}
if(($event instanceof PageRequestEvent) && $event->page_matches("admin/bulk_rate")) {
global $database, $user, $page; global $database, $user, $page;
if(!$user->is_admin()) { if(!$user->is_admin()) {
throw PermissionDeniedException(); throw PermissionDeniedException();
@ -40,6 +34,9 @@ class Ratings implements Extension {
while(true) { while(true) {
$images = Image::find_images($n, 100, Tag::explode($_POST["query"])); $images = Image::find_images($n, 100, Tag::explode($_POST["query"]));
if(count($images) == 0) break; if(count($images) == 0) break;
reset($images); // rewind to first element in array.
foreach($images as $image) { foreach($images as $image) {
send_event(new RatingSetEvent($image, $user, $_POST['rating'])); send_event(new RatingSetEvent($image, $user, $_POST['rating']));
} }
@ -54,95 +51,98 @@ class Ratings implements Extension {
$page->set_redirect(make_link("admin")); $page->set_redirect(make_link("admin"));
} }
} }
}
if($event instanceof InitExtEvent) { public function onInitExt(InitExtEvent $event) {
if($config->get_int("ext_ratings2_version") < 2) { global $config;
$this->install();
}
$config->set_default_string("ext_rating_anon_privs", 'squ'); if($config->get_int("ext_ratings2_version") < 2) {
$config->set_default_string("ext_rating_user_privs", 'sqeu'); $this->install();
$config->set_default_string("ext_rating_admin_privs", 'sqeu');
} }
if($event instanceof RatingSetEvent) { $config->set_default_string("ext_rating_anon_privs", 'squ');
if(empty($event->image->rating)){ $config->set_default_string("ext_rating_user_privs", 'sqeu');
$old_rating = ""; $config->set_default_string("ext_rating_admin_privs", 'sqeu');
}else{ }
$old_rating = $event->image->rating;
} public function onRatingSet(RatingSetEvent $event) {
$this->set_rating($event->image->id, $event->rating, $old_rating); if(empty($event->image->rating)){
$old_rating = "";
}else{
$old_rating = $event->image->rating;
} }
$this->set_rating($event->image->id, $event->rating, $old_rating);
}
if($event instanceof ImageInfoBoxBuildingEvent) { public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) {
if($this->can_rate()) { if($this->can_rate()) {
$event->add_part($this->theme->get_rater_html($event->image->id, $event->image->rating), 80); $event->add_part($this->theme->get_rater_html($event->image->id, $event->image->rating), 80);
}
}
if($event instanceof ImageInfoSetEvent) {
if($this->can_rate() && isset($_POST["rating"])) {
send_event(new RatingSetEvent($event->image, $user, $_POST['rating']));
}
}
if($event instanceof SetupBuildingEvent) {
$privs = array();
$privs['Safe Only'] = 's';
$privs['Safe and Unknown'] = 'su';
$privs['Safe and Questionable'] = 'sq';
$privs['Safe, Questionable, Unknown'] = 'squ';
$privs['All'] = 'sqeu';
$sb = new SetupBlock("Image Ratings");
$sb->add_choice_option("ext_rating_anon_privs", $privs, "Anonymous: ");
$sb->add_choice_option("ext_rating_user_privs", $privs, "<br>Users: ");
$sb->add_choice_option("ext_rating_admin_privs", $privs, "<br>Admins: ");
$event->panel->add_block($sb);
}
if($event instanceof ParseLinkTemplateEvent) {
$event->replace('$rating', $this->theme->rating_to_name($event->image->rating));
}
if($event instanceof SearchTermParseEvent) {
$matches = array();
if(is_null($event->term) && $this->no_rating_query($event->context)) {
$set = Ratings::privs_to_sql(Ratings::get_user_privs($user));
$event->add_querylet(new Querylet("rating IN ($set)"));
}
if(preg_match("/^rating=([sqeu]+)$/", $event->term, $matches)) {
$sqes = $matches[1];
$arr = array();
$length = strlen($sqes);
for($i=0; $i<$length; $i++) {
$arr[] = "'" . $sqes[$i] . "'";
}
$set = join(', ', $arr);
$event->add_querylet(new Querylet("rating IN ($set)"));
}
if(preg_match("/^rating=(safe|questionable|explicit|unknown)$/", strtolower($event->term), $matches)) {
$text = $matches[1];
$char = $text[0];
$event->add_querylet(new Querylet("rating = :img_rating", array("img_rating"=>$char)));
}
}
if($event instanceof DisplayingImageEvent) {
/**
* Deny images upon insufficient permissions.
**/
global $user, $database, $page;
$user_view_level = Ratings::get_user_privs($user);
$user_view_level = preg_split('//', $user_view_level, -1);
if(!in_array($event->image->rating, $user_view_level)) {
$page->set_mode("redirect");
$page->set_redirect(make_link("post/list"));
}
} }
} }
public static function get_user_privs($user) { public function onImageInfoSet(ImageInfoSetEvent $event) {
global $user;
if($this->can_rate() && isset($_POST["rating"])) {
send_event(new RatingSetEvent($event->image, $user, $_POST['rating']));
}
}
public function onSetupBuilding(SetupBuildingEvent $event) {
$privs = array();
$privs['Safe Only'] = 's';
$privs['Safe and Unknown'] = 'su';
$privs['Safe and Questionable'] = 'sq';
$privs['Safe, Questionable, Unknown'] = 'squ';
$privs['All'] = 'sqeu';
$sb = new SetupBlock("Image Ratings");
$sb->add_choice_option("ext_rating_anon_privs", $privs, "Anonymous: ");
$sb->add_choice_option("ext_rating_user_privs", $privs, "<br>Users: ");
$sb->add_choice_option("ext_rating_admin_privs", $privs, "<br>Admins: ");
$event->panel->add_block($sb);
}
public function onParseLinkTemplate(ParseLinkTemplateEvent $event) {
$event->replace('$rating', $this->theme->rating_to_name($event->image->rating));
}
public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array();
if(is_null($event->term) && $this->no_rating_query($event->context)) {
$set = Ratings::privs_to_sql(Ratings::get_user_privs($user));
$event->add_querylet(new Querylet("rating IN ($set)"));
}
if(preg_match("/^rating=([sqeu]+)$/", $event->term, $matches)) {
$sqes = $matches[1];
$arr = array();
$length = strlen($sqes);
for($i=0; $i<$length; $i++) {
$arr[] = "'" . $sqes[$i] . "'";
}
$set = join(', ', $arr);
$event->add_querylet(new Querylet("rating IN ($set)"));
}
if(preg_match("/^rating=(safe|questionable|explicit|unknown)$/", strtolower($event->term), $matches)) {
$text = $matches[1];
$char = $text[0];
$event->add_querylet(new Querylet("rating = :img_rating", array("img_rating"=>$char)));
}
}
public function onDisplayingImage(DisplayingImageEvent $event) {
/**
* Deny images upon insufficient permissions.
**/
global $user, $page;
$user_view_level = Ratings::get_user_privs($user);
$user_view_level = preg_split('//', $user_view_level, -1);
if(!in_array($event->image->rating, $user_view_level)) {
$page->set_mode("redirect");
$page->set_redirect(make_link("post/list"));
}
}
public static function get_user_privs(User $user) {
global $config; global $config;
if($user->is_anonymous()) { if($user->is_anonymous()) {
$sqes = $config->get_string("ext_rating_anon_privs"); $sqes = $config->get_string("ext_rating_anon_privs");

View File

@ -2,6 +2,7 @@
/* /*
* Name: Regen Thumb * Name: Regen Thumb
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Description: Regenerate a thumbnail image * Description: Regenerate a thumbnail image
* Documentation: * Documentation:
@ -12,8 +13,8 @@
* since been increased. * since been increased.
*/ */
class RegenThumb extends SimpleExtension { class RegenThumb extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $database, $page, $user; global $config, $database, $page, $user;
if($event->page_matches("regen_thumb") && $user->is_admin() && isset($_POST['image_id'])) { if($event->page_matches("regen_thumb") && $user->is_admin() && isset($_POST['image_id'])) {
@ -23,7 +24,7 @@ class RegenThumb extends SimpleExtension {
} }
} }
public function onImageAdminBlockBuilding($event) { public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_part($this->theme->get_buttons_html($event->image->id)); $event->add_part($this->theme->get_buttons_html($event->image->id));

View File

@ -29,24 +29,19 @@ class AddReportedImageEvent extends Event {
} }
} }
class ReportImage implements Extension { class ReportImage extends Extension {
var $theme; public function onInitExt(InitExtEvent $event) {
global $config;
$config->set_default_bool('report_image_show_thumbs', true);
public function get_priority() {return 50;} if($config->get_int("ext_report_image_version") < 1) {
$this->install();
public function receive_event(Event $event) {
global $config, $database, $page, $user;
if(is_null($this->theme)) $this->theme = get_theme_object($this);
if($event instanceof InitExtEvent) {
$config->set_default_bool('report_image_show_thumbs', true);
if($config->get_int("ext_report_image_version") < 1) {
$this->install();
}
} }
}
if(($event instanceof PageRequestEvent) && $event->page_matches("image_report")) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user;
if($event->page_matches("image_report")) {
if($event->get_arg(0) == "add") { if($event->get_arg(0) == "add") {
if(isset($_POST['image_id']) && isset($_POST['reason'])) { if(isset($_POST['image_id']) && isset($_POST['reason'])) {
$image_id = int_escape($_POST['image_id']); $image_id = int_escape($_POST['image_id']);
@ -70,40 +65,45 @@ class ReportImage implements Extension {
} }
} }
} }
}
if($event instanceof AddReportedImageEvent) { public function onAddReportedImage(AddReportedImageEvent $event) {
$database->Execute( global $database;
"INSERT INTO image_reports(image_id, reporter_id, reason) $database->Execute(
VALUES (?, ?, ?)", "INSERT INTO image_reports(image_id, reporter_id, reason)
array($event->image_id, $event->reporter_id, $event->reason)); VALUES (?, ?, ?)",
} array($event->image_id, $event->reporter_id, $event->reason));
}
if($event instanceof RemoveReportedImageEvent) { public function onRemoveReportedImage(RemoveReportedImageEvent $event) {
$database->Execute("DELETE FROM image_reports WHERE id = ?", array($event->id)); global $database;
} $database->Execute("DELETE FROM image_reports WHERE id = ?", array($event->id));
}
if($event instanceof DisplayingImageEvent) { public function onDisplayingImage(DisplayingImageEvent $event) {
if($config->get_bool('report_image_anon') || !$user->is_anonymous()) { global $config, $user, $page;
$this->theme->display_image_banner($page, $event->image); if($config->get_bool('report_image_anon') || !$user->is_anonymous()) {
} $this->theme->display_image_banner($page, $event->image);
} }
}
if($event instanceof SetupBuildingEvent) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Report Image Options"); $sb = new SetupBlock("Report Image Options");
$sb->add_bool_option("report_image_anon", "Allow anonymous image reporting: "); $sb->add_bool_option("report_image_anon", "Allow anonymous image reporting: ");
$sb->add_bool_option("report_image_show_thumbs", "<br>Show thumbnails in admin panel: "); $sb->add_bool_option("report_image_show_thumbs", "<br>Show thumbnails in admin panel: ");
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
if($event instanceof UserBlockBuildingEvent) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
if($user->is_admin()) { global $user;
$event->add_link("Reported Images", make_link("image_report/list")); if($user->is_admin()) {
} $event->add_link("Reported Images", make_link("image_report/list"));
} }
}
if($event instanceof ImageDeletionEvent) { public function onImageDeletion(ImageDeletionEvent $event) {
$database->Execute("DELETE FROM image_reports WHERE image_id = ?", array($event->image->id)); global $database;
} $database->Execute("DELETE FROM image_reports WHERE image_id = ?", array($event->image->id));
} }
protected function install() { protected function install() {

View File

@ -5,69 +5,68 @@
* License: GPLv2 * License: GPLv2
* Description: Allows the admin to set min / max image dimentions * Description: Allows the admin to set min / max image dimentions
*/ */
class ResolutionLimit implements Extension { class ResolutionLimit extends Extension {
public function get_priority() {return 40;} // early, to veto ImageUploadEvent public function get_priority() {return 40;} // early, to veto ImageUploadEvent
public function receive_event(Event $event) { public function onImageAddition(ImageAdditionEvent $event) {
if($event instanceof ImageAdditionEvent) { global $config;
global $config; $min_w = $config->get_int("upload_min_width", -1);
$min_w = $config->get_int("upload_min_width", -1); $min_h = $config->get_int("upload_min_height", -1);
$min_h = $config->get_int("upload_min_height", -1); $max_w = $config->get_int("upload_max_width", -1);
$max_w = $config->get_int("upload_max_width", -1); $max_h = $config->get_int("upload_max_height", -1);
$max_h = $config->get_int("upload_max_height", -1); $ratios = explode(" ", $config->get_string("upload_ratios", ""));
$ratios = explode(" ", $config->get_string("upload_ratios", ""));
$image = $event->image; $image = $event->image;
if($min_w > 0 && $image->width < $min_w) throw new UploadException("Image too small"); if($min_w > 0 && $image->width < $min_w) throw new UploadException("Image too small");
if($min_h > 0 && $image->height < $min_h) throw new UploadException("Image too small"); if($min_h > 0 && $image->height < $min_h) throw new UploadException("Image too small");
if($max_w > 0 && $image->width > $max_w) throw new UploadException("Image too large"); if($max_w > 0 && $image->width > $max_w) throw new UploadException("Image too large");
if($max_h > 0 && $image->height > $max_h) throw new UploadException("Image too large"); if($max_h > 0 && $image->height > $max_h) throw new UploadException("Image too large");
if(count($ratios) > 0) { if(count($ratios) > 0) {
$ok = false; $ok = false;
$valids = 0; $valids = 0;
foreach($ratios as $ratio) { foreach($ratios as $ratio) {
$parts = explode(":", $ratio); $parts = explode(":", $ratio);
if(count($parts) < 2) continue; if(count($parts) < 2) continue;
$valids++; $valids++;
$width = $parts[0]; $width = $parts[0];
$height = $parts[1]; $height = $parts[1];
if($image->width / $width == $image->height / $height) { if($image->width / $width == $image->height / $height) {
$ok = true; $ok = true;
break; break;
}
}
if($valids > 0 && !$ok) {
throw new UploadException(
"Image needs to be in one of these ratios: ".
html_escape($config->get_string("upload_ratios", "")));
} }
} }
if($valids > 0 && !$ok) {
throw new UploadException(
"Image needs to be in one of these ratios: ".
html_escape($config->get_string("upload_ratios", "")));
}
} }
if($event instanceof SetupBuildingEvent) { }
$sb = new SetupBlock("Resolution Limits");
$sb->add_label("Min "); public function onSetupBuilding(SetupBuildingEvent $event) {
$sb->add_int_option("upload_min_width"); $sb = new SetupBlock("Resolution Limits");
$sb->add_label(" x ");
$sb->add_int_option("upload_min_height");
$sb->add_label(" px");
$sb->add_label("<br>Max "); $sb->add_label("Min ");
$sb->add_int_option("upload_max_width"); $sb->add_int_option("upload_min_width");
$sb->add_label(" x "); $sb->add_label(" x ");
$sb->add_int_option("upload_max_height"); $sb->add_int_option("upload_min_height");
$sb->add_label(" px"); $sb->add_label(" px");
$sb->add_label("<br>(-1 for no limit)"); $sb->add_label("<br>Max ");
$sb->add_int_option("upload_max_width");
$sb->add_label(" x ");
$sb->add_int_option("upload_max_height");
$sb->add_label(" px");
$sb->add_label("<br>Ratios "); $sb->add_label("<br>(-1 for no limit)");
$sb->add_text_option("upload_ratios");
$sb->add_label("<br>(eg. '4:3 16:9', blank for no limit)");
$event->panel->add_block($sb); $sb->add_label("<br>Ratios ");
} $sb->add_text_option("upload_ratios");
$sb->add_label("<br>(eg. '4:3 16:9', blank for no limit)");
$event->panel->add_block($sb);
} }
} }
?> ?>

View File

@ -26,9 +26,9 @@ class ImageResizeException extends SCoreException {
/** /**
* This class handles image resize requests. * This class handles image resize requests.
*/ */
class ResizeImage extends SimpleExtension { class ResizeImage extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_bool('resize_enabled', true); $config->set_default_bool('resize_enabled', true);
$config->set_default_bool('resize_upload', false); $config->set_default_bool('resize_upload', false);
@ -36,7 +36,7 @@ class ResizeImage extends SimpleExtension {
$config->set_default_int('resize_default_height', 0); $config->set_default_int('resize_default_height', 0);
} }
public function onImageAdminBlockBuilding($event) { public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) {
global $user, $config; global $user, $config;
if($user->is_admin() && $config->get_bool("resize_enabled")) { if($user->is_admin() && $config->get_bool("resize_enabled")) {
/* Add a link to resize the image */ /* Add a link to resize the image */
@ -44,7 +44,7 @@ class ResizeImage extends SimpleExtension {
} }
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Image Resize"); $sb = new SetupBlock("Image Resize");
$sb->add_bool_option("resize_enabled", "Allow resizing images: "); $sb->add_bool_option("resize_enabled", "Allow resizing images: ");
$sb->add_bool_option("resize_upload", "<br>Resize on upload: "); $sb->add_bool_option("resize_upload", "<br>Resize on upload: ");
@ -89,7 +89,7 @@ class ResizeImage extends SimpleExtension {
} }
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;
if ( $event->page_matches("resize") && $user->is_admin() ) { if ( $event->page_matches("resize") && $user->is_admin() ) {

View File

@ -6,8 +6,8 @@
* Description: Self explanatory * Description: Self explanatory
*/ */
class RSS_Comments extends SimpleExtension { class RSS_Comments extends Extension {
public function onPostListBuilding($event) { public function onPostListBuilding(PostListBuildingEvent $event) {
global $config, $page; global $config, $page;
$title = $config->get_string('title'); $title = $config->get_string('title');
@ -15,7 +15,7 @@ class RSS_Comments extends SimpleExtension {
"title=\"$title - Comments\" href=\"".make_link("rss/comments")."\" />"); "title=\"$title - Comments\" href=\"".make_link("rss/comments")."\" />");
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $database, $page; global $config, $database, $page;
if($event->page_matches("rss/comments")) { if($event->page_matches("rss/comments")) {
$page->set_mode("data"); $page->set_mode("data");

View File

@ -6,8 +6,8 @@
* Description: Self explanatory * Description: Self explanatory
*/ */
class RSS_Images extends SimpleExtension { class RSS_Images extends Extension {
public function onPostListBuilding($event) { public function onPostListBuilding(PostListBuildingEvent $event) {
global $config, $page; global $config, $page;
$title = $config->get_string('title'); $title = $config->get_string('title');
@ -22,7 +22,7 @@ class RSS_Images extends SimpleExtension {
} }
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
if($event->page_matches("rss/images")) { if($event->page_matches("rss/images")) {
$search_terms = $event->get_search_terms(); $search_terms = $event->get_search_terms();
$page_number = $event->get_page_number(); $page_number = $event->get_page_number();

View File

@ -26,7 +26,7 @@ class _SafeImage {
} }
} }
class ShimmieApi extends SimpleExtension { class ShimmieApi extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $database, $page; global $database, $page;

View File

@ -205,8 +205,8 @@ class TestFinder extends TestSuite {
} }
} }
class SimpleSCoreTest extends SimpleExtension { class SimpleSCoreTest extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $page; global $page;
if($event->page_matches("test")) { if($event->page_matches("test")) {
set_time_limit(0); set_time_limit(0);
@ -220,7 +220,7 @@ class SimpleSCoreTest extends SimpleExtension {
} }
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_link("Run Tests", make_link("test/all")); $event->add_link("Run Tests", make_link("test/all"));

View File

@ -2,6 +2,7 @@
/* /*
* Name: Site Description * Name: Site Description
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* License: GPLv2 * License: GPLv2
* Visibility: admin * Visibility: admin
* Description: A description for search engines * Description: A description for search engines
@ -9,7 +10,7 @@
* This extension sets the "description" meta tag in the header * This extension sets the "description" meta tag in the header
* of pages so that search engines can pick it up * of pages so that search engines can pick it up
*/ */
class SiteDescription extends SimpleExtension { class SiteDescription extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $page; global $config, $page;
if(strlen($config->get_string("site_description")) > 0) { if(strlen($config->get_string("site_description")) > 0) {

View File

@ -7,15 +7,15 @@
* Documentation: * Documentation:
*/ */
class XMLSitemap extends SimpleExtension { class XMLSitemap extends Extension {
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
if($event->page_matches("sitemap.xml")) { if($event->page_matches("sitemap.xml")) {
$images = Image::find_images(0, 50, array()); $images = Image::find_images(0, 50, array());
$this->do_xml($images); $this->do_xml($images);
} }
} }
private function do_xml($images) { private function do_xml(/*array(Image)*/ $images) {
global $page; global $page;
$page->set_mode("data"); $page->set_mode("data");
$page->set_type("application/xml"); $page->set_type("application/xml");

View File

@ -12,56 +12,50 @@
* colorize used tags in cloud || always show used tags in front of cloud * colorize used tags in cloud || always show used tags in front of cloud
* theme junk * theme junk
*/ */
class TagEditCloud implements Extension { class TagEditCloud extends Extension {
var $theme; public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) {
global $config;
public function get_priority() {return 50;} if(!$config->get_bool("tageditcloud_disable")) {
if($this->can_tag($event->image)) {
public function receive_event(Event $event) { if(!$cfg_minusage=$config->get_int("tageditcloud_minusage")) $cfg_minusage=2;
global $config, $database, $page, $user; if(!$cfg_defcount=$config->get_int("tageditcloud_defcount")) $cfg_defcount=40;
//if(is_null($this->theme)) $this->theme = get_theme_object($this); if(!$cfg_maxcount=$config->get_int("tageditcloud_maxcount")) $cfg_maxcount=4096;
if($config->get_string("tageditcloud_sort") != "p") {
if($event instanceof ImageInfoBoxBuildingEvent) { $event->add_part($this->build_tag_map($event->image,$cfg_minusage,false),40);
if(!$config->get_bool("tageditcloud_disable")) { } else {
if($this->can_tag($event->image)) { $event->add_part($this->build_tag_map($event->image,$cfg_defcount,$cfg_maxcount),40);
if(!$cfg_minusage=$config->get_int("tageditcloud_minusage")) $cfg_minusage=2;
if(!$cfg_defcount=$config->get_int("tageditcloud_defcount")) $cfg_defcount=40;
if(!$cfg_maxcount=$config->get_int("tageditcloud_maxcount")) $cfg_maxcount=4096;
if($config->get_string("tageditcloud_sort") != "p") {
$event->add_part($this->build_tag_map($event->image,$cfg_minusage,false),40);
} else {
$event->add_part($this->build_tag_map($event->image,$cfg_defcount,$cfg_maxcount),40);
}
} }
} }
} }
}
if($event instanceof InitExtEvent) { public function onInitExt(InitExtEvent $event) {
$config->set_default_bool("tageditcloud_disable",false); global $config;
$config->set_default_bool("tageditcloud_usedfirst",true); $config->set_default_bool("tageditcloud_disable",false);
$config->set_default_string("tageditcloud_sort",'a'); $config->set_default_bool("tageditcloud_usedfirst",true);
$config->set_default_int("tageditcloud_minusage",2); $config->set_default_string("tageditcloud_sort",'a');
$config->set_default_int("tageditcloud_defcount",40); $config->set_default_int("tageditcloud_minusage",2);
$config->set_default_int("tageditcloud_maxcount",4096); $config->set_default_int("tageditcloud_defcount",40);
} $config->set_default_int("tageditcloud_maxcount",4096);
}
if($event instanceof SetupBuildingEvent) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sort_by = array('Alphabetical'=>'a','Popularity'=>'p'); $sort_by = array('Alphabetical'=>'a','Popularity'=>'p');
$sb = new SetupBlock("Tag Edit Cloud"); $sb = new SetupBlock("Tag Edit Cloud");
$sb->add_bool_option("tageditcloud_disable", "Disable Tag Selection Cloud: "); $sb->add_bool_option("tageditcloud_disable", "Disable Tag Selection Cloud: ");
$sb->add_choice_option("tageditcloud_sort", $sort_by, "<br>Sort the tags by:"); $sb->add_choice_option("tageditcloud_sort", $sort_by, "<br>Sort the tags by:");
$sb->add_bool_option("tageditcloud_usedfirst","<br>Always show used tags first: "); $sb->add_bool_option("tageditcloud_usedfirst","<br>Always show used tags first: ");
$sb->add_label("<br><b>Alpha sort</b>:<br>Only show tags used at least "); $sb->add_label("<br><b>Alpha sort</b>:<br>Only show tags used at least ");
$sb->add_int_option("tageditcloud_minusage"); $sb->add_int_option("tageditcloud_minusage");
$sb->add_label(" times.<br><b>Popularity sort</b>:<br>Show "); $sb->add_label(" times.<br><b>Popularity sort</b>:<br>Show ");
$sb->add_int_option("tageditcloud_defcount"); $sb->add_int_option("tageditcloud_defcount");
$sb->add_label(" tags by default.<br>Show a maximum of "); $sb->add_label(" tags by default.<br>Show a maximum of ");
$sb->add_int_option("tageditcloud_maxcount"); $sb->add_int_option("tageditcloud_maxcount");
$sb->add_label(" tags."); $sb->add_label(" tags.");
$event->panel->add_block($sb); $event->panel->add_block($sb);
}
} }
private function tag_link($tag) { private function tag_link($tag) {

View File

@ -5,11 +5,11 @@
* Description: Keep a record of tag changes, and allows you to revert changes. * Description: Keep a record of tag changes, and allows you to revert changes.
*/ */
class Tag_History extends SimpleExtension { class Tag_History extends Extension {
// in before tags are actually set, so that "get current tags" works // in before tags are actually set, so that "get current tags" works
public function get_priority() {return 40;} public function get_priority() {return 40;}
public function onInitExtEvent($event) { public function onInitExtEvent(InitExtEvent $event) {
global $config; global $config;
$config->set_default_int("history_limit", -1); $config->set_default_int("history_limit", -1);
@ -19,7 +19,7 @@ class Tag_History extends SimpleExtension {
} }
} }
public function onAdminBuildingEvent($event) { public function onAdminBuildingEvent(AdminBuildingEvent $event) {
global $user; global $user;
if(isset($_POST['revert_ip']) && $user->is_admin() && $user->check_auth_token()) { if(isset($_POST['revert_ip']) && $user->is_admin() && $user->check_auth_token()) {
@ -55,7 +55,7 @@ class Tag_History extends SimpleExtension {
} }
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $page, $user; global $config, $page, $user;
if ($event->page_matches("tag_history")) { if ($event->page_matches("tag_history")) {
@ -78,18 +78,18 @@ class Tag_History extends SimpleExtension {
} }
} }
public function onDisplayingImage($event) { public function onDisplayingImage(DisplayingImageEvent $event) {
global $page; global $page;
// handle displaying a link on the view page // handle displaying a link on the view page
$this->theme->display_history_link($page, $event->image->id); $this->theme->display_history_link($page, $event->image->id);
} }
public function onImageDeletion($event) { public function onImageDeletion(ImageDeletionEvent $event) {
// handle removing of history when an image is deleted // handle removing of history when an image is deleted
$this->delete_all_tag_history($event->image->id); $this->delete_all_tag_history($event->image->id);
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Tag History"); $sb = new SetupBlock("Tag History");
$sb->add_label("Limit to "); $sb->add_label("Limit to ");
$sb->add_int_option("history_limit"); $sb->add_int_option("history_limit");
@ -98,19 +98,18 @@ class Tag_History extends SimpleExtension {
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onTagSet($event) { public function onTagSet(TagSetEvent $event) {
$this->add_tag_history($event->image, $event->tags); $this->add_tag_history($event->image, $event->tags);
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_link("Tag Changes", make_link("tag_history")); $event->add_link("Tag Changes", make_link("tag_history"));
} }
} }
protected function install() protected function install() {
{
global $database; global $database;
global $config; global $config;

View File

@ -6,46 +6,37 @@
* Do not remove this notice. * Do not remove this notice.
*/ */
class Tagger implements Extension { class Tagger extends Extension {
var $theme; public function onDisplayingImage(DisplayingImageEvent $event) {
global $page, $config, $user;
public function get_priority() {return 50;} if($config->get_bool("tag_edit_anon")
|| ($user->id != $config->get_int("anon_id"))
public function receive_event(Event $event) { && $config->get_bool("ext_tagger_enabled"))
if(is_null($this->theme)) {
$this->theme = get_theme_object($this); $this->theme->build_tagger($page,$event);
if($event instanceof DisplayingImageEvent) {
global $page, $config, $user;
if($config->get_bool("tag_edit_anon")
|| ($user->id != $config->get_int("anon_id"))
&& $config->get_bool("ext_tagger_enabled"))
{
$this->theme->build_tagger($page,$event);
}
} }
}
if($event instanceof SetupBuildingEvent) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Tagger"); $sb = new SetupBlock("Tagger");
$sb->add_bool_option("ext_tagger_enabled","Enable Tagger"); $sb->add_bool_option("ext_tagger_enabled","Enable Tagger");
$sb->add_int_option("ext_tagger_search_delay","<br/>Delay queries by "); $sb->add_int_option("ext_tagger_search_delay","<br/>Delay queries by ");
$sb->add_label(" milliseconds."); $sb->add_label(" milliseconds.");
$sb->add_label("<br/>Limit queries returning more than "); $sb->add_label("<br/>Limit queries returning more than ");
$sb->add_int_option("ext_tagger_tag_max"); $sb->add_int_option("ext_tagger_tag_max");
$sb->add_label(" tags to "); $sb->add_label(" tags to ");
$sb->add_int_option("ext_tagger_limit"); $sb->add_int_option("ext_tagger_limit");
$event->panel->add_block($sb); $event->panel->add_block($sb);
}
} }
} }
// Tagger AJAX back-end // Tagger AJAX back-end
class TaggerXML implements Extension { class TaggerXML extends Extension {
public function get_priority() {return 10;} public function get_priority() {return 10;}
public function receive_event(Event $event) { public function onPageRequest(PageRequestEvent $event) {
if(($event instanceof PageRequestEvent) && $event->page_matches("tagger/tags")) { if($event->page_matches("tagger/tags")) {
global $page; global $page;
//$match_tags = null; //$match_tags = null;

View File

@ -8,8 +8,8 @@
* Formatting is done with HTML * Formatting is done with HTML
*/ */
class Tips extends SimpleExtension { class Tips extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $config, $database; global $config, $database;
if ($config->get_int("ext_tips_version") < 1){ if ($config->get_int("ext_tips_version") < 1){
@ -31,7 +31,7 @@ class Tips extends SimpleExtension {
} }
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;
$this->getTip(); $this->getTip();
@ -67,7 +67,7 @@ class Tips extends SimpleExtension {
} }
} }
public function onUserBlockBuilding($event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->is_admin()) {
$event->add_link("Tips Editor", make_link("tips/list")); $event->add_link("Tips Editor", make_link("tips/list"));

View File

@ -6,15 +6,15 @@
* Description: Show a twitter feed with the Sea of Clouds script * Description: Show a twitter feed with the Sea of Clouds script
*/ */
class TwitterSoc extends SimpleExtension { class TwitterSoc extends Extension {
public function onPostListBuilding($event) { public function onPostListBuilding(PostListBuildingEvent $event) {
global $config, $page; global $config, $page;
if(strlen($config->get_string("twitter_soc_username")) > 0) { if(strlen($config->get_string("twitter_soc_username")) > 0) {
$this->theme->display_feed($page, $config->get_string("twitter_soc_username")); $this->theme->display_feed($page, $config->get_string("twitter_soc_username"));
} }
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Tweet!"); $sb = new SetupBlock("Tweet!");
$sb->add_text_option("twitter_soc_username", "Username "); $sb->add_text_option("twitter_soc_username", "Username ");
$event->panel->add_block($sb); $event->panel->add_block($sb);

View File

@ -6,14 +6,14 @@
* License: GPLv2 * License: GPLv2
* Description: Shimmie updater! * Description: Shimmie updater!
*/ */
class Update extends SimpleExtension { class Update extends Extension {
public function onInitExt(Event $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_string("update_url", "http://nodeload.github.com/shish/shimmie2/zipball/master"); //best to avoid using https $config->set_default_string("update_url", "http://nodeload.github.com/shish/shimmie2/zipball/master"); //best to avoid using https
$config->set_default_string("commit_hash", ""); $config->set_default_string("commit_hash", "");
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
global $config; global $config;
//Would prefer to use the admin panel for this. //Would prefer to use the admin panel for this.
//But since the admin panel is optional...kind of stuck to using this. //But since the admin panel is optional...kind of stuck to using this.
@ -25,7 +25,7 @@ class Update extends SimpleExtension {
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onPageRequest(Event $event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $user; global $config, $user;
if($event->page_matches("update") && $user->is_admin()) { if($event->page_matches("update") && $user->is_admin()) {
$ok = $this->update_shimmie(); $ok = $this->update_shimmie();

View File

@ -53,8 +53,8 @@ class WikiPage {
} }
} }
class Wiki extends SimpleExtension { class Wiki extends Extension {
public function onInitExt($event) { public function onInitExt(InitExtEvent $event) {
global $database; global $database;
global $config; global $config;
@ -80,7 +80,7 @@ class Wiki extends SimpleExtension {
} }
} }
public function onPageRequest($event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $page, $user; global $config, $page, $user;
if($event->page_matches("wiki")) { if($event->page_matches("wiki")) {
if(is_null($event->get_arg(0)) || strlen(trim($event->get_arg(0))) == 0) { if(is_null($event->get_arg(0)) || strlen(trim($event->get_arg(0))) == 0) {
@ -153,7 +153,7 @@ class Wiki extends SimpleExtension {
} }
} }
public function onWikiUpdate($event) { public function onWikiUpdate(WikiUpdateEvent $event) {
global $database; global $database;
$wpage = $event->wikipage; $wpage = $event->wikipage;
try { try {
@ -167,7 +167,7 @@ class Wiki extends SimpleExtension {
} }
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Wiki"); $sb = new SetupBlock("Wiki");
$sb->add_bool_option("wiki_edit_anon", "Allow anonymous edits: "); $sb->add_bool_option("wiki_edit_anon", "Allow anonymous edits: ");
$sb->add_bool_option("wiki_edit_user", "<br>Allow user edits: "); $sb->add_bool_option("wiki_edit_user", "<br>Allow user edits: ");

View File

@ -6,16 +6,16 @@
* Description: Simple search and replace * Description: Simple search and replace
*/ */
class WordFilter extends SimpleExtension { class WordFilter extends Extension {
// before emoticon filter // before emoticon filter
public function get_priority() {return 40;} public function get_priority() {return 40;}
public function onTextFormatting($event) { public function onTextFormatting(TextFormattingEvent $event) {
$event->formatted = $this->filter($event->formatted); $event->formatted = $this->filter($event->formatted);
$event->stripped = $this->filter($event->stripped); $event->stripped = $this->filter($event->stripped);
} }
public function onSetupBuilding($event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Word Filter"); $sb = new SetupBlock("Word Filter");
$sb->add_longtext_option("word_filter"); $sb->add_longtext_option("word_filter");
$sb->add_label("<br>(each line should be search term and replace term, separated by a comma)"); $sb->add_label("<br>(each line should be search term and replace term, separated by a comma)");

View File

@ -8,17 +8,17 @@ interface Config {
* so that the next time a page is loaded it will use the new * so that the next time a page is loaded it will use the new
* configuration * configuration
*/ */
public function save($name=null); public function save(/*string*/ $name=null);
/** @name set_* /** @name set_*
* Set a configuration option to a new value, regardless * Set a configuration option to a new value, regardless
* of what the value is at the moment * of what the value is at the moment
*/ */
//@{ //@{
public function set_int($name, $value); public function set_int(/*string*/ $name, $value);
public function set_string($name, $value); public function set_string(/*string*/ $name, $value);
public function set_bool($name, $value); public function set_bool(/*string*/ $name, $value);
public function set_array($name, $value); public function set_array(/*string*/ $name, $value);
//@} //@}
/** @name set_default_* /** @name set_default_*
@ -30,10 +30,10 @@ interface Config {
* "default" paramater won't show up. * "default" paramater won't show up.
*/ */
//@{ //@{
public function set_default_int($name, $value); public function set_default_int(/*string*/ $name, $value);
public function set_default_string($name, $value); public function set_default_string(/*string*/ $name, $value);
public function set_default_bool($name, $value); public function set_default_bool(/*string*/ $name, $value);
public function set_default_array($name, $value); public function set_default_array(/*string*/ $name, $value);
//@} //@}
/** @name get_* /** @name get_*
@ -41,10 +41,10 @@ interface Config {
* appropritate data type * appropritate data type
*/ */
//@{ //@{
public function get_int($name, $default=null); public function get_int(/*string*/ $name, $default=null);
public function get_string($name, $default=null); public function get_string(/*string*/ $name, $default=null);
public function get_bool($name, $default=null); public function get_bool(/*string*/ $name, $default=null);
public function get_array($name, $default=array()); public function get_array(/*string*/ $name, $default=array());
//@} //@}
} }
@ -56,60 +56,60 @@ interface Config {
abstract class BaseConfig implements Config { abstract class BaseConfig implements Config {
var $values = array(); var $values = array();
public function set_int($name, $value) { public function set_int(/*string*/ $name, $value) {
$this->values[$name] = parse_shorthand_int($value); $this->values[$name] = parse_shorthand_int($value);
$this->save($name); $this->save($name);
} }
public function set_string($name, $value) { public function set_string(/*string*/ $name, $value) {
$this->values[$name] = $value; $this->values[$name] = $value;
$this->save($name); $this->save($name);
} }
public function set_bool($name, $value) { public function set_bool(/*string*/ $name, $value) {
$this->values[$name] = (($value == 'on' || $value === true) ? 'Y' : 'N'); $this->values[$name] = (($value == 'on' || $value === true) ? 'Y' : 'N');
$this->save($name); $this->save($name);
} }
public function set_array($name, $value) { public function set_array(/*string*/ $name, $value) {
assert(is_array($value)); assert(is_array($value));
$this->values[$name] = implode(",", $value); $this->values[$name] = implode(",", $value);
$this->save($name); $this->save($name);
} }
public function set_default_int($name, $value) { public function set_default_int(/*string*/ $name, $value) {
if(is_null($this->get($name))) { if(is_null($this->get($name))) {
$this->values[$name] = parse_shorthand_int($value); $this->values[$name] = parse_shorthand_int($value);
} }
} }
public function set_default_string($name, $value) { public function set_default_string(/*string*/ $name, $value) {
if(is_null($this->get($name))) { if(is_null($this->get($name))) {
$this->values[$name] = $value; $this->values[$name] = $value;
} }
} }
public function set_default_bool($name, $value) { public function set_default_bool(/*string*/ $name, $value) {
if(is_null($this->get($name))) { if(is_null($this->get($name))) {
$this->values[$name] = (($value == 'on' || $value === true) ? 'Y' : 'N'); $this->values[$name] = (($value == 'on' || $value === true) ? 'Y' : 'N');
} }
} }
public function set_default_array($name, $value) { public function set_default_array(/*string*/ $name, $value) {
assert(is_array($value)); assert(is_array($value));
if(is_null($this->get($name))) { if(is_null($this->get($name))) {
$this->values[$name] = implode(",", $value); $this->values[$name] = implode(",", $value);
} }
} }
public function get_int($name, $default=null) { public function get_int(/*string*/ $name, $default=null) {
return (int)($this->get($name, $default)); return (int)($this->get($name, $default));
} }
public function get_string($name, $default=null) { public function get_string(/*string*/ $name, $default=null) {
return $this->get($name, $default); return $this->get($name, $default);
} }
public function get_bool($name, $default=null) { public function get_bool(/*string*/ $name, $default=null) {
return undb_bool($this->get($name, $default)); return undb_bool($this->get($name, $default));
} }
public function get_array($name, $default=array()) { public function get_array(/*string*/ $name, $default=array()) {
return explode(",", $this->get($name, "")); return explode(",", $this->get($name, ""));
} }
private function get($name, $default=null) { private function get(/*string*/ $name, $default=null) {
if(isset($this->values[$name])) { if(isset($this->values[$name])) {
return $this->values[$name]; return $this->values[$name];
} }
@ -144,7 +144,7 @@ class StaticConfig extends BaseConfig {
} }
} }
public function save($name=null) { public function save(/*string*/ $name=null) {
// static config is static // static config is static
} }
} }
@ -167,7 +167,7 @@ class DatabaseConfig extends BaseConfig {
/* /*
* Load the config table from a database * Load the config table from a database
*/ */
public function DatabaseConfig($database) { public function DatabaseConfig(Database $database) {
$this->database = $database; $this->database = $database;
$cached = $this->database->cache->get("config"); $cached = $this->database->cache->get("config");
@ -186,10 +186,11 @@ class DatabaseConfig extends BaseConfig {
/* /*
* Save the current values as the new config table * Save the current values as the new config table
*/ */
public function save($name=null) { public function save(/*string*/ $name=null) {
if(is_null($name)) { if(is_null($name)) {
reset($this->values); // rewind the array to the first element
foreach($this->values as $name => $value) { foreach($this->values as $name => $value) {
$this->save($name); $this->save(/*string*/ $name);
} }
} }
else { else {

View File

@ -310,7 +310,7 @@ class Database {
} }
$matches = array(); $matches = array();
if(CACHE_DSN && preg_match("#(memcache|apc)://(.*)#", CACHE_DSN, $matches)) { if( defined("CACHE_DSN") && CACHE_DSN && preg_match("#(memcache|apc)://(.*)#", CACHE_DSN, $matches)) {
if($matches[1] == "memcache") { if($matches[1] == "memcache") {
$this->cache = new MemcacheCache($matches[2]); $this->cache = new MemcacheCache($matches[2]);
} }

View File

@ -39,6 +39,8 @@ class PageRequestEvent extends Event {
* Test if the requested path matches a given pattern. * Test if the requested path matches a given pattern.
* *
* If it matches, store the remaining path elements in $args * If it matches, store the remaining path elements in $args
*
* @retval bool
*/ */
public function page_matches(/*string*/ $name) { public function page_matches(/*string*/ $name) {
$parts = explode("/", $name); $parts = explode("/", $name);
@ -57,6 +59,11 @@ class PageRequestEvent extends Event {
return true; return true;
} }
/**
* Get the n th argument of the page request (if it exists.)
* @param $n integer
* @retval The argmuent (string) or NULL
*/
public function get_arg(/*int*/ $n) { public function get_arg(/*int*/ $n) {
$offset = $this->part_count + $n; $offset = $this->part_count + $n;
if($offset >= 0 && $offset < $this->arg_count) { if($offset >= 0 && $offset < $this->arg_count) {
@ -67,6 +74,10 @@ class PageRequestEvent extends Event {
} }
} }
/**
* Returns the number of arguments the page request has.
* @retval int
*/
public function count_args() { public function count_args() {
return (int)($this->arg_count - $this->part_count); return (int)($this->arg_count - $this->part_count);
} }

View File

@ -13,20 +13,14 @@
* $formatted_text = $tfe->formatted; * $formatted_text = $tfe->formatted;
* \endcode * \endcode
* *
* An extension is something which is capable of reacting to events. They * An extension is something which is capable of reacting to events.
* register themselves using the add_event_listener() function, after which
* events will be sent to the object's recieve_event() function.
*
* SimpleExtension subclasses are slightly different -- they are registered
* automatically, and events are sent to a named method, eg PageRequestEvent
* will be sent to onPageRequest()
* *
* *
* \page hello The Hello World Extension * \page hello The Hello World Extension
* *
* \code * \code
* // ext/hello/main.php * // ext/hello/main.php
* public class Hello extends SimpleExtension { * public class Hello extends Extension {
* public void onPageRequest(PageRequestEvent $event) { * public void onPageRequest(PageRequestEvent $event) {
* global $page, $user; * global $page, $user;
* $this->theme->display_hello($page, $user); * $this->theme->display_hello($page, $user);
@ -62,33 +56,17 @@
* *
*/ */
/**
* A generic extension class, for subclassing
*/
interface Extension {
public function receive_event(Event $event);
public function get_priority();
}
/** /**
* send_event(BlahEvent()) -> onBlah($event) * send_event(BlahEvent()) -> onBlah($event)
* *
* Also loads the theme object into $this->theme if available * Also loads the theme object into $this->theme if available
* *
* index.php will load all SimpleExtension subclasses, * The original concept came from Artanis's Extension extension
* so no need for register_extension(new Foo())
*
* Automatic registration is done with priority returned by get_priority()
*
* Hopefully this removes as much copy & paste code from the extension
* files as possible~
*
* The original concept came from Artanis's SimpleExtension extension
* --> http://github.com/Artanis/simple-extension/tree/master * --> http://github.com/Artanis/simple-extension/tree/master
* Then re-implemented by Shish after he broke the forum and couldn't * Then re-implemented by Shish after he broke the forum and couldn't
* find the thread where the original was posted >_< * find the thread where the original was posted >_<
*/ */
abstract class SimpleExtension implements Extension { abstract class Extension {
var $theme; var $theme;
var $_child; var $_child;
@ -100,15 +78,6 @@ abstract class SimpleExtension implements Extension {
if(is_null($this->theme)) $this->theme = get_theme_object($child, false); if(is_null($this->theme)) $this->theme = get_theme_object($child, false);
} }
public function receive_event(Event $event) {
$name = get_class($event);
// this is rather clever..
$name = "on".str_replace("Event", "", $name);
if(method_exists($this->_child, $name)) {
$this->_child->$name($event);
}
}
public function get_priority() { public function get_priority() {
return 50; return 50;
} }
@ -117,7 +86,7 @@ abstract class SimpleExtension implements Extension {
/** /**
* Several extensions have this in common, make a common API * Several extensions have this in common, make a common API
*/ */
abstract class FormatterExtension extends SimpleExtension { abstract class FormatterExtension extends Extension {
public function onTextFormatting(TextFormattingEvent $event) { public function onTextFormatting(TextFormattingEvent $event) {
$event->formatted = $this->format($event->formatted); $event->formatted = $this->format($event->formatted);
$event->stripped = $this->strip($event->stripped); $event->stripped = $this->strip($event->stripped);
@ -131,7 +100,7 @@ abstract class FormatterExtension extends SimpleExtension {
* This too is a common class of extension with many methods in common, * This too is a common class of extension with many methods in common,
* so we have a base class to extend from * so we have a base class to extend from
*/ */
abstract class DataHandlerExtension extends SimpleExtension { abstract class DataHandlerExtension extends Extension {
public function onDataUpload(DataUploadEvent $event) { public function onDataUpload(DataUploadEvent $event) {
if($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) { if($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) {
if(!move_upload_to_archive($event)) return; if(!move_upload_to_archive($event)) return;

View File

@ -106,8 +106,10 @@ class Image {
/** /**
* Search for an array of images * Search for an array of images
*
* @retval Array
*/ */
public static function find_images($start, $limit, $tags=array()) { public static function find_images(/*int*/ $start, /*int*/ $limit, $tags=array()) {
assert(is_numeric($start)); assert(is_numeric($start));
assert(is_numeric($limit)); assert(is_numeric($limit));
assert(is_array($tags)); assert(is_array($tags));
@ -119,7 +121,7 @@ class Image {
if($limit < 1) $limit = 1; if($limit < 1) $limit = 1;
if(SPEED_HAX) { if(SPEED_HAX) {
if($user->is_anonymous() and count($tags) > 3) { if(!$user->can("big_search") and count($tags) > 3) {
die("Anonymous users may only search for up to 3 tags at a time"); // FIXME: throw an exception? die("Anonymous users may only search for up to 3 tags at a time"); // FIXME: throw an exception?
} }
} }
@ -383,7 +385,7 @@ class Image {
/** /**
* Set the image's source URL * Set the image's source URL
*/ */
public function set_source($source) { public function set_source(/*string*/ $source) {
global $database; global $database;
if(empty($source)) $source = null; if(empty($source)) $source = null;
if($source != $this->source) { if($source != $this->source) {
@ -392,7 +394,10 @@ class Image {
} }
} }
/**
* Check if the image is locked.
* @retval bool
*/
public function is_locked() { public function is_locked() {
return ($this->locked === true || $this->locked == "Y" || $this->locked == "t"); return ($this->locked === true || $this->locked == "Y" || $this->locked == "t");
} }
@ -776,6 +781,8 @@ class Image {
} }
} }
reset($terms); // rewind to first element in array.
// turn each term into a specific type of querylet // turn each term into a specific type of querylet
foreach($terms as $term) { foreach($terms as $term) {
$negative = false; $negative = false;
@ -1008,8 +1015,15 @@ class Tag {
} }
} }
/**
* This function takes a list (array) of tags and changes any tags that have aliases
*
* @param $tags Array of tags
* @return Array of tags
*/
public static function resolve_list($tags) { public static function resolve_list($tags) {
$tags = Tag::explode($tags); $tags = Tag::explode($tags);
reset($tags); // rewind array to the first element.
$new = array(); $new = array();
foreach($tags as $tag) { foreach($tags as $tag) {
$new_set = explode(' ', Tag::resolve_alias($tag)); $new_set = explode(' ', Tag::resolve_alias($tag));

View File

@ -237,7 +237,7 @@ class Page {
protected function add_auto_html_headers() { protected function add_auto_html_headers() {
$data_href = get_base_href(); $data_href = get_base_href();
$this->add_html_header("<script>base_href = '$data_href';</script>"); $this->add_html_header("<script type='text/javascript'>base_href = '$data_href';</script>");
/* Attempt to cache the CSS & JavaScript files */ /* Attempt to cache the CSS & JavaScript files */
if ($this->add_cached_auto_html_headers() === FALSE) { if ($this->add_cached_auto_html_headers() === FALSE) {
@ -291,7 +291,11 @@ class Page {
{ {
global $config; global $config;
if (!$config->get_bool("autocache_css") && !$config->get_bool("autocache_js")) { // store local copy for speed.
$autocache_css = $config->get_bool("autocache_css");
$autocache_js = $config->get_bool("autocache_js");
if (!$autocache_css && !$autocache_js) {
return false; // caching disabled return false; // caching disabled
} }
@ -309,7 +313,7 @@ class Page {
$data_href = get_base_href(); $data_href = get_base_href();
/* ----- CSS Files ----- */ /* ----- CSS Files ----- */
if ($config->get_bool("autocache_css")) if ($autocache_css)
{ {
// First get all the CSS from the lib directory // First get all the CSS from the lib directory
$contents_from_lib = ''; $contents_from_lib = '';
@ -376,7 +380,7 @@ class Page {
/* ----- JavaScript Files ----- */ /* ----- JavaScript Files ----- */
if ($config->get_bool("autocache_js")) if ($autocache_js)
{ {
$data = ''; $data = '';
$js_files = glob("lib/*.js"); $js_files = glob("lib/*.js");
@ -394,7 +398,7 @@ class Page {
// Minify the JS if enabled. // Minify the JS if enabled.
if ($config->get_bool("autocache_min_js")){ if ($config->get_bool("autocache_min_js")){
// not supported yet. // not supported yet.
// TODO: add support for Minifying CSS files. // TODO: add support for Minifying JS files.
} }
// compute the MD5 sum of the concatenated JavaScript files // compute the MD5 sum of the concatenated JavaScript files

View File

@ -4,6 +4,7 @@ function _new_user($row) {
return new User($row); return new User($row);
} }
/** /**
* An object representing a row in the "users" table. * An object representing a row in the "users" table.
* *
@ -90,6 +91,77 @@ class User {
/* /*
* useful user object functions start here * useful user object functions start here
*/ */
public function can($ability) {
global $config;
// TODO: make this into an editable database table
$user_classes = array(
"anonymous" => array(
"change_setting" => False, # web-level settings, eg the config table
"override_config" => False, # sys-level config, eg config.php
"big_search" => False, # more than 3 tags (speed mode only)
"lock_image" => False,
"view_ip" => False, # view IP addresses associated with things
"change_password" => False,
"change_user_info" => False,
"delete_user" => False,
"delete_image" => False,
"delete_comment" => False,
"replace_image" => False,
"manage_extension_list" => False,
"manage_alias_list" => False,
"edit_tag" => $config->get_bool("tag_edit_anon"),
"edit_source" => $config->get_bool("source_edit_anon"),
"mass_tag_edit" => False,
),
"user" => array(
"change_setting" => False,
"override_config" => False,
"big_search" => True,
"lock_image" => False,
"view_ip" => False,
"change_password" => False,
"change_user_info" => False,
"delete_user" => False,
"delete_image" => False,
"delete_comment" => False,
"replace_image" => False,
"manage_extension_list" => False,
"manage_alias_list" => False,
"edit_tag" => True,
"edit_source" => True,
"mass_tag_edit" => False,
),
"admin" => array(
"change_setting" => True,
"override_config" => True,
"big_search" => True,
"lock_image" => True,
"view_ip" => True,
"change_password" => True,
"change_user_info" => True,
"delete_user" => True,
"delete_image" => True,
"delete_comment" => True,
"replace_image" => True,
"manage_extension_list" => True,
"manage_alias_list" => True,
"edit_tag" => True,
"edit_source" => True,
"mass_tag_edit" => True,
),
);
return $user_classes[$this->get_class()][$ability];
}
// FIXME: this should be a column in the users table
public function get_class() {
if($this->is_admin()) return "admin";
else if($this->is_logged_in()) return "user";
else return"anonymous";
}
/** /**
* Test if this user is anonymous (not logged in) * Test if this user is anonymous (not logged in)
@ -144,6 +216,7 @@ class User {
/** /**
* Get a snippet of HTML which will render the user's avatar, be that * Get a snippet of HTML which will render the user's avatar, be that
* a local file, a remote file, a gravatar, a something else, etc * a local file, a remote file, a gravatar, a something else, etc
* @retval String of HTML
*/ */
public function get_avatar_html() { public function get_avatar_html() {
// FIXME: configurable // FIXME: configurable
@ -170,6 +243,8 @@ class User {
* authtok = md5(sesskey, salt), presented to the user in web forms, to make sure that * authtok = md5(sesskey, salt), presented to the user in web forms, to make sure that
* the form was generated within the session. Salted and re-hashed so that * the form was generated within the session. Salted and re-hashed so that
* reading a web page from the user's cache doesn't give access to the session key * reading a web page from the user's cache doesn't give access to the session key
*
* @retval String containing auth token (MD5sum)
*/ */
public function get_auth_token() { public function get_auth_token() {
global $config; global $config;

View File

@ -190,12 +190,26 @@ function undb_bool($val) {
if($val === false || $val == 'N' || $val == 'n' || $val == 'F' || $val == 'f' || $val === 0) return false; if($val === false || $val == 'N' || $val == 'n' || $val == 'F' || $val == 'f' || $val === 0) return false;
} }
function startsWith($haystack, $needle) { /**
* Checks if a given string contains another at the beginning.
*
* @param $haystack String to examine.
* @param $needle String to look for.
* @retval bool
*/
function startsWith(/*string*/ $haystack, /*string*/ $needle) {
$length = strlen($needle); $length = strlen($needle);
return (substr($haystack, 0, $length) === $needle); return (substr($haystack, 0, $length) === $needle);
} }
function endsWith($haystack, $needle) { /**
* Checks if a given string contains another at the end.
*
* @param $haystack String to examine.
* @param $needle String to look for.
* @retval bool
*/
function endsWith(/*string*/ $haystack, /*string*/ $needle) {
$length = strlen($needle); $length = strlen($needle);
$start = $length * -1; //negative $start = $length * -1; //negative
return (substr($haystack, $start) === $needle); return (substr($haystack, $start) === $needle);
@ -621,6 +635,7 @@ function log_msg($section, $priority, $message) {
send_event(new LogEvent($section, $priority, $message)); send_event(new LogEvent($section, $priority, $message));
} }
// More shorthand ways of logging
function log_debug($section, $message) {log_msg($section, SCORE_LOG_DEBUG, $message);} function log_debug($section, $message) {log_msg($section, SCORE_LOG_DEBUG, $message);}
function log_info($section, $message) {log_msg($section, SCORE_LOG_INFO, $message);} function log_info($section, $message) {log_msg($section, SCORE_LOG_INFO, $message);}
function log_warning($section, $message) {log_msg($section, SCORE_LOG_WARNING, $message);} function log_warning($section, $message) {log_msg($section, SCORE_LOG_WARNING, $message);}
@ -824,6 +839,7 @@ $_event_count = 0;
function send_event(Event $event) { function send_event(Event $event) {
global $_event_listeners, $_event_count; global $_event_listeners, $_event_count;
if(!isset($_event_listeners[get_class($event)])) return; if(!isset($_event_listeners[get_class($event)])) return;
$method_name = "on".str_replace("Event", "", get_class($event));
ctx_log_start(get_class($event)); ctx_log_start(get_class($event));
// SHIT: http://bugs.php.net/bug.php?id=35106 // SHIT: http://bugs.php.net/bug.php?id=35106
@ -831,7 +847,7 @@ function send_event(Event $event) {
ksort($my_event_listeners); ksort($my_event_listeners);
foreach($my_event_listeners as $listener) { foreach($my_event_listeners as $listener) {
ctx_log_start(get_class($listener)); ctx_log_start(get_class($listener));
$listener->receive_event($event); $listener->$method_name($event);
ctx_log_endok(); ctx_log_endok();
} }
$_event_count++; $_event_count++;
@ -847,6 +863,13 @@ function send_event(Event $event) {
// string representation of a number, it's two numbers separated by a space. // string representation of a number, it's two numbers separated by a space.
// What the fuck were the PHP developers smoking. // What the fuck were the PHP developers smoking.
$_load_start = microtime(true); $_load_start = microtime(true);
/**
* Collects some debug information (execution time, memory usage, queries, etc)
* and formats it to stick in the footer of the page.
*
* @retval String of debug info to add to the page.
*/
function get_debug_info() { function get_debug_info() {
global $config, $_event_count, $database, $_execs, $_load_start; global $config, $_event_count, $database, $_execs, $_load_start;
@ -879,7 +902,7 @@ function get_debug_info() {
// print_obj ($object, $title, $return) // print_obj ($object, $title, $return)
function print_obj($object,$title="Object Information", $return=false) { function print_obj($object,$title="Object Information", $return=false) {
global $user; global $user;
if(DEBUG && isset($_GET['debug']) && $user->is_admin()) { if(DEBUG && isset($_GET['DEBUG']) && $user->can("override_config")) {
$pr = print_r($object,true); $pr = print_r($object,true);
$count = substr_count($pr,"\n")<=25?substr_count($pr,"\n"):25; $count = substr_count($pr,"\n")<=25?substr_count($pr,"\n"):25;
$pr = "<textarea rows='".$count."' cols='80'>$pr</textarea>"; $pr = "<textarea rows='".$count."' cols='80'>$pr</textarea>";
@ -1001,7 +1024,7 @@ function _load_extensions() {
if($rclass->isAbstract()) { if($rclass->isAbstract()) {
// don't do anything // don't do anything
} }
elseif(is_subclass_of($class, "SimpleExtension")) { elseif(is_subclass_of($class, "Extension")) {
$c = new $class(); $c = new $class();
$c->i_am($c); $c->i_am($c);
$my_events = array(); $my_events = array();
@ -1012,10 +1035,6 @@ function _load_extensions() {
} }
add_event_listener($c, $c->get_priority(), $my_events); add_event_listener($c, $c->get_priority(), $my_events);
} }
elseif(is_subclass_of($class, "Extension")) {
$c = new $class();
add_event_listener($c, $c->get_priority(), $all_events);
}
} }
if(COMPILE_ELS) { if(COMPILE_ELS) {
@ -1024,13 +1043,10 @@ function _load_extensions() {
foreach(get_declared_classes() as $class) { foreach(get_declared_classes() as $class) {
$rclass = new ReflectionClass($class); $rclass = new ReflectionClass($class);
if($rclass->isAbstract()) {} if($rclass->isAbstract()) {}
elseif(is_subclass_of($class, "SimpleExtension")) { elseif(is_subclass_of($class, "Extension")) {
$p .= "\$$class = new $class(); "; $p .= "\$$class = new $class(); ";
$p .= "\${$class}->i_am(\$$class);\n"; $p .= "\${$class}->i_am(\$$class);\n";
} }
elseif(is_subclass_of($class, "Extension")) {
$p .= "\$$class = new $class();\n";
}
} }
$p .= "\$_event_listeners = array(\n"; $p .= "\$_event_listeners = array(\n";
@ -1051,6 +1067,9 @@ function _load_extensions() {
ctx_log_endok(); ctx_log_endok();
} }
/**
* Used to display fatal errors to the web user.
*/
function _fatal_error(Exception $e) { function _fatal_error(Exception $e) {
$version = VERSION; $version = VERSION;
$message = $e->getMessage(); $message = $e->getMessage();

View File

@ -22,13 +22,13 @@ class AddAliasEvent extends Event {
class AddAliasException extends SCoreException {} class AddAliasException extends SCoreException {}
class AliasEditor extends SimpleExtension { class AliasEditor extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $database, $page, $user; global $config, $database, $page, $user;
if($event->page_matches("alias")) { if($event->page_matches("alias")) {
if($event->get_arg(0) == "add") { if($event->get_arg(0) == "add") {
if($user->is_admin()) { if($user->can("manage_alias_list")) {
if(isset($_POST['oldtag']) && isset($_POST['newtag'])) { if(isset($_POST['oldtag']) && isset($_POST['newtag'])) {
try { try {
$aae = new AddAliasEvent($_POST['oldtag'], $_POST['newtag']); $aae = new AddAliasEvent($_POST['oldtag'], $_POST['newtag']);
@ -43,7 +43,7 @@ class AliasEditor extends SimpleExtension {
} }
} }
else if($event->get_arg(0) == "remove") { else if($event->get_arg(0) == "remove") {
if($user->is_admin()) { if($user->can("manage_alias_list")) {
if(isset($_POST['oldtag'])) { if(isset($_POST['oldtag'])) {
$database->execute("DELETE FROM aliases WHERE oldtag=:oldtag", array("oldtag" => $_POST['oldtag'])); $database->execute("DELETE FROM aliases WHERE oldtag=:oldtag", array("oldtag" => $_POST['oldtag']));
log_info("alias_editor", "Deleted alias for ".$_POST['oldtag']); log_info("alias_editor", "Deleted alias for ".$_POST['oldtag']);
@ -74,7 +74,7 @@ class AliasEditor extends SimpleExtension {
$total_pages = ceil($database->get_one("SELECT COUNT(*) FROM aliases") / $alias_per_page); $total_pages = ceil($database->get_one("SELECT COUNT(*) FROM aliases") / $alias_per_page);
$this->theme->display_aliases($page, $alias, $user->is_admin(), $page_number + 1, $total_pages); $this->theme->display_aliases($alias, $page_number + 1, $total_pages);
} }
else if($event->get_arg(0) == "export") { else if($event->get_arg(0) == "export") {
$page->set_mode("data"); $page->set_mode("data");
@ -82,7 +82,7 @@ class AliasEditor extends SimpleExtension {
$page->set_data($this->get_alias_csv($database)); $page->set_data($this->get_alias_csv($database));
} }
else if($event->get_arg(0) == "import") { else if($event->get_arg(0) == "import") {
if($user->is_admin()) { if($user->can("manage_alias_list")) {
if(count($_FILES) > 0) { if(count($_FILES) > 0) {
$tmp = $_FILES['alias_file']['tmp_name']; $tmp = $_FILES['alias_file']['tmp_name'];
$contents = file_get_contents($tmp); $contents = file_get_contents($tmp);
@ -115,7 +115,7 @@ class AliasEditor extends SimpleExtension {
public function onUserBlockBuilding(UserBlockBuildingEvent $event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->can("manage_alias_list")) {
$event->add_link("Alias Editor", make_link("alias/list")); $event->add_link("Alias Editor", make_link("alias/list"));
} }
} }

View File

@ -5,10 +5,13 @@ class AliasEditorTheme extends Themelet {
* Show a page of aliases: * Show a page of aliases:
* *
* $aliases = an array of ($old_tag => $new_tag) * $aliases = an array of ($old_tag => $new_tag)
* $is_admin = whether things like "add new alias" should be shown * $can_manage = whether things like "add new alias" should be shown
*/ */
public function display_aliases(Page $page, $aliases, $is_admin, $pageNumber, $totalPages) { public function display_aliases($aliases, $pageNumber, $totalPages) {
if($is_admin) { global $page, $user;
$can_manage = $user->can("manage_alias_list");
if($can_manage) {
$action = "<th width='10%'>Action</th>"; $action = "<th width='10%'>Action</th>";
$add = " $add = "
<tr> <tr>
@ -33,7 +36,7 @@ class AliasEditorTheme extends Themelet {
$oe = ($n++ % 2 == 0) ? "even" : "odd"; $oe = ($n++ % 2 == 0) ? "even" : "odd";
$h_aliases .= "<tr class='$oe'><td>$h_old</td><td>$h_new</td>"; $h_aliases .= "<tr class='$oe'><td>$h_old</td><td>$h_new</td>";
if($is_admin) { if($can_manage) {
$h_aliases .= " $h_aliases .= "
<td> <td>
".make_form(make_link("alias/remove"))." ".make_form(make_link("alias/remove"))."
@ -70,7 +73,7 @@ class AliasEditorTheme extends Themelet {
$page->set_heading("Alias List"); $page->set_heading("Alias List");
$page->add_block(new NavBlock()); $page->add_block(new NavBlock());
$page->add_block(new Block("Aliases", $html)); $page->add_block(new Block("Aliases", $html));
if($is_admin) { if($can_manage) {
$page->add_block(new Block("Bulk Upload", $bulk_html, "main", 51)); $page->add_block(new Block("Bulk Upload", $bulk_html, "main", 51));
} }

View File

@ -60,7 +60,7 @@ class Comment {
} }
} }
class CommentList extends SimpleExtension { class CommentList extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config, $database; global $config, $database;
$config->set_default_bool('comment_anon', true); $config->set_default_bool('comment_anon', true);
@ -128,7 +128,7 @@ class CommentList extends SimpleExtension {
} }
} }
else if($event->get_arg(0) === "delete") { else if($event->get_arg(0) === "delete") {
if($user->is_admin()) { if($user->can("delete_comment")) {
// FIXME: post, not args // FIXME: post, not args
if($event->count_args() === 3) { if($event->count_args() === 3) {
send_event(new CommentDeletionEvent($event->get_arg(1))); send_event(new CommentDeletionEvent($event->get_arg(1)));

View File

@ -35,14 +35,17 @@ class CommentListTheme extends Themelet {
// parts for each image // parts for each image
$position = 10; $position = 10;
$comment_limit = $config->get_int("comment_list_count", 10);
$comment_captcha = $config->get_bool('comment_captcha');
foreach($images as $pair) { foreach($images as $pair) {
$image = $pair[0]; $image = $pair[0];
$comments = $pair[1]; $comments = $pair[1];
$thumb_html = $this->build_thumb_html($image); $thumb_html = $this->build_thumb_html($image);
$comment_html = ""; $comment_html = "";
$comment_limit = $config->get_int("comment_list_count", 10);
$comment_count = count($comments); $comment_count = count($comments);
if($comment_limit > 0 && $comment_count > $comment_limit) { if($comment_limit > 0 && $comment_count > $comment_limit) {
$hidden = $comment_count - $comment_limit; $hidden = $comment_count - $comment_limit;
@ -59,7 +62,7 @@ class CommentListTheme extends Themelet {
} }
} else { } else {
if ($can_post) { if ($can_post) {
if(!$config->get_bool('comment_captcha')) { if(!$comment_captcha) {
$comment_html .= $this->build_postbox($image->id); $comment_html .= $this->build_postbox($image->id);
} }
else { else {
@ -170,10 +173,9 @@ class CommentListTheme extends Themelet {
$hash = md5(strtolower($comment->owner_email)); $hash = md5(strtolower($comment->owner_email));
$avatar = "<img src=\"http://www.gravatar.com/avatar/$hash.jpg\"><br>"; $avatar = "<img src=\"http://www.gravatar.com/avatar/$hash.jpg\"><br>";
} }
$a = $user->is_admin();
$h_reply = " - <a href='javascript: replyTo($i_image_id, $i_comment_id)'>Reply</a>"; $h_reply = " - <a href='javascript: replyTo($i_image_id, $i_comment_id)'>Reply</a>";
$h_ip = $a ? "<br>$h_poster_ip" : ""; $h_ip = $user->can("view_ip") ? "<br>$h_poster_ip" : "";
$h_del = $a ? $h_del = $user->can("delete_comment") ?
' - <a onclick="return confirm(\'Delete comment by '.$h_name.':\\n'.$stripped_nonl.'\');" '. ' - <a onclick="return confirm(\'Delete comment by '.$h_name.':\\n'.$stripped_nonl.'\');" '.
'href="'.make_link('comment/delete/'.$i_comment_id.'/'.$i_image_id).'">Del</a>' : ''; 'href="'.make_link('comment/delete/'.$i_comment_id.'/'.$i_image_id).'">Del</a>' : '';
return ' return '

View File

@ -87,11 +87,11 @@ class ExtensionInfo {
} }
} }
class ExtManager extends SimpleExtension { class ExtManager extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;
if($event->page_matches("ext_manager")) { if($event->page_matches("ext_manager")) {
if($user->is_admin()) { if($user->can("manage_extension_list")) {
if($event->get_arg(0) == "set" && $user->check_auth_token()) { if($event->get_arg(0) == "set" && $user->check_auth_token()) {
if(is_writable("ext")) { if(is_writable("ext")) {
$this->set_things($_POST); $this->set_things($_POST);
@ -130,7 +130,7 @@ class ExtManager extends SimpleExtension {
public function onUserBlockBuilding(UserBlockBuildingEvent $event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->can("manage_extension_list")) {
$event->add_link("Extension Manager", make_link("ext_manager")); $event->add_link("Extension Manager", make_link("ext_manager"));
} }
else { else {

View File

@ -8,7 +8,7 @@
* Description: Shows an error message when the user views a page with no content * Description: Shows an error message when the user views a page with no content
*/ */
class Handle404 extends SimpleExtension { class Handle404 extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $page; global $page;
// hax. // hax.

View File

@ -129,7 +129,7 @@ class ParseLinkTemplateEvent extends Event {
/** /**
* A class to handle adding / getting / removing image files from the disk. * A class to handle adding / getting / removing image files from the disk.
*/ */
class ImageIO extends SimpleExtension { class ImageIO extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_int('thumb_width', 192); $config->set_default_int('thumb_width', 192);
@ -162,7 +162,7 @@ class ImageIO extends SimpleExtension {
} }
if($event->page_matches("image_admin/delete")) { if($event->page_matches("image_admin/delete")) {
global $page, $user; global $page, $user;
if($user->is_admin() && isset($_POST['image_id']) && $user->check_auth_token()) { if($user->can("delete_image") && isset($_POST['image_id']) && $user->check_auth_token()) {
$image = Image::by_id($_POST['image_id']); $image = Image::by_id($_POST['image_id']);
if($image) { if($image) {
send_event(new ImageDeletionEvent($image)); send_event(new ImageDeletionEvent($image));
@ -173,7 +173,7 @@ class ImageIO extends SimpleExtension {
} }
if($event->page_matches("image_admin/replace")) { if($event->page_matches("image_admin/replace")) {
global $page, $user; global $page, $user;
if($user->is_admin() && isset($_POST['image_id']) && $user->check_auth_token()) { if($user->can("replace_image") && isset($_POST['image_id']) && $user->check_auth_token()) {
$image = Image::by_id($_POST['image_id']); $image = Image::by_id($_POST['image_id']);
if($image) { if($image) {
$page->set_mode("redirect"); $page->set_mode("redirect");
@ -190,11 +190,11 @@ class ImageIO extends SimpleExtension {
global $user; global $user;
global $config; global $config;
if($user->is_admin()) { if($user->can("delete_image")) {
$event->add_part($this->theme->get_deleter_html($event->image->id)); $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... */ /* In the future, could perhaps allow users to replace images that they own as well... */
if ($user->is_admin() && $config->get_bool("upload_replace")) { if ($user->can("replace_image") && $config->get_bool("upload_replace")) {
$event->add_part($this->theme->get_replace_html($event->image->id)); $event->add_part($this->theme->get_replace_html($event->image->id));
} }
} }

View File

@ -128,7 +128,7 @@ class PostListBuildingEvent extends Event {
} }
} }
class Index extends SimpleExtension { class Index extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_int("index_width", 3); $config->set_default_int("index_width", 3);

View File

@ -7,7 +7,7 @@
* Description: Provides an interface for sending and receiving mail. * Description: Provides an interface for sending and receiving mail.
*/ */
class Mail extends SimpleExtension { class Mail extends Extension {
public function onSetupBuilding(SetupBuildingEvent $event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Mailing Options"); $sb = new SetupBlock("Mailing Options");
$sb->add_text_option("mail_sub", "<br>Subject prefix: "); $sb->add_text_option("mail_sub", "<br>Subject prefix: ");
@ -26,7 +26,7 @@ class Mail extends SimpleExtension {
$config->set_default_string("mail_fot", "<a href='".make_http(make_link())."'>".$config->get_string("site_title")."</a>"); $config->set_default_string("mail_fot", "<a href='".make_http(make_link())."'>".$config->get_string("site_title")."</a>");
} }
} }
class MailTest extends SimpleExtension { class MailTest extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
if($event->page_matches("mail/test")) { if($event->page_matches("mail/test")) {
global $page; global $page;

View File

@ -161,7 +161,7 @@ class SetupBlock extends Block {
} }
// }}} // }}}
class Setup extends SimpleExtension { class Setup extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_string("title", "Shimmie"); $config->set_default_string("title", "Shimmie");
@ -187,7 +187,7 @@ class Setup extends SimpleExtension {
} }
if($event->page_matches("setup")) { if($event->page_matches("setup")) {
if(!$user->is_admin()) { if(!$user->can("change_setting")) {
$this->theme->display_permission_denied($page); $this->theme->display_permission_denied($page);
} }
else { else {
@ -329,7 +329,7 @@ class Setup extends SimpleExtension {
public function onUserBlockBuilding(UserBlockBuildingEvent $event) { public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->can("change_setting")) {
$event->add_link("Board Config", make_link("setup")); $event->add_link("Board Config", make_link("setup"));
} }
} }

View File

@ -55,12 +55,12 @@ class LockSetEvent extends Event {
} }
} }
class TagEdit extends SimpleExtension { class TagEdit extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $user, $page; global $user, $page;
if($event->page_matches("tag_edit")) { if($event->page_matches("tag_edit")) {
if($event->get_arg(0) == "replace") { if($event->get_arg(0) == "replace") {
if($user->is_admin() && isset($_POST['search']) && isset($_POST['replace'])) { if($user->can("mass_tag_edit") && isset($_POST['search']) && isset($_POST['replace'])) {
$search = $_POST['search']; $search = $_POST['search'];
$replace = $_POST['replace']; $replace = $_POST['replace'];
$this->mass_tag_edit($search, $replace); $this->mass_tag_edit($search, $replace);
@ -82,7 +82,7 @@ class TagEdit extends SimpleExtension {
else { else {
$this->theme->display_error($page, "Error", "Anonymous tag editing is disabled"); $this->theme->display_error($page, "Error", "Anonymous tag editing is disabled");
} }
if($user->is_admin()) { if($user->can("lock_image")) {
$locked = isset($_POST['tag_edit__locked']) && $_POST['tag_edit__locked']=="on"; $locked = isset($_POST['tag_edit__locked']) && $_POST['tag_edit__locked']=="on";
send_event(new LockSetEvent($event->image, $locked)); send_event(new LockSetEvent($event->image, $locked));
} }
@ -90,21 +90,21 @@ class TagEdit extends SimpleExtension {
public function onTagSet(TagSetEvent $event) { public function onTagSet(TagSetEvent $event) {
global $user; global $user;
if($user->is_admin() || !$event->image->is_locked()) { if($user->can("edit_tag") || !$event->image->is_locked()) {
$event->image->set_tags($event->tags); $event->image->set_tags($event->tags);
} }
} }
public function onSourceSet(SourceSetEvent $event) { public function onSourceSet(SourceSetEvent $event) {
global $user; global $user;
if($user->is_admin() || !$event->image->is_locked()) { if($user->can("edit_tag") || !$event->image->is_locked()) {
$event->image->set_source($event->source); $event->image->set_source($event->source);
} }
} }
public function onLockSet(LockSetEvent $event) { public function onLockSet(LockSetEvent $event) {
global $user; global $user;
if($user->is_admin()) { if($user->can("lock_image")) {
$event->image->set_locked($event->locked); $event->image->set_locked($event->locked);
} }
} }
@ -130,7 +130,7 @@ class TagEdit extends SimpleExtension {
if($this->can_source($event->image)) { if($this->can_source($event->image)) {
$event->add_part($this->theme->get_source_editor_html($event->image), 41); $event->add_part($this->theme->get_source_editor_html($event->image), 41);
} }
if($user->is_admin()) { if($user->can("lock_image")) {
$event->add_part($this->theme->get_lock_editor_html($event->image), 42); $event->add_part($this->theme->get_lock_editor_html($event->image), 42);
} }
} }
@ -147,7 +147,7 @@ class TagEdit extends SimpleExtension {
global $config, $user; global $config, $user;
return ( return (
($config->get_bool("tag_edit_anon") || !$user->is_anonymous()) && ($config->get_bool("tag_edit_anon") || !$user->is_anonymous()) &&
($user->is_admin() || !$image->is_locked()) ($user->can("edit_tag") || !$image->is_locked())
); );
} }
@ -155,7 +155,7 @@ class TagEdit extends SimpleExtension {
global $config, $user; global $config, $user;
return ( return (
($config->get_bool("source_edit_anon") || !$user->is_anonymous()) && ($config->get_bool("source_edit_anon") || !$user->is_anonymous()) &&
($user->is_admin() || !$image->is_locked()) ($user->can("edit_source") || !$image->is_locked())
); );
} }

View File

@ -1,11 +1,12 @@
<?php <?php
/* /**
* Name: Tag List * Name: Tag List
* Author: Shish * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* Description: Show the tags in various ways * Description: Show the tags in various ways
*/ */
class TagList extends SimpleExtension { class TagList extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_int("tag_list_length", 15); $config->set_default_int("tag_list_length", 15);
@ -107,13 +108,18 @@ class TagList extends SimpleExtension {
return make_link("post/list/$u_tag/1"); return make_link("post/list/$u_tag/1");
} }
/**
* Get the minimum number of times a tag needs to be used
* in order to be considered in the tag list.
* @retval int
*/
private function get_tags_min() { private function get_tags_min() {
if(isset($_GET['mincount'])) { if(isset($_GET['mincount'])) {
return int_escape($_GET['mincount']); return int_escape($_GET['mincount']);
} }
else { else {
global $config; global $config;
return $config->get_int('tags_min'); return $config->get_int('tags_min'); // get the default.
} }
} }
@ -170,6 +176,8 @@ class TagList extends SimpleExtension {
$tags_min = $this->get_tags_min(); $tags_min = $this->get_tags_min();
$starts_with = $this->get_starts_with(); $starts_with = $this->get_starts_with();
// check if we have a cached version
$cache_key = "data/tag_cloud-" . md5("tc" . $tags_min . $starts_with) . ".html"; $cache_key = "data/tag_cloud-" . md5("tc" . $tags_min . $starts_with) . ".html";
if(file_exists($cache_key)) {return file_get_contents($cache_key);} if(file_exists($cache_key)) {return file_get_contents($cache_key);}
@ -205,6 +213,8 @@ class TagList extends SimpleExtension {
$tags_min = $this->get_tags_min(); $tags_min = $this->get_tags_min();
$starts_with = $this->get_starts_with(); $starts_with = $this->get_starts_with();
// check if we have a cached version
$cache_key = "data/tag_alpha-" . md5("ta" . $tags_min . $starts_with) . ".html"; $cache_key = "data/tag_alpha-" . md5("ta" . $tags_min . $starts_with) . ".html";
if(file_exists($cache_key)) {return file_get_contents($cache_key);} if(file_exists($cache_key)) {return file_get_contents($cache_key);}
@ -239,6 +249,8 @@ class TagList extends SimpleExtension {
global $database; global $database;
$tags_min = $this->get_tags_min(); $tags_min = $this->get_tags_min();
// check if we have a cached version
$cache_key = "data/tag_popul-" . md5("tp" . $tags_min) . ".html"; $cache_key = "data/tag_popul-" . md5("tp" . $tags_min) . ".html";
if(file_exists($cache_key)) {return file_get_contents($cache_key);} if(file_exists($cache_key)) {return file_get_contents($cache_key);}

View File

@ -70,22 +70,27 @@ class TagListTheme extends Themelet {
public function display_popular_block(Page $page, $tag_infos) { public function display_popular_block(Page $page, $tag_infos) {
global $config; global $config;
// store local copies for speed.
$info_link = $config->get_string('info_link');
$tag_list_num = $config->get_bool("tag_list_numbers");
$html = ""; $html = "";
$n = 0; $n = 0;
foreach($tag_infos as $row) { foreach($tag_infos as $row) {
$tag = $row['tag']; $tag = $row['tag'];
$h_tag = html_escape($tag); $h_tag = html_escape($tag);
$h_tag_no_underscores = str_replace("_", " ", $h_tag); $h_tag_no_underscores = str_replace("_", " ", $h_tag);
$count = $row['count']; $count = $row['count'];
if($n++) $html .= "\n<br/>"; if($n++) $html .= "\n<br/>";
if(!is_null($config->get_string('info_link'))) { if(!is_null($info_link)) {
$link = str_replace('$tag', $tag, $config->get_string('info_link')); $link = str_replace('$tag', $tag, $info_link);
$html .= " <a class='tag_info_link' href='$link'>?</a>"; $html .= ' <a class="tag_info_link" href="'.$link.'">?</a>';
} }
$link = $this->tag_link($row['tag']); $link = $this->tag_link($row['tag']);
$html .= " <a class='tag_name' href='$link'>$h_tag_no_underscores</a>"; $html .= ' <a class="tag_name" href="$link">'.$h_tag_no_underscores.'</a>';
if($config->get_bool("tag_list_numbers")) { if($tag_list_num) {
$html .= " <span class='tag_count'>$count</span>"; $html .= ' <span class="tag_count">'.$count.'</span>';
} }
} }
@ -103,19 +108,23 @@ class TagListTheme extends Themelet {
public function display_refine_block(Page $page, $tag_infos, $search) { public function display_refine_block(Page $page, $tag_infos, $search) {
global $config; global $config;
// store local copy for speed.
$info_link = $config->get_string('info_link');
$html = ""; $html = "";
$n = 0; $n = 0;
foreach($tag_infos as $row) { foreach($tag_infos as $row) {
$tag = $row['tag']; $tag = $row['tag'];
$h_tag = html_escape($tag); $h_tag = html_escape($tag);
$h_tag_no_underscores = str_replace("_", " ", $h_tag); $h_tag_no_underscores = str_replace("_", " ", $h_tag);
if($n++) $html .= "\n<br/>"; if($n++) $html .= "\n<br/>";
if(!is_null($config->get_string('info_link'))) { if(!is_null($info_link)) {
$link = str_replace('$tag', $tag, $config->get_string('info_link')); $link = str_replace('$tag', $tag, $info_link);
$html .= " <a class='tag_info_link' href='$link'>?</a>"; $html .= ' <a class="tag_info_link" href="'.$link.'">?</a>';
} }
$link = $this->tag_link($row['tag']); $link = $this->tag_link($row['tag']);
$html .= " <a class='tag_name' href='$link'>$h_tag_no_underscores</a>"; $html .= ' <a class="tag_name" href="'.$link.'">'.$h_tag_no_underscores.'</a>';
$html .= $this->ars($tag, $search); $html .= $this->ars($tag, $search);
} }

View File

@ -1,15 +1,18 @@
<?php <?php
/* /*
* Name: Database Upgrader * Name: Database Upgrader
* Author: Shish * Author: Shish <webmaster@shishnet.org>
* Link: http://code.shishnet.org/shimmie2/
* Description: Keeps things happy behind the scenes * Description: Keeps things happy behind the scenes
* Visibility: admin * Visibility: admin
*/ */
class Upgrade extends SimpleExtension { class Upgrade extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config, $database; global $config, $database;
if($config->get_bool("in_upgrade")) return;
if(!is_numeric($config->get_string("db_version"))) { if(!is_numeric($config->get_string("db_version"))) {
$config->set_int("db_version", 2); $config->set_int("db_version", 2);
} }
@ -18,28 +21,43 @@ class Upgrade extends SimpleExtension {
// cry :S // cry :S
} }
if($config->get_int("db_version") < 7) { // v7 is convert to innodb with adodb
/* // now done again as v9 with PDO
// mysql-adodb specific
if($database->engine->name == "mysql") {
$tables = $database->db->MetaTables();
foreach($tables as $table) {
log_info("upgrade", "converting $table to innodb");
$database->execute("ALTER TABLE $table TYPE=INNODB");
}
}
*/
$config->set_int("db_version", 7);
log_info("upgrade", "Database at version 7");
}
if($config->get_int("db_version") < 8) { if($config->get_int("db_version") < 8) {
// if this fails, don't try again // if this fails, don't try again
$config->set_bool("in_upgrade", true);
$config->set_int("db_version", 8); $config->set_int("db_version", 8);
$database->execute($database->engine->scoreql_to_sql( $database->execute($database->engine->scoreql_to_sql(
"ALTER TABLE images ADD COLUMN locked SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N" "ALTER TABLE images ADD COLUMN locked SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N"
)); ));
log_info("upgrade", "Database at version 8"); log_info("upgrade", "Database at version 8");
$config->set_bool("in_upgrade", false);
}
if($config->get_int("db_version") < 9) {
$config->set_bool("in_upgrade", true);
if($database->db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') {
$tables = $database->get_col("SHOW TABLES");
foreach($tables as $table) {
log_info("upgrade", "converting $table to innodb");
$database->execute("ALTER TABLE $table TYPE=INNODB");
}
}
$config->set_int("db_version", 9);
log_info("upgrade", "Database at version 9");
$config->set_bool("in_upgrade", false);
}
if($config->get_int("db_version") < 10) {
$config->set_bool("in_upgrade", true);
log_info("upgrade", "Adding foreign keys to images");
$database->Execute("ALTER TABLE images ADD CONSTRAINT foreign_images_owner_id FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT");
$config->set_int("db_version", 10);
log_info("upgrade", "Database at version 10");
$config->set_bool("in_upgrade", false);
} }
} }

View File

@ -4,22 +4,49 @@
var maxsze = (maxsze.match("(?:\.*[0-9])")) * 1024; //This assumes we are only working with MB. var maxsze = (maxsze.match("(?:\.*[0-9])")) * 1024; //This assumes we are only working with MB.
var toobig = "The file you are trying to upload is too big to upload!"; var toobig = "The file you are trying to upload is too big to upload!";
var notsup = "The file you are trying to upload is not supported!"; var notsup = "The file you are trying to upload is not supported!";
if (CA === 0 || CA > 2){ //Default
if (confirm("OK = Use Current tags.\nCancel = Use new tags.")==true){
}else{
var tag=prompt("Enter Tags","");
var chk=1; //This makes sure it doesn't use current tags.
}
}else if (CA === 1){ //Current Tags
}else if (CA === 2){ //New Tags
var tag=prompt("Enter Tags","");
var chk=1;
}
if (confirm("OK = Use Current tags.\nCancel = Use new tags.")==true){}else{var tag=prompt("Enter Tags","");var chk=1;}; // Danbooru | oreno.imouto | konachan | sankakucomplex
// Danbooru
if(document.getElementById("post_tags") !== null){ if(document.getElementById("post_tags") !== null){
if (typeof tag !=="ftp://ftp." && chk !==1){var tag=document.getElementById("post_tags").value;} if (typeof tag !=="ftp://ftp." && chk !==1){var tag=document.getElementById("post_tags").value;}
var rtg=document.getElementById("stats").innerHTML.match("<li>Rating: (.*)<\/li>")[1]; var srx="http://" + document.location.hostname + document.location.href.match("\/post\/show\/[0-9]+");
var srx="http://" + document.location.hostname + document.location.href.match("\/post\/show\/[0-9]+\/"); if(srx.search("oreno\\.imouto") >= 0 || srx.search("konachan\\.com") >= 0){
var rtg=document.getElementById("stats").innerHTML.match("<li>Rating: (.*) <span")[1];
}else{
var rtg=document.getElementById("stats").innerHTML.match("<li>Rating: (.*)<\/li>")[1];
}
if(tag.search(/\bflash\b/)===-1){ if(tag.search(/\bflash\b/)===-1){
var filesze=document.getElementById("stats").innerHTML.match("[0-9] \\(((?:\.*[0-9])) ([a-zA-Z]+)"); var hrs=document.getElementById("highres").href;
if(srx.search("oreno\\.imouto") >= 0 || srx.search("konachan\\.com") >= 0){ //oreno's theme seems to have moved the filesize
var filesze = document.getElementById("highres").innerHTML.match("[a-zA-Z0-9]+ \\(+([0-9]+\\.[0-9]+) ([a-zA-Z]+)");
}else{
var filesze=document.getElementById("stats").innerHTML.match("[0-9] \\(((?:\.*[0-9])) ([a-zA-Z]+)");
}
if(filesze[2] == "MB"){var filesze = filesze[1] * 1024;}else{var filesze = filesze[2].match("[0-9]+");} if(filesze[2] == "MB"){var filesze = filesze[1] * 1024;}else{var filesze = filesze[2].match("[0-9]+");}
if(supext.search(document.getElementById("highres").href.match("http\:\/\/.*\\.([a-z0-9]+)")[1]) !== -1){ if(supext.search(hrs.match("http\:\/\/.*\\.([a-z0-9]+)")[1]) !== -1){
if(filesze <= maxsze){ if(filesze <= maxsze){
location.href=ste+document.getElementById("highres").href+"&tags="+tag+"&rating="+rtg+"&source="+srx; if(srx.search("oreno\\.imouto") >= 0){
//this regex tends to be a bit picky with tags -_-;;
var hrs=hrs.match("(http\:\/\/[a-z0-9]+\.[a-z]+\.[a-z]\/[a-z0-9]+\/[a-z0-9]+)\/[a-z0-9A-Z%_-]+(\.[a-zA-Z0-9]+)");
var hrs=hrs[1]+hrs[2]; //this should bypass hotlink protection
}else if(srx.search("konachan\\.com") >= 0){
//konachan affixs konachan.com to the start of the tags, this requires different regex
var hrs=hrs.match("(http\:\/\/[a-z0-9]+\.[a-z]+\.[a-z]\/[a-z0-9]+\/[a-z0-9]+)\/[a-z0-9A-Z%_]+\.[a-zA-Z0-9%_-]+(\.[a-z0-9A-Z]+)")
var hrs=hrs[1]+hrs[2];
}
location.href=ste+hrs+"&tags="+tag+"&rating="+rtg+"&source="+srx;
}else{alert(toobig);} }else{alert(toobig);}
}else{alert(notsup);} }else{alert(notsup);}
}else{ }else{
@ -29,6 +56,7 @@ if(document.getElementById("post_tags") !== null){
} }
} }
/* Shimmie /* Shimmie
One problem with shimmie is each theme does not show the same info as other themes (I.E only the danbooru & lite themes show statistics)
Shimmie doesn't seem to have any way to grab tags via id unless you have the ability to edit tags. Shimmie doesn't seem to have any way to grab tags via id unless you have the ability to edit tags.
Have to go the round about way of checking the title for tags. Have to go the round about way of checking the title for tags.
This crazy way of checking "should" work with older releases though (Seems to work with 2009~ ver) */ This crazy way of checking "should" work with older releases though (Seems to work with 2009~ ver) */
@ -36,7 +64,6 @@ else if(document.getElementsByTagName("title")[0].innerHTML.search("Image [0-9.-
if (typeof tag !=="ftp://ftp." && chk !==1){var tag=document.getElementsByTagName("title")[0].innerHTML.match("Image [0-9.-]+\: (.*)")[1];} if (typeof tag !=="ftp://ftp." && chk !==1){var tag=document.getElementsByTagName("title")[0].innerHTML.match("Image [0-9.-]+\: (.*)")[1];}
//TODO: Make rating show in statistics. //TODO: Make rating show in statistics.
var srx="http://" + document.location.hostname + document.location.href.match("\/post\/view\/[0-9]+"); var srx="http://" + document.location.hostname + document.location.href.match("\/post\/view\/[0-9]+");
/*TODO: Figure out regex for shortening file link. I.E http://blah.net/_images/1234abcd/everysingletag.png > http://blah.net/_images/1234abcd.png*/
/*TODO: Make file size show on all themes (Only seems to show in lite/Danbooru themes.)*/ /*TODO: Make file size show on all themes (Only seems to show in lite/Danbooru themes.)*/
if(tag.search(/\bflash\b/)==-1){ if(tag.search(/\bflash\b/)==-1){
var img = document.getElementById("main_image").src; var img = document.getElementById("main_image").src;
@ -52,7 +79,6 @@ else if(document.getElementsByTagName("title")[0].innerHTML.search("Image [0-9.-
} }
// Gelbooru // Gelbooru
else if(document.getElementById("tags") !== null){ else if(document.getElementById("tags") !== null){
//Gelbooru has an annoying anti-hotlinking thing which doesn't seem to like the bookmarklet.
if (typeof tag !=="ftp://ftp." && chk !==1){var tag=document.getElementById("tags").value;} if (typeof tag !=="ftp://ftp." && chk !==1){var tag=document.getElementById("tags").value;}
var rtg=document.getElementById("stats").innerHTML.match("<li>Rating: (.*)<\/li>")[1]; var rtg=document.getElementById("stats").innerHTML.match("<li>Rating: (.*)<\/li>")[1];
//Can't seem to grab source due to url containing a & //Can't seem to grab source due to url containing a &
@ -61,6 +87,6 @@ else if(document.getElementById("tags") !== null){
//Since Gelbooru does not allow flash, no need to search for flash tag. //Since Gelbooru does not allow flash, no need to search for flash tag.
//Gelbooru doesn't show file size in statistics either... //Gelbooru doesn't show file size in statistics either...
if(supext.search(gmi.match("http\:\/\/.*\\.([a-z0-9]+)")[1]) !== -1){ if(supext.search(gmi.match("http\:\/\/.*\\.([a-z0-9]+)")[1]) !== -1){
location.href=ste+gmi+"&tags="+tag+"&rating="+rtg[1];//+"&source="+srx; location.href=ste+gmi+"&tags="+tag+"&rating="+rtg;//+"&source="+srx;
}else{alert(notsup);} }else{alert(notsup);}
} }

View File

@ -1,5 +1,5 @@
<?php <?php
/* /**
* Name: Uploader * Name: Uploader
* Author: Shish * Author: Shish
* Description: Allows people to upload files to the website * Description: Allows people to upload files to the website
@ -41,7 +41,7 @@ class UploadException extends SCoreException {}
* All files that are uploaded to the site are handled through this class. * All files that are uploaded to the site are handled through this class.
* This also includes transloaded files as well. * This also includes transloaded files as well.
*/ */
class Upload extends SimpleExtension { class Upload extends Extension {
// early, so it can stop the DataUploadEvent before any data handlers see it // early, so it can stop the DataUploadEvent before any data handlers see it
public function get_priority() {return 40;} public function get_priority() {return 40;}
@ -58,6 +58,8 @@ class Upload extends SimpleExtension {
$this->is_full = false; $this->is_full = false;
} }
else { else {
// TODO: This size limit should be configureable by the admin...
// currently set to 100 MB
$this->is_full = $free_num < 100*1024*1024; $this->is_full = $free_num < 100*1024*1024;
} }
@ -120,7 +122,7 @@ class Upload extends SimpleExtension {
} }
// check if the user is an administrator and can upload files. // check if the user is an administrator and can upload files.
if(!$user->is_admin()) { if(!$user->can("replace_image")) {
$this->theme->display_permission_denied($page); $this->theme->display_permission_denied($page);
} }
else { else {
@ -150,12 +152,14 @@ class Upload extends SimpleExtension {
$tags = ''; // Tags aren't changed when uploading. Set to null to stop PHP warnings. $tags = ''; // Tags aren't changed when uploading. Set to null to stop PHP warnings.
if(count($_FILES)) { if(count($_FILES)) {
reset($_FILES); // rewind to first element in array.
foreach($_FILES as $file) { foreach($_FILES as $file) {
$ok = $this->try_upload($file, $tags, $source, $image_id); $ok = $this->try_upload($file, $tags, $source, $image_id);
break; // leave the foreach loop. break; // leave the foreach loop.
} }
} }
else { else {
reset($_POST); // rewind to first element in array.
foreach($_POST as $name => $value) { foreach($_POST as $name => $value) {
if(substr($name, 0, 3) == "url" && strlen($value) > 0) { if(substr($name, 0, 3) == "url" && strlen($value) > 0) {
$ok = $this->try_transload($value, $tags, $source, $image_id); $ok = $this->try_transload($value, $tags, $source, $image_id);
@ -186,9 +190,11 @@ class Upload extends SimpleExtension {
$source = isset($_POST['source']) ? $_POST['source'] : null; $source = isset($_POST['source']) ? $_POST['source'] : null;
$ok = true; $ok = true;
foreach($_FILES as $file) { foreach($_FILES as $file) {
reset($_FILES); // rewind to first element in array.
$ok = $ok & $this->try_upload($file, $tags, $source); $ok = $ok & $this->try_upload($file, $tags, $source);
} }
foreach($_POST as $name => $value) { foreach($_POST as $name => $value) {
reset($_POST); // rewind to first element in array.
if(substr($name, 0, 3) == "url" && strlen($value) > 0) { if(substr($name, 0, 3) == "url" && strlen($value) > 0) {
$ok = $ok & $this->try_transload($value, $tags, $source); $ok = $ok & $this->try_transload($value, $tags, $source);
} }
@ -218,14 +224,28 @@ class Upload extends SimpleExtension {
} }
// }}} // }}}
// do things {{{ // do things {{{
/**
* Check if a given user can upload.
* @param $user The user to check.
* @retval bool
*/
private function can_upload(User $user) { private function can_upload(User $user) {
global $config; global $config;
return ($config->get_bool("upload_anon") || !$user->is_anonymous()); return ($config->get_bool("upload_anon") || !$user->is_anonymous());
} }
// Helper function based on the one from the online PHP Documentation /**
// which is licensed under Creative Commons Attribution 3.0 License * Returns a descriptive error message for the specified PHP error code.
// TODO: Make these messages user/admin editable *
* This is a helper function based on the one from the online PHP Documentation
* which is licensed under Creative Commons Attribution 3.0 License
*
* TODO: Make these messages user/admin editable
*
* @param $error_code PHP error code (int)
* @retval String
*/
private function upload_error_message($error_code) { private function upload_error_message($error_code) {
switch ($error_code) { switch ($error_code) {
case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_INI_SIZE:
@ -247,6 +267,10 @@ class Upload extends SimpleExtension {
} }
} }
/**
* Handle an upload.
* @retval bool TRUE on upload successful.
*/
private function try_upload($file, $tags, $source, $replace='') { private function try_upload($file, $tags, $source, $replace='') {
global $page; global $page;
global $config; global $config;
@ -293,6 +317,10 @@ class Upload extends SimpleExtension {
return $ok; return $ok;
} }
/**
* Handle an transload.
* @retval bool TRUE on transload successful.
*/
private function try_transload($url, $tags, $source, $replace='') { private function try_transload($url, $tags, $source, $replace='') {
global $page; global $page;
global $config; global $config;
@ -308,7 +336,7 @@ class Upload extends SimpleExtension {
} }
// Checks if user is admin > check if you want locked. // Checks if user is admin > check if you want locked.
if($user->is_admin() && !empty($_GET['locked'])){ if($user->can("lock_image") && !empty($_GET['locked'])){
$locked = bool_escape($_GET['locked']); $locked = bool_escape($_GET['locked']);
} }

View File

@ -18,6 +18,7 @@ class UploadTheme extends Themelet {
$upload_list = ""; $upload_list = "";
$upload_count = $config->get_int('upload_count'); $upload_count = $config->get_int('upload_count');
for($i=0; $i<$upload_count; $i++) for($i=0; $i<$upload_count; $i++)
{ {
$a=$i+1; $a=$i+1;
@ -53,7 +54,7 @@ class UploadTheme extends Themelet {
<a href='#' onclick='$js'>". <a href='#' onclick='$js'>".
"<img src='ext/upload/minus.png' /></a>"; "<img src='ext/upload/minus.png' /></a>";
if($a==$config->get_int('upload_count')){ if($a == $upload_count){
$upload_list .="<img id='wrapper' src='ext/upload/plus.png' />"; $upload_list .="<img id='wrapper' src='ext/upload/plus.png' />";
}else{ }else{
$js1 = 'javascript:$(function() { $js1 = 'javascript:$(function() {
@ -145,8 +146,7 @@ class UploadTheme extends Themelet {
{ {
/* Imageboard > Shimmie Bookmarklet /* Imageboard > Shimmie Bookmarklet
This is more or less, an upgraded version of the "Danbooru>Shimmie" bookmarklet. This is more or less, an upgraded version of the "Danbooru>Shimmie" bookmarklet.
At the moment this works with Shimmie & Danbooru. At the moment this is known to work with Shimmie/Danbooru/Gelbooru/oreno.imouto/konachan/sankakucomplex.
It would also work with Gelbooru but unless someone can figure out how to bypass their hotlinking..meh.
The bookmarklet is now also loaded via the .js file in this folder. The bookmarklet is now also loaded via the .js file in this folder.
*/ */
//Bookmarklet checks if shimmie supports ext. If not, won't upload to site/shows alert saying not supported. //Bookmarklet checks if shimmie supports ext. If not, won't upload to site/shows alert saying not supported.
@ -156,7 +156,8 @@ class UploadTheme extends Themelet {
if(file_exists("ext/handle_mp3")){$supported_ext .= " mp3";} if(file_exists("ext/handle_mp3")){$supported_ext .= " mp3";}
if(file_exists("ext/handle_svg")){$supported_ext .= " svg";} if(file_exists("ext/handle_svg")){$supported_ext .= " svg";}
$title = "Booru to " . $config->get_string('title'); $title = "Booru to " . $config->get_string('title');
$html .= '<p><a href="javascript:var ste=&quot;'. $link . $delimiter .'url=&quot;; var supext=&quot;'.$supported_ext.'&quot;; var maxsze=&quot;'.$max_kb.'&quot;; void(document.body.appendChild(document.createElement(&quot;script&quot;)).src=&quot;'.make_http(make_link("ext/upload/bookmarklet.js")).'&quot;)">'. //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;; var supext=&quot;'.$supported_ext.'&quot;; var maxsze=&quot;'.$max_kb.'&quot;; var CA=0; void(document.body.appendChild(document.createElement(&quot;script&quot;)).src=&quot;'.make_http(get_base_href())."/ext/upload/bookmarklet.js".'&quot;)">'.
$title . '</a> (Click when looking at an image page. Works on sites running Shimmie/Danbooru/Gelbooru. (This also grabs the tags/rating/source!))'; $title . '</a> (Click when looking at an image page. Works on sites running Shimmie/Danbooru/Gelbooru. (This also grabs the tags/rating/source!))';
} }

View File

@ -42,7 +42,7 @@ class UserCreationEvent extends Event {
class UserCreationException extends SCoreException {} class UserCreationException extends SCoreException {}
class UserPage extends SimpleExtension { class UserPage extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_bool("login_signup_enabled", true); $config->set_default_bool("login_signup_enabled", true);
@ -187,7 +187,7 @@ class UserPage extends SimpleExtension {
$this->theme->display_user_links($page, $user, $ubbe->parts); $this->theme->display_user_links($page, $user, $ubbe->parts);
} }
if( if(
($user->is_admin() || ($user->is_logged_in() && $user->id == $event->display_user->id)) && # admin or self-user ($user->can("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 ($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( $this->theme->display_ip_list(
@ -256,7 +256,7 @@ class UserPage extends SimpleExtension {
$user_id = int_escape($matches[2]); $user_id = int_escape($matches[2]);
$event->add_querylet(new Querylet("images.owner_id = $user_id")); $event->add_querylet(new Querylet("images.owner_id = $user_id"));
} }
else if($user->is_admin() && preg_match("/^(poster|user)_ip=([0-9\.]+)$/i", $event->term, $matches)) { else if($user->can("view_ip") && preg_match("/^(poster|user)_ip=([0-9\.]+)$/i", $event->term, $matches)) {
$user_ip = $matches[2]; // FIXME: ip_escape? $user_ip = $matches[2]; // FIXME: ip_escape?
$event->add_querylet(new Querylet("images.owner_ip = '$user_ip'")); $event->add_querylet(new Querylet("images.owner_ip = '$user_ip'"));
} }
@ -354,7 +354,7 @@ class UserPage extends SimpleExtension {
$duser = User::by_id($id); $duser = User::by_id($id);
if((!$user->is_admin()) && ($duser->name != $user->name)) { if((!$user->can("change_user_info")) && ($duser->name != $user->name)) {
$this->theme->display_error($page, "Error", $this->theme->display_error($page, "Error",
"You need to be an admin to change other people's passwords"); "You need to be an admin to change other people's passwords");
} }
@ -392,7 +392,7 @@ class UserPage extends SimpleExtension {
$duser = User::by_id($id); $duser = User::by_id($id);
if((!$user->is_admin()) && ($duser->name != $user->name)) { if((!$user->can("change_user_info")) && ($duser->name != $user->name)) {
$this->theme->display_error($page, "Error", $this->theme->display_error($page, "Error",
"You need to be an admin to change other people's addressess"); "You need to be an admin to change other people's addressess");
} }
@ -419,7 +419,7 @@ class UserPage extends SimpleExtension {
$page->set_title("Error"); $page->set_title("Error");
$page->set_heading("Error"); $page->set_heading("Error");
$page->add_block(new NavBlock()); $page->add_block(new NavBlock());
if(!$user->is_admin()) { if(!$user->can("change_user_info")) {
$page->add_block(new Block("Not Admin", "Only admins can edit accounts")); $page->add_block(new Block("Not Admin", "Only admins can edit accounts"));
} }
else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) { else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {
@ -479,7 +479,7 @@ class UserPage extends SimpleExtension {
$page->set_heading("Error"); $page->set_heading("Error");
$page->add_block(new NavBlock()); $page->add_block(new NavBlock());
if (!$user->is_admin()) { if (!$user->can("delete_user")) {
$page->add_block(new Block("Not Admin", "Only admins can delete accounts")); $page->add_block(new Block("Not Admin", "Only admins can delete accounts"));
} }
else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) { else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {
@ -510,7 +510,7 @@ class UserPage extends SimpleExtension {
$page->set_heading("Error"); $page->set_heading("Error");
$page->add_block(new NavBlock()); $page->add_block(new NavBlock());
if (!$user->is_admin()) { if (!$user->can("delete_user") || !$user->can("delete_image")) {
$page->add_block(new Block("Not Admin", "Only admins can delete accounts")); $page->add_block(new Block("Not Admin", "Only admins can delete accounts"));
} }
else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) { else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {

View File

@ -141,7 +141,7 @@ class UserPageTheme extends Themelet {
$page->add_block(new Block("Stats", join("<br>", $stats), "main", 0)); $page->add_block(new Block("Stats", join("<br>", $stats), "main", 0));
if(!$user->is_anonymous()) { if(!$user->is_anonymous()) {
if($user->id == $duser->id || $user->is_admin()) { if($user->id == $duser->id || $user->can("change_user_info")) {
$page->add_block(new Block("Options", $this->build_options($duser), "main", 20)); $page->add_block(new Block("Options", $this->build_options($duser), "main", 20));
} }
} }
@ -173,7 +173,7 @@ class UserPageTheme extends Themelet {
</form> </form>
"; ";
if($user->is_admin()) { if($user->can("change_user_info")) {
$i_user_id = int_escape($duser->id); $i_user_id = int_escape($duser->id);
$h_is_admin = $duser->is_admin() ? " checked" : ""; $h_is_admin = $duser->is_admin() ? " checked" : "";
$html .= " $html .= "

View File

@ -66,7 +66,7 @@ class ImageAdminBlockBuildingEvent extends Event {
} }
} }
class ViewImage extends SimpleExtension { class ViewImage extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;

View File

@ -90,7 +90,7 @@ class ViewImageTheme extends Themelet {
$html = ""; $html = "";
$html .= "<p>Uploaded by <a href='".make_link("user/$h_owner")."'>$h_owner</a> $h_date"; $html .= "<p>Uploaded by <a href='".make_link("user/$h_owner")."'>$h_owner</a> $h_date";
if($user->is_admin()) { if($user->can("view_ip")) {
$html .= " ($h_ip)"; $html .= " ($h_ip)";
} }
if(!is_null($image->source)) { if(!is_null($image->source)) {

View File

@ -1,7 +1,8 @@
<?php ob_start(); ?> <?php ob_start(); ?>
<html> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- <!--
- install.php (c) Shish 2007 - install.php (c) Shish et all. 2007-2012
- -
- Initialise the database, check that folder - Initialise the database, check that folder
- permissions are set properly, set an admin - permissions are set properly, set an admin
@ -12,17 +13,18 @@
--> -->
<head> <head>
<title>Shimmie Installation</title> <title>Shimmie Installation</title>
<style> <link rel="shortcut icon" href="/favicon.ico" />
BODY {background: #EEE;font-family: "Arial", sans-serif;font-size: 14px;} <style type="text/css">
H1, H3 {border: 1px solid black;background: #DDD;text-align: center;} BODY {background: #EEE;font-family: "Arial", sans-serif;font-size: 14px;}
H1 {margin-top: 0px;margin-bottom: 0px;padding: 2px;} H1, H3 {border: 1px solid black;background: #DDD;text-align: center;}
H3 {margin-top: 32px;padding: 1px;} H1 {margin-top: 0px;margin-bottom: 0px;padding: 2px;}
FORM {margin: 0px;} H3 {margin-top: 32px;padding: 1px;}
A {text-decoration: none;} FORM {margin: 0px;}
A:hover {text-decoration: underline;} A {text-decoration: none;}
#block {width: 512px; margin: auto; margin-top: 64px;} A:hover {text-decoration: underline;}
#iblock {width: 512px; margin: auto; margin-top: 16px;} #block {width: 512px; margin: auto; margin-top: 64px;}
TD INPUT {width: 350px;} #iblock {width: 512px; margin: auto; margin-top: 16px;}
TD INPUT {width: 350px;}
</style> </style>
</head> </head>
<body> <body>
@ -31,9 +33,10 @@ TD INPUT {width: 350px;}
<h1>Install Error</h1> <h1>Install Error</h1>
<p>Shimmie needs to be run via a web server with PHP support -- you <p>Shimmie needs to be run via a web server with PHP support -- you
appear to be either opening the file from your hard disk, or your appear to be either opening the file from your hard disk, or your
web server is mis-configured. web server is mis-configured.</p>
<p>If you've installed a web server on your desktop PC, you probably <p>If you've installed a web server on your desktop PC, you probably
want to visit <a href="http://localhost/">the local web server</a>. want to visit <a href="http://localhost/">the local web server</a>.<br/><br/>
</p>
</div> </div>
<div style="display: none;"> <div style="display: none;">
<PLAINTEXT> <PLAINTEXT>
@ -51,9 +54,32 @@ if(is_readable("config.php")) {
<div id="iblock"> <div id="iblock">
<h1>Shimmie Repair Console</h1> <h1>Shimmie Repair Console</h1>
<?php <?php
include "config.php";
if($_SESSION['dsn'] == DATABASE_DSN || $_POST['dsn'] == DATABASE_DSN) { /*
if($_POST['dsn']) {$_SESSION['dsn'] = $_POST['dsn'];} * Compute the path to the folder containing "install.php" and
* store it as the 'Shimmie Root' folder for later on.
*
* Example:
* __SHIMMIE_ROOT__ = '/var/www/shimmie2/'
*
*/
define('__SHIMMIE_ROOT__', trim( remove_trailing_slash( dirname(__FILE__) ) ) . '/' );
// Pull in necessary files
require_once __SHIMMIE_ROOT__."config.php"; // Load user/site specifics First
require_once __SHIMMIE_ROOT__."core/default_config.inc.php"; // Defaults for the rest.
require_once __SHIMMIE_ROOT__."core/util.inc.php";
require_once __SHIMMIE_ROOT__."core/database.class.php";
if (
( array_key_exists('dsn', $_SESSION) && $_SESSION['dsn'] === DATABASE_DSN ) ||
( array_key_exists('dsn', $_POST) && $_POST['dsn'] === DATABASE_DSN )
)
{
if ( array_key_exists('dsn', $_POST) && !empty($_POST['dsn']) )
{
$_SESSION['dsn'] = $_POST['dsn'];
}
if(empty($_GET["action"])) { if(empty($_GET["action"])) {
echo "<h3>Basic Checks</h3>"; echo "<h3>Basic Checks</h3>";
@ -76,15 +102,6 @@ if(is_readable("config.php")) {
</form> </form>
"; ";
*/ */
echo "<h3>Database quick fix for User deletion</h3>";
echo "just a database fix for those who instaled shimmie before 2012 january the 22rd.<br>";
echo "Note: some things needs to be done manually, to work properly.<br>";
echo "WARNING: ONLY PROCEEDS IF YOU KNOW WHAT YOU ARE DOING!";
echo "
<form action='install.php?action=Database_user_deletion_fix' method='POST'>
<input type='submit' value='go!'>
</form>
";
echo "<h3>Log Out</h3>"; echo "<h3>Log Out</h3>";
echo " echo "
@ -95,15 +112,12 @@ if(is_readable("config.php")) {
} }
else if($_GET["action"] == "logout") { else if($_GET["action"] == "logout") {
session_destroy(); session_destroy();
} echo "<h3>Logged Out</h3><p>You have been logged out.</p><a href='index.php'>Main Shimmie Page</a>";
else if($_GET["action"] == "Database_user_deletion_fix") {
Database_user_deletion_fix();
} }
} else { } else {
echo " echo "
<h3>Login</h3> <h3>Login</h3>
Enter the database DSN exactly as in config.php (ie, as originally <p>Enter the database DSN exactly as in config.php (ie, as originally installed) to access advanced recovery tools:</p>
installed) to access advanced recovery tools:
<form action='install.php' method='POST'> <form action='install.php' method='POST'>
<center> <center>
@ -118,13 +132,24 @@ if(is_readable("config.php")) {
echo "\t\t</div>"; echo "\t\t</div>";
exit; exit;
} }
require_once "core/compat.inc.php";
require_once "core/util.inc.php";
require_once "core/database.class.php";
do_install(); do_install();
// utilities {{{ // utilities {{{
/**
* Strips off any kind of slash at the end so as to normalise the path.
* @param string $path Path to normalise.
* @return string Path without trailing slash.
*/
function remove_trailing_slash($path) {
if ((substr($path, -1) === '/') || (substr($path, -1) === '\\')) {
return substr($path, 0, -1);
} else {
return $path;
}
}
function check_gd_version() { function check_gd_version() {
$gdversion = 0; $gdversion = 0;
@ -249,7 +274,7 @@ function begin() { // {{{
<h3>Help</h3> <h3>Help</h3>
<p>Please make sure the database you have chosen exists and is empty.<br> <p>Please make sure the database you have chosen exists and is empty.<br>
The username provided must have access to create tables within the database. The username provided must have access to create tables within the database.</p>
</div> </div>
EOD; EOD;
@ -315,7 +340,7 @@ function create_tables() { // {{{
CONSTRAINT foreign_image_tags_image_id FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, CONSTRAINT foreign_image_tags_image_id FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE,
CONSTRAINT foreign_image_tags_tag_id FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE CONSTRAINT foreign_image_tags_tag_id FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
"); ");
$db->execute("INSERT INTO config(name, value) VALUES('db_version', 8)"); $db->execute("INSERT INTO config(name, value) VALUES('db_version', 10)");
} }
catch (PDOException $e) catch (PDOException $e)
{ {
@ -354,11 +379,12 @@ function build_dirs() { // {{{
!file_exists("images") || !file_exists("thumbs") || !file_exists("data") || !file_exists("images") || !file_exists("thumbs") || !file_exists("data") ||
!is_writable("images") || !is_writable("thumbs") || !is_writable("data") !is_writable("images") || !is_writable("thumbs") || !is_writable("data")
) { ) {
print "Shimmie needs three folders in it's directory, 'images', 'thumbs', and 'data', print "<p>Shimmie needs three folders in it's directory, 'images', 'thumbs', and 'data',
and they need to be writable by the PHP user (if you see this error, and they need to be writable by the PHP user.</p>
if probably means the folders are owned by you, and they need to be <p>If you see this error, if probably means the folders are owned by you, and they need to be
writable by the web server). writable by the web server.</p>
<p>Once you have created these folders, hit 'refresh' to continue."; <p>PHP reports that it is currently running as user: ".$_ENV["USER"]." (". $_SERVER["USER"] .")</p>
<p>Once you have created these folders and/or changed the ownership of the shimmie folder, hit 'refresh' to continue.</p>";
exit; exit;
} }
} // }}} } // }}}
@ -387,49 +413,6 @@ EOD;
exit; exit;
} }
} // }}} } // }}}
function Database_user_deletion_fix() {
try {
require_once "core/database.class.php";
$db = new Database();
echo "Fixing user_favorites table....";
($db->Execute("ALTER TABLE user_favorites ENGINE=InnoDB;")) ? print_r("ok<br>") : print_r("failed<br>");
echo "adding Foreign key to user ids...";
($db->Execute("ALTER TABLE user_favorites ADD CONSTRAINT foreign_user_favorites_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;"))? print_r("ok<br>"):print_r("failed<br>");
echo "cleaning, the table from deleted image favorites...<br>";
$rows = $db->get_all("SELECT * FROM user_favorites WHERE image_id NOT IN ( SELECT id FROM images );");
foreach( $rows as $key => $value)
$db->Execute("DELETE FROM user_favorites WHERE image_id = :image_id;", array("image_id" => $value["image_id"]));
echo "adding forign key to image ids...";
($db->Execute("ALTER TABLE user_favorites ADD CONSTRAINT user_favorites_image_id FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE;"))? print_r("ok<br>"):print_r("failed<br>");
echo "adding foreign keys to private messages...";
($db->Execute("ALTER TABLE private_message
ADD CONSTRAINT foreign_private_message_from_id FOREIGN KEY (from_id) REFERENCES users(id) ON DELETE CASCADE,
ADD CONSTRAINT foreign_private_message_to_id FOREIGN KEY (to_id) REFERENCES users(id) ON DELETE CASCADE;")) ? print_r("ok<br>"):print_r("failed<br>");
echo "Just one more step...which you need to do manually:<br>";
echo "You need to go to your database and Delete the foreign key on the owner_id in the images table.<br><br>";
echo "<a href='http://www.justin-cook.com/wp/2006/05/09/how-to-remove-foreign-keys-in-mysql/'>How to remove foreign keys</a><br><br>";
echo "and finally execute this querry:<br><br>";
echo "ALTER TABLE images ADD CONSTRAINT foreign_images_owner_id FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT;<br><br>";
echo "if this is all sucesfull you are done!";
}
catch (PDOException $e)
{
// FIXME: Make the error message user friendly
exit($e->getMessage());
}
}
?> ?>
</body> </body>
</html> </html>

View File

@ -43,63 +43,10 @@ $(document).ready(function() {
var sections=get_sections(); var sections=get_sections();
for(var i=0;i<sections.length;i++) toggle(sections[i]); for(var i=0;i<sections.length;i++) toggle(sections[i]);
initGray("search_input", "Search"); $("#commentBox").DefaultValue("Comment");
initGray("commentBox", "Comment"); $("#tagBox").DefaultValue("tagme");
initGray("tagBox", "tagme");
// if we're going to show with JS, hide with JS first
pass_confirm = byId("pass_confirm");
if(pass_confirm) {
pass_confirm.style.display = "none";
}
}); });
function initGray(boxname, text) {
var box = byId(boxname);
if(!box) return;
var clr = function () {cleargray(box, text);};
var set = function () {setgray(box, text);};
addEvent(box, "focus", clr, false);
addEvent(box, "blur", set, false);
if(box.value == text) {
box.style.color = "#999";
box.style.textAlign = "center";
}
else {
box.style.color = "#000";
box.style.textAlign = "left";
}
}
function cleargray(box, text) {
if(box.value == text) {
box.value = "";
box.style.color = "#000";
box.style.textAlign = "left";
}
}
function setgray(box, text) {
if(box.value == "") {
box.style.textAlign = "center";
box.style.color = "gray";
box.value = text;
}
}
function showUp(elem) {
e = document.getElementById(elem)
if(!e) return;
e.style.display = "";
// alert(e.type+": "+e.value);
if(e.value.match(/^http|^ftp/)) {
e.type = "text";
alert("Box is web upload");
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* LibShish-JS * * LibShish-JS *
@ -119,6 +66,7 @@ function byId(id) {
} }
// used once in ext/setup/main
function getHTTPObject() { function getHTTPObject() {
if (window.XMLHttpRequest){ if (window.XMLHttpRequest){
return new XMLHttpRequest(); return new XMLHttpRequest();
@ -128,15 +76,6 @@ function getHTTPObject() {
} }
} }
function ajaxRequest(url, callback) {
var http = getHTTPObject();
http.open("GET", url, true);
http.onreadystatechange = function() {
if(http.readyState == 4) callback(http.responseText);
}
http.send(null);
}
/* get, set, and delete cookies */ /* get, set, and delete cookies */
function getCookie( name ) { function getCookie( name ) {

View File

@ -25,6 +25,10 @@ class CustomCommentListTheme extends CommentListTheme {
// parts for each image // parts for each image
$position = 10; $position = 10;
$comment_captcha = $config->get_bool('comment_captcha');
$comment_limit = $config->get_int("comment_list_count", 10);
foreach($images as $pair) { foreach($images as $pair) {
$image = $pair[0]; $image = $pair[0];
$comments = $pair[1]; $comments = $pair[1];
@ -42,7 +46,7 @@ class CustomCommentListTheme extends CommentListTheme {
$r = class_exists("Ratings") ? "<b>Rating</b> ".Ratings::rating_to_human($image->rating) : ""; $r = class_exists("Ratings") ? "<b>Rating</b> ".Ratings::rating_to_human($image->rating) : "";
$comment_html = "<b>Date</b> $p $s <b>User</b> $un $s $r<br><b>Tags</b> $t<p>&nbsp;"; $comment_html = "<b>Date</b> $p $s <b>User</b> $un $s $r<br><b>Tags</b> $t<p>&nbsp;";
$comment_limit = $config->get_int("comment_list_count", 10);
$comment_count = count($comments); $comment_count = count($comments);
if($comment_limit > 0 && $comment_count > $comment_limit) { if($comment_limit > 0 && $comment_count > $comment_limit) {
$hidden = $comment_count - $comment_limit; $hidden = $comment_count - $comment_limit;
@ -57,7 +61,7 @@ class CustomCommentListTheme extends CommentListTheme {
$comment_html .= $this->build_postbox($image->id); $comment_html .= $this->build_postbox($image->id);
} }
else { else {
if(!$config->get_bool('comment_captcha')) { if(!$comment_captcha) {
$comment_html .= $this->build_postbox($image->id); $comment_html .= $this->build_postbox($image->id);
} }
else { else {

View File

@ -38,7 +38,7 @@ class CustomViewImageTheme extends ViewImageTheme {
$html .= "<br>Source: <a href='$h_source'>link</a>"; $html .= "<br>Source: <a href='$h_source'>link</a>";
} }
if(!is_null($image->rating) && file_exists("ext/rating")) { if(file_exists("ext/rating")) {
if($image->rating == null || $image->rating == "u"){ if($image->rating == null || $image->rating == "u"){
$image->rating = "u"; $image->rating = "u";
} }

View File

@ -44,7 +44,7 @@ class CustomViewImageTheme extends ViewImageTheme {
$html .= "<br>Source: <a href='$h_source'>link</a>"; $html .= "<br>Source: <a href='$h_source'>link</a>";
} }
if(!is_null($image->rating) && file_exists("ext/rating")) { if(file_exists("ext/rating")) {
if($image->rating == null || $image->rating == "u"){ if($image->rating == null || $image->rating == "u"){
$image->rating = "u"; $image->rating = "u";
} }