Merge branch 'master' into speed_tweaks
This commit is contained in:
commit
d69fa6ae9d
52 changed files with 478 additions and 3723 deletions
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: Comment Word Ban
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: For stopping spam and other comment abuse
|
||||
* Documentation:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: Bulk Add
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: Bulk add server-side images
|
||||
* Documentation:
|
||||
|
@ -30,7 +31,9 @@ class BulkAdd extends SimpleExtension {
|
|||
$this->theme->display_admin_block();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the necessary DataUploadEvent for a given image and tags.
|
||||
*/
|
||||
private function add_image($tmpname, $filename, $tags) {
|
||||
assert(file_exists($tmpname));
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@ class ET extends SimpleExtension {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the information and return it in a keyed array.
|
||||
*/
|
||||
private function get_info() {
|
||||
global $config, $database;
|
||||
global $_event_listeners; // yay for using secret globals \o/
|
||||
|
|
|
@ -152,6 +152,17 @@ class Favorites extends SimpleExtension {
|
|||
");
|
||||
$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) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: Featured Image
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: Bring a specific image to the users' attentions
|
||||
* Documentation:
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* Name: Handle Flash
|
||||
* 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 {
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* Name: Handle SVG
|
||||
* 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 {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: IP Ban
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: Ban IP addresses
|
||||
* Documentation:
|
||||
|
@ -92,7 +93,7 @@ class IPBan extends SimpleExtension {
|
|||
public function onRemoveIPBan($event) {
|
||||
global $database;
|
||||
$database->Execute("DELETE FROM bans WHERE id = :id", array("id"=>$event->id));
|
||||
$database->cache->delete("ip_bans");
|
||||
$database->cache->delete("ip_bans_sorted");
|
||||
}
|
||||
|
||||
// installer {{{
|
||||
|
@ -261,7 +262,7 @@ class IPBan extends SimpleExtension {
|
|||
global $database;
|
||||
$sql = "INSERT INTO bans (ip, reason, end_timestamp, banner_id) VALUES (:ip, :reason, :end, :admin_id)";
|
||||
$database->Execute($sql, array("ip"=>$ip, "reason"=>$reason, "end"=>strtotime($end), "admin_id"=>$user->id));
|
||||
$database->cache->delete("ip_bans");
|
||||
$database->cache->delete("ip_bans_sorted");
|
||||
log_info("ipban", "'$user->name' has banned '$ip' because '$reason' until '$end'");
|
||||
}
|
||||
// }}}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?php
|
||||
/*
|
||||
* Name: Logging (Database)
|
||||
* Author: Shish
|
||||
* Description: Keep a record of SCore events
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* Description: Keep a record of SCore events (in the database).
|
||||
* Visibility: admin
|
||||
*/
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: News
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: Show a short amount of text in a block on the post list
|
||||
* Documentation:
|
||||
|
|
3408
contrib/notes/jquery.js
vendored
3408
contrib/notes/jquery.js
vendored
File diff suppressed because it is too large
Load diff
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: Image Scores (Numeric)
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: Allow users to score images
|
||||
* Documentation:
|
||||
|
|
|
@ -57,11 +57,24 @@ class PrivMsg extends SimpleExtension {
|
|||
subject VARCHAR(64) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
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);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: Random Image
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: Do things with a random image
|
||||
* Documentation:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: Image Ratings
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: Allow users to rate images "safe", "questionable" or "explicit"
|
||||
*/
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: Regen Thumb
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Description: Regenerate a thumbnail image
|
||||
* Documentation:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Name: Site Description
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* License: GPLv2
|
||||
* Visibility: admin
|
||||
* Description: A description for search engines
|
||||
|
|
|
@ -8,17 +8,17 @@ interface Config {
|
|||
* so that the next time a page is loaded it will use the new
|
||||
* configuration
|
||||
*/
|
||||
public function save($name=null);
|
||||
public function save(/*string*/ $name=null);
|
||||
|
||||
/** @name set_*
|
||||
* Set a configuration option to a new value, regardless
|
||||
* of what the value is at the moment
|
||||
*/
|
||||
//@{
|
||||
public function set_int($name, $value);
|
||||
public function set_string($name, $value);
|
||||
public function set_bool($name, $value);
|
||||
public function set_array($name, $value);
|
||||
public function set_int(/*string*/ $name, $value);
|
||||
public function set_string(/*string*/ $name, $value);
|
||||
public function set_bool(/*string*/ $name, $value);
|
||||
public function set_array(/*string*/ $name, $value);
|
||||
//@}
|
||||
|
||||
/** @name set_default_*
|
||||
|
@ -30,10 +30,10 @@ interface Config {
|
|||
* "default" paramater won't show up.
|
||||
*/
|
||||
//@{
|
||||
public function set_default_int($name, $value);
|
||||
public function set_default_string($name, $value);
|
||||
public function set_default_bool($name, $value);
|
||||
public function set_default_array($name, $value);
|
||||
public function set_default_int(/*string*/ $name, $value);
|
||||
public function set_default_string(/*string*/ $name, $value);
|
||||
public function set_default_bool(/*string*/ $name, $value);
|
||||
public function set_default_array(/*string*/ $name, $value);
|
||||
//@}
|
||||
|
||||
/** @name get_*
|
||||
|
@ -41,10 +41,10 @@ interface Config {
|
|||
* appropritate data type
|
||||
*/
|
||||
//@{
|
||||
public function get_int($name, $default=null);
|
||||
public function get_string($name, $default=null);
|
||||
public function get_bool($name, $default=null);
|
||||
public function get_array($name, $default=array());
|
||||
public function get_int(/*string*/ $name, $default=null);
|
||||
public function get_string(/*string*/ $name, $default=null);
|
||||
public function get_bool(/*string*/ $name, $default=null);
|
||||
public function get_array(/*string*/ $name, $default=array());
|
||||
//@}
|
||||
}
|
||||
|
||||
|
@ -56,60 +56,60 @@ interface Config {
|
|||
abstract class BaseConfig implements Config {
|
||||
var $values = array();
|
||||
|
||||
public function set_int($name, $value) {
|
||||
public function set_int(/*string*/ $name, $value) {
|
||||
$this->values[$name] = parse_shorthand_int($value);
|
||||
$this->save($name);
|
||||
}
|
||||
public function set_string($name, $value) {
|
||||
public function set_string(/*string*/ $name, $value) {
|
||||
$this->values[$name] = $value;
|
||||
$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->save($name);
|
||||
}
|
||||
public function set_array($name, $value) {
|
||||
public function set_array(/*string*/ $name, $value) {
|
||||
assert(is_array($value));
|
||||
$this->values[$name] = implode(",", $value);
|
||||
$this->save($name);
|
||||
}
|
||||
|
||||
public function set_default_int($name, $value) {
|
||||
public function set_default_int(/*string*/ $name, $value) {
|
||||
if(is_null($this->get($name))) {
|
||||
$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))) {
|
||||
$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))) {
|
||||
$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));
|
||||
if(is_null($this->get($name))) {
|
||||
$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));
|
||||
}
|
||||
public function get_string($name, $default=null) {
|
||||
public function get_string(/*string*/ $name, $default=null) {
|
||||
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));
|
||||
}
|
||||
public function get_array($name, $default=array()) {
|
||||
public function get_array(/*string*/ $name, $default=array()) {
|
||||
return explode(",", $this->get($name, ""));
|
||||
}
|
||||
|
||||
private function get($name, $default=null) {
|
||||
private function get(/*string*/ $name, $default=null) {
|
||||
if(isset($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
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ class DatabaseConfig extends BaseConfig {
|
|||
/*
|
||||
* Load the config table from a database
|
||||
*/
|
||||
public function DatabaseConfig($database) {
|
||||
public function DatabaseConfig(Database $database) {
|
||||
$this->database = $database;
|
||||
|
||||
$cached = $this->database->cache->get("config");
|
||||
|
@ -186,11 +186,11 @@ class DatabaseConfig extends BaseConfig {
|
|||
/*
|
||||
* Save the current values as the new config table
|
||||
*/
|
||||
public function save($name=null) {
|
||||
public function save(/*string*/ $name=null) {
|
||||
if(is_null($name)) {
|
||||
reset($this->values); // rewind the array to the first element
|
||||
foreach($this->values as $name => $value) {
|
||||
$this->save($name);
|
||||
$this->save(/*string*/ $name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -310,7 +310,7 @@ class Database {
|
|||
}
|
||||
|
||||
$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") {
|
||||
$this->cache = new MemcacheCache($matches[2]);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ class PageRequestEvent extends Event {
|
|||
* Test if the requested path matches a given pattern.
|
||||
*
|
||||
* If it matches, store the remaining path elements in $args
|
||||
*
|
||||
* @retval bool
|
||||
*/
|
||||
public function page_matches(/*string*/ $name) {
|
||||
$parts = explode("/", $name);
|
||||
|
@ -57,6 +59,11 @@ class PageRequestEvent extends Event {
|
|||
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) {
|
||||
$offset = $this->part_count + $n;
|
||||
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() {
|
||||
return (int)($this->arg_count - $this->part_count);
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ abstract class DataHandlerExtension extends SimpleExtension {
|
|||
}
|
||||
}
|
||||
|
||||
public function onThumnbnailGeneration(ThumbnailGenerationEvent $event) {
|
||||
public function onThumbnailGeneration(ThumbnailGenerationEvent $event) {
|
||||
if($this->supported_ext($event->type)) {
|
||||
if (method_exists($this, 'create_thumb_force') && $event->force == true) {
|
||||
$this->create_thumb_force($event->hash);
|
||||
|
|
|
@ -106,18 +106,26 @@ class Image {
|
|||
|
||||
/**
|
||||
* 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($limit));
|
||||
assert(is_array($tags));
|
||||
global $database;
|
||||
global $database, $user;
|
||||
|
||||
$images = array();
|
||||
|
||||
if($start < 0) $start = 0;
|
||||
if($limit < 1) $limit = 1;
|
||||
|
||||
if(SPEED_HAX) {
|
||||
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?
|
||||
}
|
||||
}
|
||||
|
||||
$querylet = Image::build_search_querylet($tags);
|
||||
$querylet->append(new Querylet("ORDER BY images.id DESC LIMIT :limit OFFSET :offset", array("limit"=>$limit, "offset"=>$start)));
|
||||
#var_dump($querylet->sql); var_dump($querylet->variables);
|
||||
|
@ -377,7 +385,7 @@ class Image {
|
|||
/**
|
||||
* Set the image's source URL
|
||||
*/
|
||||
public function set_source($source) {
|
||||
public function set_source(/*string*/ $source) {
|
||||
global $database;
|
||||
if(empty($source)) $source = null;
|
||||
if($source != $this->source) {
|
||||
|
@ -386,7 +394,10 @@ class Image {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the image is locked.
|
||||
* @retval bool
|
||||
*/
|
||||
public function is_locked() {
|
||||
return ($this->locked === true || $this->locked == "Y" || $this->locked == "t");
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ class Page {
|
|||
/** @private */
|
||||
var $mode = "page";
|
||||
/** @private */
|
||||
var $type = "text/html";
|
||||
var $type = "text/html; charset=utf-8";
|
||||
|
||||
/**
|
||||
* Set what this page should do; "page", "data", or "redirect".
|
||||
|
@ -196,8 +196,8 @@ class Page {
|
|||
|
||||
switch($this->mode) {
|
||||
case "page":
|
||||
header("Vary: Cookie, Accept-Encoding");
|
||||
if(CACHE_HTTP) {
|
||||
header("Vary: Cookie, Accept-Encoding");
|
||||
if($user->is_anonymous() && $_SERVER["REQUEST_METHOD"] == "GET") {
|
||||
header("Cache-control: public, max-age=600");
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 600) . ' GMT');
|
||||
|
@ -236,6 +236,8 @@ class Page {
|
|||
|
||||
protected function add_auto_html_headers() {
|
||||
$data_href = get_base_href();
|
||||
|
||||
$this->add_html_header("<script type='text/javascript'>base_href = '$data_href';</script>");
|
||||
|
||||
/* Attempt to cache the CSS & JavaScript files */
|
||||
if ($this->add_cached_auto_html_headers() === FALSE) {
|
||||
|
|
|
@ -4,6 +4,7 @@ function _new_user($row) {
|
|||
return new User($row);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An object representing a row in the "users" table.
|
||||
*
|
||||
|
@ -90,6 +91,77 @@ class User {
|
|||
/*
|
||||
* 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)
|
||||
|
@ -144,6 +216,7 @@ class User {
|
|||
/**
|
||||
* 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
|
||||
* @retval String of HTML
|
||||
*/
|
||||
public function get_avatar_html() {
|
||||
// FIXME: configurable
|
||||
|
@ -170,6 +243,8 @@ class User {
|
|||
* 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
|
||||
* 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() {
|
||||
global $config;
|
||||
|
|
|
@ -190,12 +190,26 @@ function undb_bool($val) {
|
|||
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);
|
||||
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);
|
||||
$start = $length * -1; //negative
|
||||
return (substr($haystack, $start) === $needle);
|
||||
|
@ -621,6 +635,7 @@ function log_msg($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_info($section, $message) {log_msg($section, SCORE_LOG_INFO, $message);}
|
||||
function log_warning($section, $message) {log_msg($section, SCORE_LOG_WARNING, $message);}
|
||||
|
@ -847,6 +862,13 @@ function send_event(Event $event) {
|
|||
// string representation of a number, it's two numbers separated by a space.
|
||||
// What the fuck were the PHP developers smoking.
|
||||
$_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() {
|
||||
global $config, $_event_count, $database, $_execs, $_load_start;
|
||||
|
||||
|
@ -879,7 +901,7 @@ function get_debug_info() {
|
|||
// print_obj ($object, $title, $return)
|
||||
function print_obj($object,$title="Object Information", $return=false) {
|
||||
global $user;
|
||||
if(DEBUG && isset($_GET['debug']) && $user->is_admin()) {
|
||||
if(DEBUG && isset($_GET['DEBUG']) && $user->can("override_config")) {
|
||||
$pr = print_r($object,true);
|
||||
$count = substr_count($pr,"\n")<=25?substr_count($pr,"\n"):25;
|
||||
$pr = "<textarea rows='".$count."' cols='80'>$pr</textarea>";
|
||||
|
@ -1051,6 +1073,9 @@ function _load_extensions() {
|
|||
ctx_log_endok();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to display fatal errors to the web user.
|
||||
*/
|
||||
function _fatal_error(Exception $e) {
|
||||
$version = VERSION;
|
||||
$message = $e->getMessage();
|
||||
|
|
|
@ -28,7 +28,7 @@ class AliasEditor extends SimpleExtension {
|
|||
|
||||
if($event->page_matches("alias")) {
|
||||
if($event->get_arg(0) == "add") {
|
||||
if($user->is_admin()) {
|
||||
if($user->can("manage_alias_list")) {
|
||||
if(isset($_POST['oldtag']) && isset($_POST['newtag'])) {
|
||||
try {
|
||||
$aae = new AddAliasEvent($_POST['oldtag'], $_POST['newtag']);
|
||||
|
@ -43,7 +43,7 @@ class AliasEditor extends SimpleExtension {
|
|||
}
|
||||
}
|
||||
else if($event->get_arg(0) == "remove") {
|
||||
if($user->is_admin()) {
|
||||
if($user->can("manage_alias_list")) {
|
||||
if(isset($_POST['oldtag'])) {
|
||||
$database->execute("DELETE FROM aliases WHERE oldtag=:oldtag", array("oldtag" => $_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);
|
||||
|
||||
$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") {
|
||||
$page->set_mode("data");
|
||||
|
@ -82,7 +82,7 @@ class AliasEditor extends SimpleExtension {
|
|||
$page->set_data($this->get_alias_csv($database));
|
||||
}
|
||||
else if($event->get_arg(0) == "import") {
|
||||
if($user->is_admin()) {
|
||||
if($user->can("manage_alias_list")) {
|
||||
if(count($_FILES) > 0) {
|
||||
$tmp = $_FILES['alias_file']['tmp_name'];
|
||||
$contents = file_get_contents($tmp);
|
||||
|
@ -115,7 +115,7 @@ class AliasEditor extends SimpleExtension {
|
|||
|
||||
public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
|
||||
global $user;
|
||||
if($user->is_admin()) {
|
||||
if($user->can("manage_alias_list")) {
|
||||
$event->add_link("Alias Editor", make_link("alias/list"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,13 @@ class AliasEditorTheme extends Themelet {
|
|||
* Show a page of aliases:
|
||||
*
|
||||
* $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) {
|
||||
if($is_admin) {
|
||||
public function display_aliases($aliases, $pageNumber, $totalPages) {
|
||||
global $page, $user;
|
||||
|
||||
$can_manage = $user->can("manage_alias_list");
|
||||
if($can_manage) {
|
||||
$action = "<th width='10%'>Action</th>";
|
||||
$add = "
|
||||
<tr>
|
||||
|
@ -33,7 +36,7 @@ class AliasEditorTheme extends Themelet {
|
|||
$oe = ($n++ % 2 == 0) ? "even" : "odd";
|
||||
|
||||
$h_aliases .= "<tr class='$oe'><td>$h_old</td><td>$h_new</td>";
|
||||
if($is_admin) {
|
||||
if($can_manage) {
|
||||
$h_aliases .= "
|
||||
<td>
|
||||
".make_form(make_link("alias/remove"))."
|
||||
|
@ -70,7 +73,7 @@ class AliasEditorTheme extends Themelet {
|
|||
$page->set_heading("Alias List");
|
||||
$page->add_block(new NavBlock());
|
||||
$page->add_block(new Block("Aliases", $html));
|
||||
if($is_admin) {
|
||||
if($can_manage) {
|
||||
$page->add_block(new Block("Bulk Upload", $bulk_html, "main", 51));
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ class BBCode extends FormatterExtension {
|
|||
$text = preg_replace("/\[i\](.*?)\[\/i\]/s", "<i>\\1</i>", $text);
|
||||
$text = preg_replace("/\[u\](.*?)\[\/u\]/s", "<u>\\1</u>", $text);
|
||||
$text = preg_replace("/\[s\](.*?)\[\/s\]/s", "<s>\\1</s>", $text);
|
||||
$text = preg_replace("/>>(\d+)/s", "<a href=\"".make_link("post/view/\\1")."\">>>\\1</a>", $text);
|
||||
$text = preg_replace("/>>(\d+)(#\d+)?/s", "<a href=\"".make_link("post/view/\\1\\2")."\">>>\\1\\2</a>", $text);
|
||||
$text = preg_replace("/(^|\s)#(\d+)/s", "\\1<a href=\"#\\2\">#\\2</a>", $text);
|
||||
$text = preg_replace("/>>([^\d].+)/", "<blockquote><small>\\1</small></blockquote>", $text);
|
||||
$text = preg_replace("/\[url=((?:https?|ftp|irc|mailto):\/\/.*?)\](.*?)\[\/url\]/s", "<a href=\"\\1\">\\2</a>", $text);
|
||||
$text = preg_replace("/\[url\]((?:https?|ftp|irc|mailto):\/\/.*?)\[\/url\]/s", "<a href=\"\\1\">\\1</a>", $text);
|
||||
|
|
|
@ -128,7 +128,7 @@ class CommentList extends SimpleExtension {
|
|||
}
|
||||
}
|
||||
else if($event->get_arg(0) === "delete") {
|
||||
if($user->is_admin()) {
|
||||
if($user->can("delete_comment")) {
|
||||
// FIXME: post, not args
|
||||
if($event->count_args() === 3) {
|
||||
send_event(new CommentDeletionEvent($event->get_arg(1)));
|
||||
|
@ -173,7 +173,6 @@ class CommentList extends SimpleExtension {
|
|||
$h_comment_rate = sprintf("%.1f", ($i_comment_count / $i_days_old));
|
||||
$event->add_stats("Comments made: $i_comment_count, $h_comment_rate per day");
|
||||
|
||||
global $user;
|
||||
$recent = $this->get_user_recent_comments($event->display_user->id, 10);
|
||||
$this->theme->display_user_comments($recent);
|
||||
}
|
||||
|
|
|
@ -143,46 +143,53 @@ class CommentListTheme extends Themelet {
|
|||
$h_name = html_escape($comment->owner_name);
|
||||
$h_poster_ip = html_escape($comment->poster_ip);
|
||||
$h_timestamp = autodate($comment->posted);
|
||||
$h_comment = ($trim ? substr($tfe->stripped, 0, 50)."..." : $tfe->formatted);
|
||||
$h_comment = ($trim ? substr($tfe->stripped, 0, 50) . (strlen($tfe->stripped) > 50 ? "..." : "") : $tfe->formatted);
|
||||
$i_comment_id = int_escape($comment->comment_id);
|
||||
$i_image_id = int_escape($comment->image_id);
|
||||
|
||||
$anoncode = "";
|
||||
if($h_name == "Anonymous" && $this->anon_id >= 0) {
|
||||
$anoncode = '<sup>'.$this->anon_id.'</sup>';
|
||||
$this->anon_id++;
|
||||
if($h_name == "Anonymous") {
|
||||
$anoncode = "";
|
||||
if($this->anon_id >= 0) {
|
||||
$anoncode = '<sup>'.$this->anon_id.'</sup>';
|
||||
$this->anon_id++;
|
||||
}
|
||||
$h_userlink = $h_name . $anoncode;
|
||||
}
|
||||
else {
|
||||
$h_userlink = '<a href="'.make_link('user/'.$h_name).'">'.$h_name.'</a>';
|
||||
}
|
||||
$h_userlink = '<a href="'.make_link('user/'.$h_name).'">'.$h_name.'</a>'.$anoncode;
|
||||
$stripped_nonl = str_replace("\n", "\\n", substr($tfe->stripped, 0, 50));
|
||||
$stripped_nonl = str_replace("\r", "\\r", $stripped_nonl);
|
||||
$h_dellink = $user->is_admin() ?
|
||||
'<br>('.$h_poster_ip.', '.$h_timestamp.', <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>)' : '';
|
||||
|
||||
if($trim) {
|
||||
return '
|
||||
'.$h_userlink.': '.$h_comment.'
|
||||
<a href="'.make_link('post/view/'.$i_image_id).'">>>></a>
|
||||
'.$h_dellink.'
|
||||
';
|
||||
}
|
||||
else {
|
||||
//$avatar = "";
|
||||
//if(!empty($comment->owner->email)) {
|
||||
// $hash = md5(strtolower($comment->owner->email));
|
||||
// $avatar = "<img src=\"http://www.gravatar.com/avatar/$hash.jpg\"><br>";
|
||||
//}
|
||||
$oe = ($this->comments_shown++ % 2 == 0) ? "even" : "odd";
|
||||
$avatar = "";
|
||||
if(!empty($comment->owner_email)) {
|
||||
$hash = md5(strtolower($comment->owner_email));
|
||||
$avatar = "<img src=\"http://www.gravatar.com/avatar/$hash.jpg\"><br>";
|
||||
}
|
||||
$h_reply = " - <a href='javascript: replyTo($i_image_id, $i_comment_id)'>Reply</a>";
|
||||
$h_ip = $user->can("view_ip") ? "<br>$h_poster_ip" : "";
|
||||
$h_del = $user->can("delete_comment") ?
|
||||
' - <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>' : '';
|
||||
return '
|
||||
<a name="'.$i_comment_id.'"></a>
|
||||
<div class="'.$oe.' comment">
|
||||
<!--<span class="timeago" style="float: right;">'.$h_timestamp.'</span>-->
|
||||
'.$h_userlink.': '.$h_comment.'
|
||||
'.$h_dellink.'
|
||||
<div class="comment">
|
||||
<div class="info">
|
||||
'.$avatar.'
|
||||
'.$h_timestamp.$h_reply.$h_ip.$h_del.'
|
||||
</div>
|
||||
'.$h_userlink.': '.$h_comment.'
|
||||
</div>
|
||||
';
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
protected function build_postbox($image_id) {
|
||||
|
@ -196,7 +203,7 @@ class CommentListTheme extends Themelet {
|
|||
'.make_form(make_link("comment/add")).'
|
||||
<input type="hidden" name="image_id" value="'.$i_image_id.'" />
|
||||
<input type="hidden" name="hash" value="'.$hash.'" />
|
||||
<textarea name="comment" rows="5" cols="50"></textarea>
|
||||
<textarea id="comment_on_'.$i_image_id.'" name="comment" rows="5" cols="50"></textarea>
|
||||
'.$captcha.'
|
||||
<br><input type="submit" value="Post Comment" />
|
||||
</form>
|
||||
|
|
|
@ -91,7 +91,7 @@ class ExtManager extends SimpleExtension {
|
|||
public function onPageRequest(PageRequestEvent $event) {
|
||||
global $page, $user;
|
||||
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(is_writable("ext")) {
|
||||
$this->set_things($_POST);
|
||||
|
@ -130,7 +130,7 @@ class ExtManager extends SimpleExtension {
|
|||
|
||||
public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
|
||||
global $user;
|
||||
if($user->is_admin()) {
|
||||
if($user->can("manage_extension_list")) {
|
||||
$event->add_link("Extension Manager", make_link("ext_manager"));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -162,7 +162,7 @@ class ImageIO extends SimpleExtension {
|
|||
}
|
||||
if($event->page_matches("image_admin/delete")) {
|
||||
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']);
|
||||
if($image) {
|
||||
send_event(new ImageDeletionEvent($image));
|
||||
|
@ -173,7 +173,7 @@ class ImageIO extends SimpleExtension {
|
|||
}
|
||||
if($event->page_matches("image_admin/replace")) {
|
||||
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']);
|
||||
if($image) {
|
||||
$page->set_mode("redirect");
|
||||
|
@ -190,11 +190,11 @@ class ImageIO extends SimpleExtension {
|
|||
global $user;
|
||||
global $config;
|
||||
|
||||
if($user->is_admin()) {
|
||||
if($user->can("delete_image")) {
|
||||
$event->add_part($this->theme->get_deleter_html($event->image->id));
|
||||
}
|
||||
/* In the future, could perhaps allow users to replace images that they own as well... */
|
||||
if ($user->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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,23 +79,8 @@ and of course start organising your images :-)
|
|||
$h_search_string = html_escape(implode(" ", $search_terms));
|
||||
$h_search_link = make_link();
|
||||
$h_search = "
|
||||
<script type='text/javascript'><!--
|
||||
$(document).ready(function() {
|
||||
$('#search_input').DefaultValue('Search');
|
||||
$('#search_input').autocomplete('".make_link("api/internal/tag_list/complete")."', {
|
||||
width: 320,
|
||||
max: 15,
|
||||
highlight: false,
|
||||
multiple: true,
|
||||
multipleSeparator: ' ',
|
||||
scroll: true,
|
||||
scrollHeight: 300,
|
||||
selectFirst: false
|
||||
});
|
||||
});
|
||||
//--></script>
|
||||
<p><form action='$h_search_link' method='GET'>
|
||||
<input id='search_input' name='search' type='text'
|
||||
<input class='search_input' id='search_input' name='search' type='text'
|
||||
value='$h_search_string' autocomplete='off' />
|
||||
<input type='hidden' name='q' value='/post/list'>
|
||||
<input type='submit' value='Find' style='display: none;' />
|
||||
|
|
|
@ -187,7 +187,7 @@ class Setup extends SimpleExtension {
|
|||
}
|
||||
|
||||
if($event->page_matches("setup")) {
|
||||
if(!$user->is_admin()) {
|
||||
if(!$user->can("change_setting")) {
|
||||
$this->theme->display_permission_denied($page);
|
||||
}
|
||||
else {
|
||||
|
@ -329,7 +329,7 @@ class Setup extends SimpleExtension {
|
|||
|
||||
public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
|
||||
global $user;
|
||||
if($user->is_admin()) {
|
||||
if($user->can("change_setting")) {
|
||||
$event->add_link("Board Config", make_link("setup"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class TagEdit extends SimpleExtension {
|
|||
global $user, $page;
|
||||
if($event->page_matches("tag_edit")) {
|
||||
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'];
|
||||
$replace = $_POST['replace'];
|
||||
$this->mass_tag_edit($search, $replace);
|
||||
|
@ -82,7 +82,7 @@ class TagEdit extends SimpleExtension {
|
|||
else {
|
||||
$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";
|
||||
send_event(new LockSetEvent($event->image, $locked));
|
||||
}
|
||||
|
@ -90,21 +90,21 @@ class TagEdit extends SimpleExtension {
|
|||
|
||||
public function onTagSet(TagSetEvent $event) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public function onSourceSet(SourceSetEvent $event) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public function onLockSet(LockSetEvent $event) {
|
||||
global $user;
|
||||
if($user->is_admin()) {
|
||||
if($user->can("lock_image")) {
|
||||
$event->image->set_locked($event->locked);
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ class TagEdit extends SimpleExtension {
|
|||
if($this->can_source($event->image)) {
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ class TagEdit extends SimpleExtension {
|
|||
global $config, $user;
|
||||
return (
|
||||
($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;
|
||||
return (
|
||||
($config->get_bool("source_edit_anon") || !$user->is_anonymous()) &&
|
||||
($user->is_admin() || !$image->is_locked())
|
||||
($user->can("edit_source") || !$image->is_locked())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?php
|
||||
/*
|
||||
/**
|
||||
* Name: Tag List
|
||||
* Author: Shish
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* Description: Show the tags in various ways
|
||||
*/
|
||||
|
||||
|
@ -107,13 +108,18 @@ class TagList extends SimpleExtension {
|
|||
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() {
|
||||
if(isset($_GET['mincount'])) {
|
||||
return int_escape($_GET['mincount']);
|
||||
}
|
||||
else {
|
||||
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();
|
||||
$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";
|
||||
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();
|
||||
$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";
|
||||
if(file_exists($cache_key)) {return file_get_contents($cache_key);}
|
||||
|
||||
|
@ -239,6 +249,8 @@ class TagList extends SimpleExtension {
|
|||
global $database;
|
||||
|
||||
$tags_min = $this->get_tags_min();
|
||||
|
||||
// check if we have a cached version
|
||||
$cache_key = "data/tag_popul-" . md5("tp" . $tags_min) . ".html";
|
||||
if(file_exists($cache_key)) {return file_get_contents($cache_key);}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?php
|
||||
/*
|
||||
* Name: Database Upgrader
|
||||
* Author: Shish
|
||||
* Author: Shish <webmaster@shishnet.org>
|
||||
* Link: http://code.shishnet.org/shimmie2/
|
||||
* Description: Keeps things happy behind the scenes
|
||||
* Visibility: admin
|
||||
*/
|
||||
|
@ -10,6 +11,8 @@ class Upgrade extends SimpleExtension {
|
|||
public function onInitExt(InitExtEvent $event) {
|
||||
global $config, $database;
|
||||
|
||||
if($config->get_bool("in_upgrade")) return;
|
||||
|
||||
if(!is_numeric($config->get_string("db_version"))) {
|
||||
$config->set_int("db_version", 2);
|
||||
}
|
||||
|
@ -18,28 +21,43 @@ class Upgrade extends SimpleExtension {
|
|||
// cry :S
|
||||
}
|
||||
|
||||
if($config->get_int("db_version") < 7) {
|
||||
/*
|
||||
// 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");
|
||||
}
|
||||
// v7 is convert to innodb with adodb
|
||||
// now done again as v9 with PDO
|
||||
|
||||
if($config->get_int("db_version") < 8) {
|
||||
// if this fails, don't try again
|
||||
$config->set_bool("in_upgrade", true);
|
||||
$config->set_int("db_version", 8);
|
||||
$database->execute($database->engine->scoreql_to_sql(
|
||||
"ALTER TABLE images ADD COLUMN locked SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N"
|
||||
));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
/*
|
||||
/**
|
||||
* Name: Uploader
|
||||
* Author: Shish
|
||||
* Description: Allows people to upload files to the website
|
||||
|
@ -122,7 +122,7 @@ class Upload extends SimpleExtension {
|
|||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
else {
|
||||
|
@ -224,14 +224,28 @@ class Upload extends SimpleExtension {
|
|||
}
|
||||
// }}}
|
||||
// do things {{{
|
||||
|
||||
/**
|
||||
* Check if a given user can upload.
|
||||
* @param $user The user to check.
|
||||
* @retval bool
|
||||
*/
|
||||
private function can_upload(User $user) {
|
||||
global $config;
|
||||
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
|
||||
// TODO: Make these messages user/admin editable
|
||||
/**
|
||||
* Returns a descriptive error message for the specified PHP error code.
|
||||
*
|
||||
* 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) {
|
||||
switch ($error_code) {
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
|
@ -253,6 +267,10 @@ class Upload extends SimpleExtension {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an upload.
|
||||
* @retval bool TRUE on upload successful.
|
||||
*/
|
||||
private function try_upload($file, $tags, $source, $replace='') {
|
||||
global $page;
|
||||
global $config;
|
||||
|
@ -299,6 +317,10 @@ class Upload extends SimpleExtension {
|
|||
return $ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an transload.
|
||||
* @retval bool TRUE on transload successful.
|
||||
*/
|
||||
private function try_transload($url, $tags, $source, $replace='') {
|
||||
global $page;
|
||||
global $config;
|
||||
|
@ -314,7 +336,7 @@ class Upload extends SimpleExtension {
|
|||
}
|
||||
|
||||
// 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']);
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ class UserPage extends SimpleExtension {
|
|||
$this->theme->display_error($page, "Not Logged In",
|
||||
"You aren't logged in. First do that, then you can see your stats.");
|
||||
}
|
||||
else if(!is_null($display_user)) {
|
||||
else if(!is_null($display_user) && ($display_user->id != $config->get_int("anon_id"))) {
|
||||
send_event(new UserPageBuildingEvent($display_user));
|
||||
}
|
||||
else {
|
||||
|
@ -187,7 +187,7 @@ class UserPage extends SimpleExtension {
|
|||
$this->theme->display_user_links($page, $user, $ubbe->parts);
|
||||
}
|
||||
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
|
||||
) {
|
||||
$this->theme->display_ip_list(
|
||||
|
@ -256,7 +256,7 @@ class UserPage extends SimpleExtension {
|
|||
$user_id = int_escape($matches[2]);
|
||||
$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?
|
||||
$event->add_querylet(new Querylet("images.owner_ip = '$user_ip'"));
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ class UserPage extends SimpleExtension {
|
|||
|
||||
$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",
|
||||
"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);
|
||||
|
||||
if((!$user->is_admin()) && ($duser->name != $user->name)) {
|
||||
if((!$user->can("change_user_info")) && ($duser->name != $user->name)) {
|
||||
$this->theme->display_error($page, "Error",
|
||||
"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_heading("Error");
|
||||
$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"));
|
||||
}
|
||||
else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {
|
||||
|
@ -479,7 +479,7 @@ class UserPage extends SimpleExtension {
|
|||
$page->set_heading("Error");
|
||||
$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"));
|
||||
}
|
||||
else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {
|
||||
|
@ -510,7 +510,7 @@ class UserPage extends SimpleExtension {
|
|||
$page->set_heading("Error");
|
||||
$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"));
|
||||
}
|
||||
else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {
|
||||
|
|
|
@ -141,7 +141,7 @@ class UserPageTheme extends Themelet {
|
|||
$page->add_block(new Block("Stats", join("<br>", $stats), "main", 0));
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ class UserPageTheme extends Themelet {
|
|||
</form>
|
||||
";
|
||||
|
||||
if($user->is_admin()) {
|
||||
if($user->can("change_user_info")) {
|
||||
$i_user_id = int_escape($duser->id);
|
||||
$h_is_admin = $duser->is_admin() ? " checked" : "";
|
||||
$html .= "
|
||||
|
|
|
@ -90,7 +90,7 @@ class ViewImageTheme extends Themelet {
|
|||
$html = "";
|
||||
$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)";
|
||||
}
|
||||
if(!is_null($image->source)) {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
* Each of these can be imported at the start of a function with eg "global $page, $user;"
|
||||
*/
|
||||
|
||||
if(empty($database_dsn) && !file_exists("config.php")) {
|
||||
if(!file_exists("config.php")) {
|
||||
header("Location: install.php");
|
||||
exit;
|
||||
}
|
||||
|
|
153
install.php
153
install.php
|
@ -1,7 +1,8 @@
|
|||
<?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
|
||||
- permissions are set properly, set an admin
|
||||
|
@ -12,17 +13,18 @@
|
|||
-->
|
||||
<head>
|
||||
<title>Shimmie Installation</title>
|
||||
<style>
|
||||
BODY {background: #EEE;font-family: "Arial", sans-serif;font-size: 14px;}
|
||||
H1, H3 {border: 1px solid black;background: #DDD;text-align: center;}
|
||||
H1 {margin-top: 0px;margin-bottom: 0px;padding: 2px;}
|
||||
H3 {margin-top: 32px;padding: 1px;}
|
||||
FORM {margin: 0px;}
|
||||
A {text-decoration: none;}
|
||||
A:hover {text-decoration: underline;}
|
||||
#block {width: 512px; margin: auto; margin-top: 64px;}
|
||||
#iblock {width: 512px; margin: auto; margin-top: 16px;}
|
||||
TD INPUT {width: 350px;}
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<style type="text/css">
|
||||
BODY {background: #EEE;font-family: "Arial", sans-serif;font-size: 14px;}
|
||||
H1, H3 {border: 1px solid black;background: #DDD;text-align: center;}
|
||||
H1 {margin-top: 0px;margin-bottom: 0px;padding: 2px;}
|
||||
H3 {margin-top: 32px;padding: 1px;}
|
||||
FORM {margin: 0px;}
|
||||
A {text-decoration: none;}
|
||||
A:hover {text-decoration: underline;}
|
||||
#block {width: 512px; margin: auto; margin-top: 64px;}
|
||||
#iblock {width: 512px; margin: auto; margin-top: 16px;}
|
||||
TD INPUT {width: 350px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -31,9 +33,10 @@ TD INPUT {width: 350px;}
|
|||
<h1>Install Error</h1>
|
||||
<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
|
||||
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
|
||||
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 style="display: none;">
|
||||
<PLAINTEXT>
|
||||
|
@ -51,9 +54,32 @@ if(is_readable("config.php")) {
|
|||
<div id="iblock">
|
||||
<h1>Shimmie Repair Console</h1>
|
||||
<?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"])) {
|
||||
echo "<h3>Basic Checks</h3>";
|
||||
|
@ -76,15 +102,6 @@ if(is_readable("config.php")) {
|
|||
</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 "
|
||||
|
@ -95,15 +112,12 @@ if(is_readable("config.php")) {
|
|||
}
|
||||
else if($_GET["action"] == "logout") {
|
||||
session_destroy();
|
||||
}
|
||||
else if($_GET["action"] == "Database_user_deletion_fix") {
|
||||
Database_user_deletion_fix();
|
||||
echo "<h3>Logged Out</h3><p>You have been logged out.</p><a href='index.php'>Main Shimmie Page</a>";
|
||||
}
|
||||
} else {
|
||||
echo "
|
||||
<h3>Login</h3>
|
||||
Enter the database DSN exactly as in config.php (ie, as originally
|
||||
installed) to access advanced recovery tools:
|
||||
<p>Enter the database DSN exactly as in config.php (ie, as originally installed) to access advanced recovery tools:</p>
|
||||
|
||||
<form action='install.php' method='POST'>
|
||||
<center>
|
||||
|
@ -118,13 +132,24 @@ if(is_readable("config.php")) {
|
|||
echo "\t\t</div>";
|
||||
exit;
|
||||
}
|
||||
require_once "core/compat.inc.php";
|
||||
require_once "core/util.inc.php";
|
||||
require_once "core/database.class.php";
|
||||
|
||||
do_install();
|
||||
|
||||
// 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() {
|
||||
$gdversion = 0;
|
||||
|
||||
|
@ -249,7 +274,7 @@ function begin() { // {{{
|
|||
<h3>Help</h3>
|
||||
|
||||
<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>
|
||||
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_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)
|
||||
{
|
||||
|
@ -354,11 +379,12 @@ function build_dirs() { // {{{
|
|||
!file_exists("images") || !file_exists("thumbs") || !file_exists("data") ||
|
||||
!is_writable("images") || !is_writable("thumbs") || !is_writable("data")
|
||||
) {
|
||||
print "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,
|
||||
if probably means the folders are owned by you, and they need to be
|
||||
writable by the web server).
|
||||
<p>Once you have created these folders, hit 'refresh' to continue.";
|
||||
print "<p>Shimmie needs three folders in it's directory, 'images', 'thumbs', and 'data',
|
||||
and they need to be writable by the PHP user.</p>
|
||||
<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.</p>
|
||||
<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;
|
||||
}
|
||||
} // }}}
|
||||
|
@ -387,49 +413,6 @@ EOD;
|
|||
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>
|
||||
</html>
|
||||
|
|
|
@ -27,70 +27,25 @@ $(document).ready(function() {
|
|||
});
|
||||
|
||||
$("time").timeago();
|
||||
});
|
||||
|
||||
var defaultTexts = new Array();
|
||||
$('.search_input').DefaultValue('Search');
|
||||
$('#search_input').autocomplete(base_href + '/api/internal/tag_list/complete', {
|
||||
width: 320,
|
||||
max: 15,
|
||||
highlight: false,
|
||||
multiple: true,
|
||||
multipleSeparator: ' ',
|
||||
scroll: true,
|
||||
scrollHeight: 300,
|
||||
selectFirst: false
|
||||
});
|
||||
|
||||
window.onload = function(e) {
|
||||
var sections=get_sections();
|
||||
for(var i=0;i<sections.length;i++) toggle(sections[i]);
|
||||
|
||||
initGray("search_input", "Search");
|
||||
initGray("commentBox", "Comment");
|
||||
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");
|
||||
}
|
||||
}
|
||||
$("#commentBox").DefaultValue("Comment");
|
||||
$("#tagBox").DefaultValue("tagme");
|
||||
});
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
|
||||
|
@ -111,6 +66,7 @@ function byId(id) {
|
|||
}
|
||||
|
||||
|
||||
// used once in ext/setup/main
|
||||
function getHTTPObject() {
|
||||
if (window.XMLHttpRequest){
|
||||
return new XMLHttpRequest();
|
||||
|
@ -120,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 */
|
||||
function getCookie( name ) {
|
||||
|
@ -164,3 +111,10 @@ function deleteCookie( name, path, domain ) {
|
|||
";expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
||||
}
|
||||
|
||||
function replyTo(imageId, commentId) {
|
||||
var box = $("#comment_on_"+imageId);
|
||||
var text = ">>"+imageId+"#"+commentId+": ";
|
||||
|
||||
box.focus();
|
||||
box.val(box.val() + text);
|
||||
}
|
||||
|
|
|
@ -223,7 +223,9 @@ $header_html
|
|||
<em>
|
||||
Images © their respective owners,
|
||||
<a href="http://code.shishnet.org/shimmie2/">Shimmie</a> ©
|
||||
<a href="http://www.shishnet.org/">Shish</a> & Co 2007-2012,
|
||||
<a href="http://www.shishnet.org/">Shish</a> &
|
||||
<a href="https://github.com/shish/shimmie2/contributors">The Team</a>
|
||||
2007-2012,
|
||||
based on the Danbooru concept.
|
||||
$debug
|
||||
$contact
|
||||
|
|
|
@ -71,7 +71,9 @@ $header_html
|
|||
<div id="footer">
|
||||
Images © their respective owners,
|
||||
<a href="http://code.shishnet.org/shimmie2/">Shimmie</a> ©
|
||||
<a href="http://www.shishnet.org/">Shish</a> & Co 2007-2012,
|
||||
<a href="http://www.shishnet.org/">Shish</a> &
|
||||
<a href="https://github.com/shish/shimmie2/contributors">The Team</a>
|
||||
2007-2012,
|
||||
based on the Danbooru concept.
|
||||
$debug
|
||||
$contact
|
||||
|
|
|
@ -128,9 +128,8 @@ UL {
|
|||
.comment {
|
||||
text-align: left;
|
||||
}
|
||||
.comment .timeago {
|
||||
float: right;
|
||||
font-size: 75%;
|
||||
.comment .info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.more:after {
|
||||
|
|
|
@ -71,7 +71,9 @@ $header_html
|
|||
<div id="footer">
|
||||
Images © their respective owners,
|
||||
<a href="http://code.shishnet.org/shimmie2/">Shimmie</a> ©
|
||||
<a href="http://www.shishnet.org/">Shish</a> & Co 2007-2012,
|
||||
<a href="http://www.shishnet.org/">Shish</a> &
|
||||
<a href="https://github.com/shish/shimmie2/contributors">The Team</a>
|
||||
2007-2012,
|
||||
based on the Danbooru concept.
|
||||
$debug
|
||||
$contact
|
||||
|
|
|
@ -79,7 +79,9 @@ $header_html
|
|||
<hr>
|
||||
Images © their respective owners,
|
||||
<a href="http://code.shishnet.org/shimmie2/">Shimmie</a> ©
|
||||
<a href="http://www.shishnet.org/">Shish</a> & Co 2007-2012,
|
||||
<a href="http://www.shishnet.org/">Shish</a> &
|
||||
<a href="https://github.com/shish/shimmie2/contributors">The Team</a>
|
||||
2007-2012,
|
||||
based on the Danbooru concept.
|
||||
<br>Futaba theme based on 4chan's layout and CSS :3
|
||||
$debug
|
||||
|
|
|
@ -184,7 +184,9 @@ class Layout {
|
|||
<div id="footer">
|
||||
Images © their respective owners,
|
||||
<a href="http://code.shishnet.org/shimmie2/">Shimmie</a> ©
|
||||
<a href="http://www.shishnet.org/">Shish</a> & Co 2007-2012,
|
||||
<a href="http://www.shishnet.org/">Shish</a> &
|
||||
<a href="https://github.com/shish/shimmie2/contributors">The Team</a>
|
||||
2007-2012,
|
||||
based on the Danbooru concept.<br />
|
||||
Lite Theme by <a href="http://seemslegit.com">Zach</a>
|
||||
$debug
|
||||
|
|
|
@ -69,7 +69,9 @@ $header_html
|
|||
<hr>
|
||||
Images © their respective owners,
|
||||
<a href="http://code.shishnet.org/shimmie2/">Shimmie</a> ©
|
||||
<a href="http://www.shishnet.org/">Shish</a> & Co 2007-2012,
|
||||
<a href="http://www.shishnet.org/">Shish</a> &
|
||||
<a href="https://github.com/shish/shimmie2/contributors">The Team</a>
|
||||
2007-2012,
|
||||
based on the Danbooru concept.
|
||||
$debug
|
||||
$contact
|
||||
|
|
|
@ -85,7 +85,9 @@ $header_html
|
|||
<div id="footer">
|
||||
Images © their respective owners,
|
||||
<a href="http://code.shishnet.org/shimmie2/">Shimmie</a> ©
|
||||
<a href="http://www.shishnet.org/">Shish</a> & Co 2007-2012,
|
||||
<a href="http://www.shishnet.org/">Shish</a> &
|
||||
<a href="https://github.com/shish/shimmie2/contributors">The Team</a>
|
||||
2007-2012,
|
||||
based on the Danbooru concept.
|
||||
$debug
|
||||
$contact
|
||||
|
|
Reference in a new issue