Merge branch 'develop' of https://github.com/shish/shimmie2 into develop
This commit is contained in:
commit
445687111e
18 changed files with 178 additions and 56 deletions
|
@ -191,7 +191,13 @@ class Image {
|
|||
return null;
|
||||
}
|
||||
fwrite($fp, json_encode($req));
|
||||
$data = fgets($fp, 1024);
|
||||
$data = "";
|
||||
while (($buffer = fgets($fp, 4096)) !== false) {
|
||||
$data .= $buffer;
|
||||
}
|
||||
if (!feof($fp)) {
|
||||
die("Error: unexpected fgets() fail in query_accelerator($req)\n");
|
||||
}
|
||||
fclose($fp);
|
||||
return json_decode($data);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ _d("CORE_EXTS", "bbcode,user,mail,upload,image,view,handle_pixel,ext_manager,set
|
|||
_d("EXTRA_EXTS", ""); // string optional extra extensions
|
||||
_d("BASE_URL", null); // string force a specific base URL (default is auto-detect)
|
||||
_d("MIN_PHP_VERSION", '7.0');// string minimum supported PHP version
|
||||
_d("SLOW_PAGES", null); // float log pages which take more time than this
|
||||
_d("ENABLED_MODS", "imageboard");
|
||||
|
||||
/*
|
||||
|
|
|
@ -105,11 +105,19 @@ class User {
|
|||
$user = User::by_name($name);
|
||||
if($user) {
|
||||
if($user->passhash == md5(strtolower($name) . $pass)) {
|
||||
log_info("core-user", "Migrating from md5 to bcrypt for ".html_escape($name));
|
||||
$user->set_password($pass);
|
||||
}
|
||||
if(password_verify($pass, $user->passhash)) {
|
||||
log_info("core-user", "Logged in as ".html_escape($name)." ({$user->class->name})");
|
||||
return $user;
|
||||
}
|
||||
else {
|
||||
log_warning("core-user", "Failed to log in as ".html_escape($name)." (Invalid password)");
|
||||
}
|
||||
}
|
||||
else {
|
||||
log_warning("core-user", "Failed to log in as ".html_escape($name)." (Invalid username)");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -350,6 +350,18 @@ function get_debug_info(): string {
|
|||
return $debug;
|
||||
}
|
||||
|
||||
function log_slow() {
|
||||
global $_shm_load_start;
|
||||
if(!is_null(SLOW_PAGES)) {
|
||||
$_time = microtime(true) - $_shm_load_start;
|
||||
if($_time > SLOW_PAGES) {
|
||||
$_query = _get_query();
|
||||
$_dbg = get_debug_info();
|
||||
file_put_contents("data/slow-pages.log", "$_time $_query $_dbg\n", FILE_APPEND | LOCK_EX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function score_assert_handler($file, $line, $code, $desc = null) {
|
||||
$file = basename($file);
|
||||
print("Assertion failed at $file:$line: $code ($desc)");
|
||||
|
@ -389,7 +401,7 @@ function _sanitise_environment() {
|
|||
date_default_timezone_set(TIMEZONE);
|
||||
}
|
||||
|
||||
ini_set('zend.assertions', 1); // generate assertions
|
||||
# ini_set('zend.assertions', 1); // generate assertions
|
||||
ini_set('assert.exception', 1); // throw exceptions when failed
|
||||
if(DEBUG) {
|
||||
error_reporting(E_ALL);
|
||||
|
|
|
@ -130,16 +130,15 @@ class AdminPage extends Extension {
|
|||
$reason = @$_POST['reason'];
|
||||
assert(strlen($query) > 1);
|
||||
|
||||
log_warning("admin", "Mass deleting: $query");
|
||||
$count = 0;
|
||||
foreach(Image::find_images(0, 1000000, Tag::explode($query)) as $image) {
|
||||
$images = Image::find_images(0, 1000000, Tag::explode($query));
|
||||
$count = count($images);
|
||||
log_warning("admin", "Mass-deleting $count images from $query", true);
|
||||
foreach($images as $image) {
|
||||
if($reason && class_exists("ImageBan")) {
|
||||
send_event(new AddImageHashBanEvent($image->hash, $reason));
|
||||
}
|
||||
send_event(new ImageDeletionEvent($image));
|
||||
$count++;
|
||||
}
|
||||
log_debug("admin", "Deleted $count images", true);
|
||||
|
||||
$page->set_mode("redirect");
|
||||
$page->set_redirect(make_link("post/list"));
|
||||
|
|
|
@ -14,10 +14,24 @@ class AutoComplete extends Extension {
|
|||
if($event->page_matches("api/internal/autocomplete")) {
|
||||
if(!isset($_GET["s"])) return;
|
||||
|
||||
$page->set_mode("data");
|
||||
$page->set_type("application/json");
|
||||
|
||||
$s = strtolower($_GET["s"]);
|
||||
if(
|
||||
$s == '' ||
|
||||
$s[0] == '_' ||
|
||||
$s[0] == '%' ||
|
||||
strlen($s) > 32
|
||||
) {
|
||||
$page->set_data("{}");
|
||||
return;
|
||||
}
|
||||
|
||||
//$limit = 0;
|
||||
$cache_key = "autocomplete-" . strtolower($_GET["s"]);
|
||||
$cache_key = "autocomplete-$s";
|
||||
$limitSQL = "";
|
||||
$SQLarr = array("search"=>$_GET["s"]."%");
|
||||
$SQLarr = array("search"=>"$s%");
|
||||
if(isset($_GET["limit"]) && $_GET["limit"] !== 0){
|
||||
$limitSQL = "LIMIT :limit";
|
||||
$SQLarr['limit'] = $_GET["limit"];
|
||||
|
@ -37,8 +51,6 @@ class AutoComplete extends Extension {
|
|||
$database->cache->set($cache_key, $res, 600);
|
||||
}
|
||||
|
||||
$page->set_mode("data");
|
||||
$page->set_type("application/json");
|
||||
$page->set_data(json_encode($res));
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ class VideoFileHandler extends DataHandlerExtension {
|
|||
|
||||
$orig_size = $this->video_size($inname);
|
||||
$scaled_size = get_thumbnail_size($orig_size[0], $orig_size[1]);
|
||||
$cmd = escapeshellcmd(Tag::implode([
|
||||
$cmd = escapeshellcmd(implode(" ", [
|
||||
escapeshellarg($ffmpeg),
|
||||
"-y", "-i", escapeshellarg($inname),
|
||||
"-vf", "scale={$scaled_size[0]}:{$scaled_size[1]}",
|
||||
|
@ -76,12 +76,13 @@ class VideoFileHandler extends DataHandlerExtension {
|
|||
|
||||
exec($cmd, $output, $ret);
|
||||
|
||||
if ((int)$ret == (int)1) {
|
||||
if ((int)$ret == (int)0) {
|
||||
$ok = true;
|
||||
log_error('handle_video', "Generating thumbnail with command `$cmd`, returns $ret");
|
||||
}
|
||||
|
||||
// error_log("Generating thumbnail with command `$cmd`, returns $ret");
|
||||
else {
|
||||
log_debug('handle_video', "Generating thumbnail with command `$cmd`, returns $ret");
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
@ -89,7 +90,7 @@ class VideoFileHandler extends DataHandlerExtension {
|
|||
protected function video_size(string $filename) {
|
||||
global $config;
|
||||
$ffmpeg = $config->get_string("thumb_ffmpeg_path");
|
||||
$cmd = escapeshellcmd(Tag::implode([
|
||||
$cmd = escapeshellcmd(implode(" ", [
|
||||
escapeshellarg($ffmpeg),
|
||||
"-y", "-i", escapeshellarg($filename),
|
||||
"-vstats"
|
||||
|
@ -100,15 +101,17 @@ class VideoFileHandler extends DataHandlerExtension {
|
|||
$regex_sizes = "/Video: .* ([0-9]{1,4})x([0-9]{1,4})/";
|
||||
if (preg_match($regex_sizes, $output, $regs)) {
|
||||
if (preg_match("/displaymatrix: rotation of (90|270).00 degrees/", $output)) {
|
||||
return [$regs[2], $regs[1]];
|
||||
$size = [$regs[2], $regs[1]];
|
||||
}
|
||||
else {
|
||||
return [$regs[1], $regs[2]];
|
||||
$size = [$regs[1], $regs[2]];
|
||||
}
|
||||
}
|
||||
else {
|
||||
return [1, 1];
|
||||
$size = [1, 1];
|
||||
}
|
||||
log_debug('handle_video', "Getting video size with `$cmd`, returns $output -- $size[0], $size[1]");
|
||||
return $size;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,7 +43,11 @@ class IPBan extends Extension {
|
|||
if($config->get_int("ext_ipban_version") < 8) {
|
||||
$this->install();
|
||||
}
|
||||
$config->set_default_string("ipban_message", "If you couldn't possibly be guilty of what you're banned for, the person we banned probably had a dynamic IP address and so do you. See <a href='http://whatismyipaddress.com/dynamic-static'>http://whatismyipaddress.com/dynamic-static</a> for more information.\n");
|
||||
$config->set_default_string("ipban_message",
|
||||
'<p>IP <b>$IP</b> has been banned until <b>$DATE</b> by <b>$ADMIN</b> because of <b>$REASON</b>
|
||||
<p>If you couldn\'t possibly be guilty of what you\'re banned for, the person we banned probably had a dynamic IP address and so do you.
|
||||
<p>See <a href="http://whatismyipaddress.com/dynamic-static">http://whatismyipaddress.com/dynamic-static</a> for more information.
|
||||
<p>$CONTACT');
|
||||
$this->check_ip_ban();
|
||||
}
|
||||
|
||||
|
@ -84,7 +88,7 @@ class IPBan extends Extension {
|
|||
|
||||
public function onSetupBuilding(SetupBuildingEvent $event) {
|
||||
$sb = new SetupBlock("IP Ban");
|
||||
$sb->add_longtext_option("ipban_message", 'Message to show to banned users:');
|
||||
$sb->add_longtext_option("ipban_message", 'Message to show to banned users:<br>(with $IP, $DATE, $ADMIN, $REASON, and $CONTACT)');
|
||||
$event->panel->add_block($sb);
|
||||
}
|
||||
|
||||
|
@ -226,14 +230,20 @@ class IPBan extends Extension {
|
|||
$admin = User::by_id($row[$prefix.'banner_id']);
|
||||
$date = date("Y-m-d", $row[$prefix.'end_timestamp']);
|
||||
$msg = $config->get_string("ipban_message");
|
||||
header("HTTP/1.0 403 Forbidden");
|
||||
print "IP <b>$ip</b> has been banned until <b>$date</b> by <b>{$admin->name}</b> because of <b>$reason</b>\n";
|
||||
print "<p>$msg";
|
||||
|
||||
$msg = str_replace('$IP', $ip, $msg);
|
||||
$msg = str_replace('$DATE', $date, $msg);
|
||||
$msg = str_replace('$ADMIN', $admin->name, $msg);
|
||||
$msg = str_replace('$REASON', $reason, $msg);
|
||||
$contact_link = contact_link();
|
||||
if(!empty($contact_link)) {
|
||||
print "<p><a href='$contact_link'>Contact the staff (be sure to include this message)</a>";
|
||||
$msg = str_replace('$CONTACT', "<a href='$contact_link'>Contact the staff (be sure to include this message)</a>", $msg);
|
||||
}
|
||||
else {
|
||||
$msg = str_replace('$CONTACT', "", $msg);
|
||||
}
|
||||
header("HTTP/1.0 403 Forbidden");
|
||||
print "$msg";
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,13 +91,13 @@ class RSS_Images extends Extension {
|
|||
|
||||
$link = make_http(make_link("post/view/{$image->id}"));
|
||||
$tags = html_escape($image->get_tag_list());
|
||||
$owner = $image->get_owner();
|
||||
$thumb_url = $image->get_thumb_link();
|
||||
$image_url = $image->get_image_link();
|
||||
$posted = date(DATE_RSS, strtotime($image->posted));
|
||||
$content = html_escape(
|
||||
"<div>" .
|
||||
"<p>" . $this->theme->build_thumb_html($image) . "</p>" .
|
||||
"<p>Uploaded by " . html_escape($owner->name) . "</p>"
|
||||
"</div>"
|
||||
);
|
||||
|
||||
$data = "
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
$(function() {
|
||||
if(Cookies.get("ui-tnc-agreed") !== "true") {
|
||||
$("BODY").html(""+
|
||||
"<div align='center' style='font-size: 2em; position: absolute; z-index: 99999999999999999999999999;'>"+
|
||||
$("BODY").addClass("censored");
|
||||
$("BODY").append("<div class='tnc_bg'></div>");
|
||||
$("BODY").append(""+
|
||||
"<div class='tnc'>"+
|
||||
"<p>For legal reasons, we need to point out that:"+
|
||||
"<p>A) this site contains material not suitable for minors"+
|
||||
"<br>B) cookies may be used"+
|
||||
"<p><a href='/tnc_agreed'>Click here if you're an adult, and you're ok with that</a>"+
|
||||
"<p><a onclick='tnc_agree();'>Click here if you're an adult, and you're ok with that</a>"+
|
||||
"</div>"+
|
||||
"");
|
||||
}
|
||||
});
|
||||
|
||||
function tnc_agree() {
|
||||
Cookies.set("ui-tnc-agreed", "true", {path: '/', expires: 365});
|
||||
$("BODY").removeClass("censored");
|
||||
$(".tnc_bg").hide();
|
||||
$(".tnc").hide();
|
||||
}
|
||||
|
||||
function image_hash_ban(id) {
|
||||
var reason = prompt("WHY?", "DNP");
|
||||
if(reason) {
|
||||
|
|
35
ext/rule34/style.css
Normal file
35
ext/rule34/style.css
Normal file
|
@ -0,0 +1,35 @@
|
|||
BODY.censored #header,
|
||||
BODY.censored NAV,
|
||||
BODY.censored ARTICLE,
|
||||
BODY.censored FOOTER {
|
||||
filter: blur(10px);
|
||||
}
|
||||
.tnc_bg {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background: #ACE4A3;
|
||||
opacity: 0.75;
|
||||
z-index: 999999999999999999999;
|
||||
}
|
||||
.tnc {
|
||||
position: fixed;
|
||||
top: 20%;
|
||||
left: 20%;
|
||||
right: 20%;
|
||||
text-align: center;
|
||||
font-size: 2em;
|
||||
background: #ACE4A3;
|
||||
border: 1px solid #7EB977;
|
||||
z-index: 9999999999999999999999;
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.tnc {
|
||||
top: 5%;
|
||||
left: 5%;
|
||||
right: 5%;
|
||||
font-size: 3vw;
|
||||
}
|
||||
}
|
|
@ -66,19 +66,19 @@ class StatsDInterface extends Extension {
|
|||
}
|
||||
|
||||
public function onUserCreation(UserCreationEvent $event) {
|
||||
StatsDInterface::$stats["shimmie.events.user_creations"] = "1|c";
|
||||
StatsDInterface::$stats["shimmie_events.user_creations"] = "1|c";
|
||||
}
|
||||
|
||||
public function onDataUpload(DataUploadEvent $event) {
|
||||
StatsDInterface::$stats["shimmie.events.uploads"] = "1|c";
|
||||
StatsDInterface::$stats["shimmie_events.uploads"] = "1|c";
|
||||
}
|
||||
|
||||
public function onCommentPosting(CommentPostingEvent $event) {
|
||||
StatsDInterface::$stats["shimmie.events.comments"] = "1|c";
|
||||
StatsDInterface::$stats["shimmie_events.comments"] = "1|c";
|
||||
}
|
||||
|
||||
public function onImageInfoSet(ImageInfoSetEvent $event) {
|
||||
StatsDInterface::$stats["shimmie.events.info-sets"] = "1|c";
|
||||
StatsDInterface::$stats["shimmie_events.info-sets"] = "1|c";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -497,6 +497,8 @@ class TagList extends Extension {
|
|||
private function add_refine_block(Page $page, array $search) {
|
||||
global $database, $config;
|
||||
|
||||
if(count($search) > 5) return;
|
||||
|
||||
$wild_tags = $search;
|
||||
$str_search = Tag::implode($search);
|
||||
$related_tags = $database->cache->get("related_tags:$str_search");
|
||||
|
@ -509,7 +511,7 @@ class TagList extends Extension {
|
|||
foreach($wild_tags as $tag) {
|
||||
$tag = str_replace("*", "%", $tag);
|
||||
$tag = str_replace("?", "_", $tag);
|
||||
$tag_ids = $database->get_col("SELECT id FROM tags WHERE tag LIKE :tag", array("tag"=>$tag));
|
||||
$tag_ids = $database->get_col("SELECT id FROM tags WHERE tag LIKE :tag AND count < 25000", array("tag"=>$tag));
|
||||
// $search_tags = array_merge($search_tags,
|
||||
// $database->get_col("SELECT tag FROM tags WHERE tag LIKE :tag", array("tag"=>$tag)));
|
||||
$tag_id_array = array_merge($tag_id_array, $tag_ids);
|
||||
|
@ -518,6 +520,8 @@ class TagList extends Extension {
|
|||
}
|
||||
$tag_id_list = join(', ', $tag_id_array);
|
||||
|
||||
if(count($tag_id_array) > 5) return;
|
||||
|
||||
if($tags_ok) {
|
||||
$query = "
|
||||
SELECT t2.tag AS tag, COUNT(it2.image_id) AS calc_count
|
||||
|
|
|
@ -82,18 +82,6 @@ class Upload extends Extension {
|
|||
}
|
||||
}
|
||||
|
||||
public function onPostListBuilding(PostListBuildingEvent $event) {
|
||||
global $user, $page;
|
||||
if($user->can("create_image")) {
|
||||
if($this->is_full) {
|
||||
$this->theme->display_full($page);
|
||||
}
|
||||
else {
|
||||
$this->theme->display_block($page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function onSetupBuilding(SetupBuildingEvent $event) {
|
||||
$tes = array();
|
||||
$tes["Disabled"] = "none";
|
||||
|
@ -130,6 +118,15 @@ class Upload extends Extension {
|
|||
public function onPageRequest(PageRequestEvent $event) {
|
||||
global $database, $page, $user;
|
||||
|
||||
if($user->can("create_image")) {
|
||||
if($this->is_full) {
|
||||
$this->theme->display_full($page);
|
||||
}
|
||||
else {
|
||||
$this->theme->display_block($page);
|
||||
}
|
||||
}
|
||||
|
||||
if($event->page_matches("upload/replace")) {
|
||||
// check if the user is an administrator and can upload files.
|
||||
if(!$user->can("replace_image")) {
|
||||
|
|
|
@ -19,9 +19,9 @@ class UploadTheme extends Themelet {
|
|||
$html = "
|
||||
".make_form(make_link("upload"), "POST", $multipart=True, 'file_upload')."
|
||||
<table id='large_upload_form' class='vert'>
|
||||
<tr><td width='20'>Common Tags<td colspan='5'><input name='tags' type='text' placeholder='tagme' class='autocomplete_tags' autocomplete='off'></td></tr>
|
||||
<tr><td>Common Source</td><td colspan='5'><input name='source' type='text'></td></tr>
|
||||
$upload_list
|
||||
<tr><td width='20'>Tags<td colspan='5'><input name='tags' type='text' placeholder='tagme' class='autocomplete_tags' autocomplete='off'></td></tr>
|
||||
<tr><td>Source</td><td colspan='5'><input name='source' type='text'></td></tr>
|
||||
<tr><td colspan='6'><input id='uploadbutton' type='submit' value='Post'></td></tr>
|
||||
</table>
|
||||
</form>
|
||||
|
|
|
@ -240,7 +240,9 @@ class UserPage extends Extension {
|
|||
$this->theme->display_ip_list(
|
||||
$page,
|
||||
$this->count_upload_ips($event->display_user),
|
||||
$this->count_comment_ips($event->display_user));
|
||||
$this->count_comment_ips($event->display_user),
|
||||
$this->count_log_ips($event->display_user)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,7 +346,6 @@ class UserPage extends Extension {
|
|||
if(!is_null($duser)) {
|
||||
$user = $duser;
|
||||
$this->set_login_cookie($duser->name, $pass);
|
||||
log_info("user", "{$user->class->name} logged in");
|
||||
$page->set_mode("redirect");
|
||||
|
||||
// Try returning to previous page
|
||||
|
@ -358,7 +359,6 @@ class UserPage extends Extension {
|
|||
}
|
||||
}
|
||||
else {
|
||||
log_warning("user", "Failed to log in as ".html_escape($name));
|
||||
$this->theme->display_error(401, "Error", "No user with those details was found");
|
||||
}
|
||||
}
|
||||
|
@ -587,6 +587,21 @@ class UserPage extends Extension {
|
|||
return $rows;
|
||||
}
|
||||
|
||||
private function count_log_ips(User $duser): array {
|
||||
if(!class_exists('LogDatabase')) return array();
|
||||
global $database;
|
||||
$rows = $database->get_pairs("
|
||||
SELECT
|
||||
address,
|
||||
COUNT(id) AS count,
|
||||
MAX(date_sent) AS most_recent
|
||||
FROM score_log
|
||||
WHERE username=:username
|
||||
GROUP BY address
|
||||
ORDER BY most_recent DESC", array("username"=>$duser->name));
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private function delete_user(Page $page, bool $with_images=false, bool $with_comments=false) {
|
||||
global $user, $config, $database;
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ class UserPageTheme extends Themelet {
|
|||
$page->add_block(new Block("Login", $html, "left", 90));
|
||||
}
|
||||
|
||||
public function display_ip_list(Page $page, array $uploads, array $comments) {
|
||||
public function display_ip_list(Page $page, array $uploads, array $comments, array $events) {
|
||||
$html = "<table id='ip-history'>";
|
||||
$html .= "<tr><td>Uploaded from: ";
|
||||
$n = 0;
|
||||
|
@ -190,8 +190,18 @@ class UserPageTheme extends Themelet {
|
|||
}
|
||||
}
|
||||
|
||||
$html .= "</td><td>Logged Events:";
|
||||
$n = 0;
|
||||
foreach($events as $ip => $count) {
|
||||
$html .= '<br>'.$ip.' ('.$count.')';
|
||||
if(++$n >= 20) {
|
||||
$html .= "<br>...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$html .= "</td></tr>";
|
||||
$html .= "<tr><td colspan='2'>(Most recent at top)</td></tr></table>";
|
||||
$html .= "<tr><td colspan='3'>(Most recent at top)</td></tr></table>";
|
||||
|
||||
$page->add_block(new Block("IPs", $html, "main", 70));
|
||||
}
|
||||
|
|
|
@ -107,4 +107,5 @@ catch(Exception $e) {
|
|||
_fatal_error($e);
|
||||
$_shm_ctx->log_ender();
|
||||
}
|
||||
log_slow();
|
||||
|
||||
|
|
Reference in a new issue