mirror of
https://github.com/vichan-devel/vichan.git
synced 2025-02-17 19:29:28 +01:00
Merge pull request #453 from czaks/smart-build
Smart build and a few more optimizations
This commit is contained in:
commit
64e3f488d6
6
.gitignore
vendored
6
.gitignore
vendored
@ -40,6 +40,12 @@ Thumbs.db
|
||||
*.orig
|
||||
*~
|
||||
|
||||
# tmp filesystem
|
||||
/tmp/cache/*
|
||||
/tmp/locks/*
|
||||
!/tmp/cache/.gitkeep
|
||||
!/tmp/locks/.gitkeep
|
||||
|
||||
#vichan custom
|
||||
favicon.ico
|
||||
/static/spoiler.png
|
||||
|
2
404.php
2
404.php
@ -3,6 +3,8 @@
|
||||
require_once "inc/functions.php";
|
||||
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
|
||||
|
||||
global $config;
|
||||
|
||||
$dir = "static/404/";
|
||||
|
||||
if (!is_dir($dir))
|
||||
|
@ -54,3 +54,23 @@ function human_time_diff( $from, $to = '' ) {
|
||||
|
||||
return $since;
|
||||
}
|
||||
|
||||
function is_billion_laughs($arr1, $arr2) {
|
||||
$arr = array();
|
||||
foreach ($arr1 as $k => $v) {
|
||||
$arr[$v] = $arr2[$k];
|
||||
}
|
||||
|
||||
for ($i = 0; $i <= sizeof($arr); $i++) {
|
||||
$cur = array_slice($arr, $i, 1);
|
||||
$pst = array_slice($arr, 0, $i);
|
||||
if (!$cur) continue;
|
||||
$kk = array_keys($cur)[0];
|
||||
$vv = array_values($cur)[0];
|
||||
foreach ($pst as $k => $v) {
|
||||
if (str_replace($kk, $vv, $v) != $v)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
53
inc/8chan-mod-config.php
Normal file
53
inc/8chan-mod-config.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
$config['mod']['show_ip'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['show_ip_less'] = BOARDVOLUNTEER;
|
||||
$config['mod']['manageusers'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['noticeboard_post'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['search'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['clean_global'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['view_notes'] = DISABLED;
|
||||
$config['mod']['create_notes'] = DISABLED;
|
||||
$config['mod']['edit_config'] = DISABLED;
|
||||
$config['mod']['debug_recent'] = ADMIN;
|
||||
$config['mod']['debug_antispam'] = ADMIN;
|
||||
$config['mod']['noticeboard_post'] = ADMIN;
|
||||
$config['mod']['modlog'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['mod_board_log'] = MOD;
|
||||
$config['mod']['editpost'] = BOARDVOLUNTEER;
|
||||
$config['mod']['edit_banners'] = MOD;
|
||||
$config['mod']['edit_flags'] = MOD;
|
||||
$config['mod']['edit_settings'] = MOD;
|
||||
$config['mod']['edit_volunteers'] = MOD;
|
||||
$config['mod']['edit_tags'] = MOD;
|
||||
$config['mod']['clean'] = BOARDVOLUNTEER;
|
||||
// new perms
|
||||
|
||||
$config['mod']['ban'] = BOARDVOLUNTEER;
|
||||
$config['mod']['bandelete'] = BOARDVOLUNTEER;
|
||||
$config['mod']['unban'] = BOARDVOLUNTEER;
|
||||
$config['mod']['deletebyip'] = BOARDVOLUNTEER;
|
||||
$config['mod']['sticky'] = BOARDVOLUNTEER;
|
||||
$config['mod']['cycle'] = BOARDVOLUNTEER;
|
||||
$config['mod']['lock'] = BOARDVOLUNTEER;
|
||||
$config['mod']['postinlocked'] = BOARDVOLUNTEER;
|
||||
$config['mod']['bumplock'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_bumplock'] = BOARDVOLUNTEER;
|
||||
$config['mod']['bypass_field_disable'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_banlist'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_banstaff'] = BOARDVOLUNTEER;
|
||||
$config['mod']['public_ban'] = BOARDVOLUNTEER;
|
||||
$config['mod']['recent'] = BOARDVOLUNTEER;
|
||||
$config['mod']['ban_appeals'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_ban_appeals'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_ban'] = BOARDVOLUNTEER;
|
||||
$config['mod']['reassign_board'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['move'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['shadow_capcode'] = 'Global Volunteer';
|
||||
|
||||
// Mod pages assignment
|
||||
$config['mod']['custom_pages']['/tags/(\%b)'] = '8_tags';
|
||||
$config['mod']['custom_pages']['/reassign/(\%b)'] = '8_reassign';
|
||||
$config['mod']['custom_pages']['/volunteers/(\%b)'] = '8_volunteers';
|
||||
$config['mod']['custom_pages']['/flags/(\%b)'] = '8_flags';
|
||||
$config['mod']['custom_pages']['/banners/(\%b)'] = '8_banners';
|
||||
$config['mod']['custom_pages']['/settings/(\%b)'] = '8_settings';
|
@ -1,73 +1,5 @@
|
||||
<?php
|
||||
if (!function_exists('is_billion_laughs')){
|
||||
function is_billion_laughs($arr1, $arr2) {
|
||||
$arr = array();
|
||||
foreach ($arr1 as $k => $v) {
|
||||
$arr[$v] = $arr2[$k];
|
||||
}
|
||||
|
||||
for ($i = 0; $i <= sizeof($arr); $i++) {
|
||||
$cur = array_slice($arr, $i, 1);
|
||||
$pst = array_slice($arr, 0, $i);
|
||||
if (!$cur) continue;
|
||||
$kk = array_keys($cur)[0];
|
||||
$vv = array_values($cur)[0];
|
||||
foreach ($pst as $k => $v) {
|
||||
if (str_replace($kk, $vv, $v) != $v)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$config['mod']['show_ip'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['show_ip_less'] = BOARDVOLUNTEER;
|
||||
$config['mod']['manageusers'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['noticeboard_post'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['search'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['clean_global'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['view_notes'] = DISABLED;
|
||||
$config['mod']['create_notes'] = DISABLED;
|
||||
$config['mod']['edit_config'] = DISABLED;
|
||||
$config['mod']['debug_recent'] = ADMIN;
|
||||
$config['mod']['debug_antispam'] = ADMIN;
|
||||
$config['mod']['noticeboard_post'] = ADMIN;
|
||||
$config['mod']['modlog'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['mod_board_log'] = MOD;
|
||||
$config['mod']['editpost'] = BOARDVOLUNTEER;
|
||||
$config['mod']['edit_banners'] = MOD;
|
||||
$config['mod']['edit_flags'] = MOD;
|
||||
$config['mod']['edit_settings'] = MOD;
|
||||
$config['mod']['edit_volunteers'] = MOD;
|
||||
$config['mod']['edit_tags'] = MOD;
|
||||
$config['mod']['clean'] = BOARDVOLUNTEER;
|
||||
// new perms
|
||||
|
||||
$config['mod']['ban'] = BOARDVOLUNTEER;
|
||||
$config['mod']['bandelete'] = BOARDVOLUNTEER;
|
||||
$config['mod']['unban'] = BOARDVOLUNTEER;
|
||||
$config['mod']['deletebyip'] = BOARDVOLUNTEER;
|
||||
$config['mod']['sticky'] = BOARDVOLUNTEER;
|
||||
$config['mod']['cycle'] = BOARDVOLUNTEER;
|
||||
$config['mod']['lock'] = BOARDVOLUNTEER;
|
||||
$config['mod']['postinlocked'] = BOARDVOLUNTEER;
|
||||
$config['mod']['bumplock'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_bumplock'] = BOARDVOLUNTEER;
|
||||
$config['mod']['bypass_field_disable'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_banlist'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_banstaff'] = BOARDVOLUNTEER;
|
||||
$config['mod']['public_ban'] = BOARDVOLUNTEER;
|
||||
$config['mod']['recent'] = BOARDVOLUNTEER;
|
||||
$config['mod']['ban_appeals'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_ban_appeals'] = BOARDVOLUNTEER;
|
||||
$config['mod']['view_ban'] = BOARDVOLUNTEER;
|
||||
$config['mod']['reassign_board'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['move'] = GLOBALVOLUNTEER;
|
||||
$config['mod']['shadow_capcode'] = 'Global Volunteer';
|
||||
|
||||
|
||||
$config['mod']['custom_pages']['/tags/(\%b)'] = function ($b) {
|
||||
function mod_8_tags ($b) {
|
||||
global $board, $config;
|
||||
|
||||
if (!openBoard($b))
|
||||
@ -114,9 +46,9 @@
|
||||
$sfw = $query->fetchColumn();
|
||||
|
||||
mod_page(_('Edit tags'), 'mod/tags.html', array('board'=>$board,'token'=>make_secure_link_token('tags/'.$board['uri']), 'tags'=>$tags, 'sfw'=>$sfw));
|
||||
};
|
||||
}
|
||||
|
||||
$config['mod']['custom_pages']['/reassign/(\%b)'] = function($b) {
|
||||
function mod_8_reassign($b) {
|
||||
global $board, $config;
|
||||
|
||||
if (!openBoard($b))
|
||||
@ -147,9 +79,9 @@
|
||||
modLog("Reassigned board /$b/");
|
||||
|
||||
mod_page(_('Edit reassign'), 'blank.html', array('board'=>$board,'token'=>make_secure_link_token('reassign/'.$board['uri']),'body'=>$body));
|
||||
};
|
||||
}
|
||||
|
||||
$config['mod']['custom_pages']['/volunteers/(\%b)'] = function($b) {
|
||||
function mod_8_volunteers($b) {
|
||||
global $board, $config, $pdo;
|
||||
if (!hasPermission($config['mod']['edit_volunteers'], $b))
|
||||
error($config['error']['noaccess']);
|
||||
@ -228,9 +160,9 @@
|
||||
|
||||
mod_page(_('Edit volunteers'), 'mod/volunteers.html', array('board'=>$board,'token'=>make_secure_link_token('volunteers/'.$board['uri']),'volunteers'=>$volunteers));
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
$config['mod']['custom_pages']['/flags/(\%b)'] = function($b) {
|
||||
function mod_8_flags($b) {
|
||||
global $config, $mod, $board;
|
||||
require_once 'inc/image.php';
|
||||
if (!hasPermission($config['mod']['edit_flags'], $b))
|
||||
@ -341,6 +273,11 @@
|
||||
\$config['user_flags'] = unserialize(file_get_contents('$b/flags.ser'));
|
||||
FLAGS;
|
||||
|
||||
if ($config['cache']['enabled']) {
|
||||
cache::delete('config_' . $b);
|
||||
cache::delete('events_' . $b);
|
||||
}
|
||||
|
||||
file_write($b.'/flags.php', $flags);
|
||||
}
|
||||
|
||||
@ -364,9 +301,9 @@ FLAGS;
|
||||
|
||||
$banners = array_diff(scandir($dir), array('..', '.'));
|
||||
mod_page(_('Edit flags'), 'mod/flags.html', array('board'=>$board,'banners'=>$banners,'token'=>make_secure_link_token('banners/'.$board['uri'])));
|
||||
};
|
||||
}
|
||||
|
||||
$config['mod']['custom_pages']['/banners/(\%b)'] = function($b) {
|
||||
function mod_8_banners($b) {
|
||||
global $config, $mod, $board;
|
||||
require_once 'inc/image.php';
|
||||
|
||||
@ -427,9 +364,9 @@ FLAGS;
|
||||
$banners = array_diff(scandir($dir), array('..', '.'));
|
||||
mod_page(_('Edit banners'), 'mod/banners.html', array('board'=>$board,'banners'=>$banners,'token'=>make_secure_link_token('banners/'.$board['uri'])));
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
$config['mod']['custom_pages']['/settings/(\%b)'] = function($b) {
|
||||
function mod_8_settings($b) {
|
||||
global $config, $mod;
|
||||
|
||||
//if ($b === 'infinity' && $mod['type'] !== ADMIN)
|
||||
@ -661,6 +598,7 @@ EOT;
|
||||
// Faster than openBoard and bypasses cache...we're trusting the PHP output
|
||||
// to be safe enough to run with every request, we can eval it here.
|
||||
eval(str_replace('flags.php', "$b/flags.php", preg_replace('/^\<\?php$/m', '', $config_file)));
|
||||
// czaks: maybe reconsider using it, now that config is cached?
|
||||
|
||||
// be smarter about rebuilds...only some changes really require us to rebuild all threads
|
||||
if ($_config['captcha']['enabled'] != $config['captcha']['enabled']
|
||||
@ -683,13 +621,18 @@ EOT;
|
||||
$query->bindValue(':board', $b);
|
||||
$query->execute() or error(db_error($query));
|
||||
$board = $query->fetchAll()[0];
|
||||
|
||||
$css = @file_get_contents('stylesheets/board/' . $board['uri'] . '.css');
|
||||
|
||||
|
||||
// Clean the cache
|
||||
if ($config['cache']['enabled']) {
|
||||
cache::delete('board_' . $board['uri']);
|
||||
cache::delete('all_boards');
|
||||
}
|
||||
|
||||
cache::delete('config_' . $board['uri']);
|
||||
cache::delete('events_' . $board['uri']);
|
||||
unlink('tmp/cache/locale_' . $board['uri']);
|
||||
}
|
||||
|
||||
$css = @file_get_contents('stylesheets/board/' . $board['uri'] . '.css');
|
||||
|
||||
mod_page(_('Board configuration'), 'mod/settings.html', array('board'=>$board, 'css'=>prettify_textarea($css), 'token'=>make_secure_link_token('settings/'.$board['uri']), 'languages'=>$possible_languages,'allowed_urls'=>$config['allowed_offsite_urls']));
|
||||
};
|
||||
}
|
||||
|
@ -50,6 +50,17 @@ class Cache {
|
||||
case 'php':
|
||||
$data = isset(self::$cache[$key]) ? self::$cache[$key] : false;
|
||||
break;
|
||||
case 'fs':
|
||||
$key = str_replace('/', '::', $key);
|
||||
$key = str_replace("\0", '', $key);
|
||||
if (!file_exists('tmp/cache/'.$key)) {
|
||||
$data = false;
|
||||
}
|
||||
else {
|
||||
$data = file_get_contents('tmp/cache/'.$key);
|
||||
$data = json_decode($data, true);
|
||||
}
|
||||
break;
|
||||
case 'redis':
|
||||
if (!self::$cache)
|
||||
self::init();
|
||||
@ -87,6 +98,11 @@ class Cache {
|
||||
case 'xcache':
|
||||
xcache_set($key, $value, $expires);
|
||||
break;
|
||||
case 'fs':
|
||||
$key = str_replace('/', '::', $key);
|
||||
$key = str_replace("\0", '', $key);
|
||||
file_put_contents('tmp/cache/'.$key, json_encode($value));
|
||||
break;
|
||||
case 'php':
|
||||
self::$cache[$key] = $value;
|
||||
break;
|
||||
@ -113,6 +129,11 @@ class Cache {
|
||||
case 'xcache':
|
||||
xcache_unset($key);
|
||||
break;
|
||||
case 'fs':
|
||||
$key = str_replace('/', '::', $key);
|
||||
$key = str_replace("\0", '', $key);
|
||||
@unlink('tmp/cache/'.$key);
|
||||
break;
|
||||
case 'php':
|
||||
unset(self::$cache[$key]);
|
||||
break;
|
||||
@ -134,6 +155,12 @@ class Cache {
|
||||
case 'php':
|
||||
self::$cache = array();
|
||||
break;
|
||||
case 'fs':
|
||||
$files = glob('tmp/cache/*');
|
||||
foreach ($files as $file) {
|
||||
unlink($file);
|
||||
}
|
||||
break;
|
||||
case 'redis':
|
||||
if (!self::$cache)
|
||||
self::init();
|
||||
|
@ -132,6 +132,11 @@
|
||||
// Tinyboard to use.
|
||||
$config['cache']['redis'] = array('localhost', 6379, '', 1);
|
||||
|
||||
// EXPERIMENTAL: Should we cache configs? Warning: this changes board behaviour, i'd say, a lot.
|
||||
// If you have any lambdas/includes present in your config, you should move them to instance-functions.php
|
||||
// (this file will be explicitly loaded during cache hit, but not during cache miss).
|
||||
$config['cache_config'] = false;
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Cookie settings
|
||||
@ -1239,9 +1244,20 @@
|
||||
// Website favicon.
|
||||
$config['url_favicon'] = 'static/favicon.ico';
|
||||
|
||||
// EXPERIMENTAL: Try not to build pages when we shouldn't have to.
|
||||
// Try not to build pages when we shouldn't have to.
|
||||
$config['try_smarter'] = true;
|
||||
|
||||
// EXPERIMENTAL: Defer static HTML building to a moment, when a given file is actually accessed.
|
||||
// Warning: This option won't run out of the box. You need to tell your webserver, that a file
|
||||
// for serving 403 and 404 pages is /smart_build.php. Also, you need to turn off indexes.
|
||||
$config['smart_build'] = false;
|
||||
|
||||
// Smart build related: when a file doesn't exist, where should we redirect?
|
||||
$config['page_404'] = '/404.html';
|
||||
|
||||
// Smart build related: extra entrypoints.
|
||||
$config['smart_build_entrypoints'] = array();
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Mod settings
|
||||
|
@ -19,7 +19,9 @@ require_once 'inc/database.php';
|
||||
require_once 'inc/events.php';
|
||||
require_once 'inc/api.php';
|
||||
require_once 'inc/bans.php';
|
||||
require_once 'inc/lib/gettext/gettext.inc';
|
||||
if (!extension_loaded('gettext')) {
|
||||
require_once 'inc/lib/gettext/gettext.inc';
|
||||
}
|
||||
require_once 'inc/lib/parsedown/Parsedown.php'; // todo: option for parsedown instead of Tinyboard/STI markup
|
||||
require_once 'inc/mod/auth.php';
|
||||
|
||||
@ -50,15 +52,42 @@ $current_locale = 'en';
|
||||
|
||||
|
||||
function loadConfig() {
|
||||
global $board, $config, $__ip, $debug, $__version, $microtime_start, $current_locale;
|
||||
global $board, $config, $__ip, $debug, $__version, $microtime_start, $current_locale, $events;
|
||||
|
||||
$error = function_exists('error') ? 'error' : 'basic_error_function_because_the_other_isnt_loaded_yet';
|
||||
|
||||
reset_events();
|
||||
$boardsuffix = isset($board['uri']) ? $board['uri'] : '';
|
||||
|
||||
if (!isset($_SERVER['REMOTE_ADDR']))
|
||||
$_SERVER['REMOTE_ADDR'] = '0.0.0.0';
|
||||
|
||||
if (file_exists('tmp/cache/cache_config.php')) {
|
||||
require_once('tmp/cache/cache_config.php');
|
||||
}
|
||||
|
||||
|
||||
if (isset($config['cache_config']) &&
|
||||
$config['cache_config'] &&
|
||||
$config = Cache::get('config_' . $boardsuffix ) ) {
|
||||
$events = Cache::get('events_' . $boardsuffix );
|
||||
|
||||
define_groups();
|
||||
|
||||
if (file_exists('inc/instance-functions.php')) {
|
||||
require_once('inc/instance-functions.php');
|
||||
}
|
||||
|
||||
if ($config['locale'] != $current_locale) {
|
||||
$current_locale = $config['locale'];
|
||||
init_locale($config['locale'], $error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$config = array();
|
||||
// We will indent that later.
|
||||
|
||||
reset_events();
|
||||
|
||||
$arrays = array(
|
||||
'db',
|
||||
'api',
|
||||
@ -86,7 +115,6 @@ function loadConfig() {
|
||||
'dashboard_links'
|
||||
);
|
||||
|
||||
$config = array();
|
||||
foreach ($arrays as $key) {
|
||||
$config[$key] = array();
|
||||
}
|
||||
@ -96,18 +124,28 @@ function loadConfig() {
|
||||
|
||||
// Initialize locale as early as possible
|
||||
|
||||
$config['locale'] = 'en';
|
||||
// Those calls are expensive. Unfortunately, our cache system is not initialized at this point.
|
||||
// So, we may store the locale in a tmp/ filesystem.
|
||||
|
||||
$configstr = file_get_contents('inc/instance-config.php');
|
||||
if (file_exists($fn = 'tmp/cache/locale_' . $boardsuffix ) ) {
|
||||
$config['locale'] = file_get_contents($fn);
|
||||
}
|
||||
else {
|
||||
$config['locale'] = 'en';
|
||||
|
||||
$configstr = file_get_contents('inc/instance-config.php');
|
||||
|
||||
if (isset($board['dir']) && file_exists($board['dir'] . '/config.php')) {
|
||||
$configstr .= file_get_contents($board['dir'] . '/config.php');
|
||||
$configstr .= file_get_contents($board['dir'] . '/config.php');
|
||||
}
|
||||
$matches = array();
|
||||
preg_match_all('/[^\/*#]\$config\s*\[\s*[\'"]locale[\'"]\s*\]\s*=\s*([\'"])(.*?)\1/', $configstr, $matches);
|
||||
if ($matches && isset ($matches[2]) && $matches[2]) {
|
||||
$matches = $matches[2];
|
||||
$config['locale'] = $matches[count($matches)-1];
|
||||
$matches = array();
|
||||
preg_match_all('/[^\/*#]\$config\s*\[\s*[\'"]locale[\'"]\s*\]\s*=\s*([\'"])(.*?)\1/', $configstr, $matches);
|
||||
if ($matches && isset ($matches[2]) && $matches[2]) {
|
||||
$matches = $matches[2];
|
||||
$config['locale'] = $matches[count($matches)-1];
|
||||
}
|
||||
|
||||
file_put_contents($fn, $config['locale']);
|
||||
}
|
||||
|
||||
if ($config['locale'] != $current_locale) {
|
||||
@ -128,18 +166,13 @@ function loadConfig() {
|
||||
init_locale($config['locale'], $error);
|
||||
}
|
||||
|
||||
if (!isset($__version))
|
||||
$__version = file_exists('.installed') ? trim(file_get_contents('.installed')) : false;
|
||||
$config['version'] = $__version;
|
||||
|
||||
date_default_timezone_set($config['timezone']);
|
||||
|
||||
if (!isset($config['global_message']))
|
||||
$config['global_message'] = false;
|
||||
|
||||
if (!isset($config['post_url']))
|
||||
$config['post_url'] = $config['root'] . $config['file_post'];
|
||||
|
||||
|
||||
if (!isset($config['referer_match']))
|
||||
if (isset($_SERVER['HTTP_HOST'])) {
|
||||
$config['referer_match'] = '/^' .
|
||||
@ -210,19 +243,26 @@ function loadConfig() {
|
||||
if (!isset($config['user_flags']))
|
||||
$config['user_flags'] = array();
|
||||
|
||||
if (!isset($__version))
|
||||
$__version = file_exists('.installed') ? trim(file_get_contents('.installed')) : false;
|
||||
$config['version'] = $__version;
|
||||
|
||||
if ($config['allow_roll'])
|
||||
event_handler('post', 'diceRoller');
|
||||
|
||||
if (is_array($config['anonymous']))
|
||||
$config['anonymous'] = $config['anonymous'][array_rand($config['anonymous'])];
|
||||
|
||||
|
||||
}
|
||||
// Effectful config processing below:
|
||||
|
||||
date_default_timezone_set($config['timezone']);
|
||||
|
||||
if ($config['root_file']) {
|
||||
chdir($config['root_file']);
|
||||
}
|
||||
|
||||
if ($config['verbose_errors']) {
|
||||
set_error_handler('verbose_error_handler');
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', true);
|
||||
ini_set('html_errors', false);
|
||||
} else {
|
||||
ini_set('display_errors', false);
|
||||
}
|
||||
|
||||
// Keep the original address to properly comply with other board configurations
|
||||
if (!isset($__ip))
|
||||
$__ip = $_SERVER['REMOTE_ADDR'];
|
||||
@ -231,11 +271,21 @@ function loadConfig() {
|
||||
if (preg_match('/^\:\:(ffff\:)?(\d+\.\d+\.\d+\.\d+)$/', $__ip, $m))
|
||||
$_SERVER['REMOTE_ADDR'] = $m[2];
|
||||
|
||||
if ($config['verbose_errors']) {
|
||||
set_error_handler('verbose_error_handler');
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', true);
|
||||
ini_set('html_errors', false);
|
||||
} else {
|
||||
ini_set('display_errors', false);
|
||||
}
|
||||
|
||||
if ($config['syslog'])
|
||||
openlog('tinyboard', LOG_ODELAY, LOG_SYSLOG); // open a connection to sysem logger
|
||||
|
||||
if ($config['recaptcha'])
|
||||
require_once 'inc/lib/recaptcha/recaptchalib.php';
|
||||
|
||||
if ($config['cache']['enabled'])
|
||||
require_once 'inc/cache.php';
|
||||
|
||||
@ -244,13 +294,22 @@ function loadConfig() {
|
||||
event_handler('post', 'postHandler');
|
||||
}
|
||||
|
||||
if (is_array($config['anonymous']))
|
||||
$config['anonymous'] = $config['anonymous'][array_rand($config['anonymous'])];
|
||||
|
||||
if ($config['allow_roll'])
|
||||
event_handler('post', 'diceRoller');
|
||||
|
||||
event('load-config');
|
||||
|
||||
if ($config['cache_config'] && !isset ($config['cache_config_loaded'])) {
|
||||
file_put_contents('tmp/cache/cache_config.php', '<?php '.
|
||||
'$config = array();'.
|
||||
'$config[\'cache\'] = '.var_export($config['cache'], true).';'.
|
||||
'$config[\'cache_config\'] = true;'.
|
||||
'$config[\'debug\'] = '.var_export($config['debug'], true).';'.
|
||||
'require_once(\'inc/cache.php\');'
|
||||
);
|
||||
|
||||
$config['cache_config_loaded'] = true;
|
||||
|
||||
Cache::set('config_'.$boardsuffix, $config);
|
||||
Cache::set('events_'.$boardsuffix, $events);
|
||||
}
|
||||
|
||||
if ($config['debug']) {
|
||||
if (!isset($debug)) {
|
||||
@ -327,8 +386,12 @@ function verbose_error_handler($errno, $errstr, $errfile, $errline) {
|
||||
function define_groups() {
|
||||
global $config;
|
||||
|
||||
foreach ($config['mod']['groups'] as $group_value => $group_name)
|
||||
defined($group_name) or define($group_name, $group_value, true);
|
||||
foreach ($config['mod']['groups'] as $group_value => $group_name) {
|
||||
$group_name = strtoupper($group_name);
|
||||
if(!defined($group_name)) {
|
||||
define($group_name, $group_value, true);
|
||||
}
|
||||
}
|
||||
|
||||
ksort($config['mod']['groups']);
|
||||
}
|
||||
@ -347,9 +410,22 @@ function rebuildThemes($action, $boardname = false) {
|
||||
$_board = $board;
|
||||
|
||||
// List themes
|
||||
$query = query("SELECT `theme` FROM ``theme_settings`` WHERE `name` IS NULL AND `value` IS NULL") or error(db_error());
|
||||
if ($themes = Cache::get("themes")) {
|
||||
// OK, we already have themes loaded
|
||||
}
|
||||
else {
|
||||
$query = query("SELECT `theme` FROM ``theme_settings`` WHERE `name` IS NULL AND `value` IS NULL") or error(db_error());
|
||||
|
||||
while ($theme = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
$themes = array();
|
||||
|
||||
while ($theme = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
$themes[] = $theme;
|
||||
}
|
||||
|
||||
Cache::set("themes", $themes);
|
||||
}
|
||||
|
||||
foreach ($themes as $theme) {
|
||||
// Restore them
|
||||
$config = $_config;
|
||||
$board = $_board;
|
||||
@ -403,6 +479,10 @@ function rebuildTheme($theme, $action, $board = false) {
|
||||
|
||||
|
||||
function themeSettings($theme) {
|
||||
if ($settings = Cache::get("theme_settings_".$theme)) {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
$query = prepare("SELECT `name`, `value` FROM ``theme_settings`` WHERE `theme` = :theme AND `name` IS NOT NULL");
|
||||
$query->bindValue(':theme', $theme);
|
||||
$query->execute() or error(db_error($query));
|
||||
@ -412,6 +492,8 @@ function themeSettings($theme) {
|
||||
$settings[$s['name']] = $s['value'];
|
||||
}
|
||||
|
||||
Cache::set("theme_settings_".$theme, $settings);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
@ -469,6 +551,11 @@ function openBoard($uri) {
|
||||
$board = getBoardInfo($uri);
|
||||
if ($board) {
|
||||
setupBoard($board);
|
||||
|
||||
if (function_exists('after_open_board')) {
|
||||
after_open_board();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -630,6 +717,13 @@ function file_unlink($path) {
|
||||
}
|
||||
|
||||
$ret = @unlink($path);
|
||||
|
||||
if ($config['gzip_static']) {
|
||||
$gzpath = "$path.gz";
|
||||
|
||||
@unlink($gzpath);
|
||||
}
|
||||
|
||||
if (isset($config['purge']) && $path[0] != '/' && isset($_SERVER['HTTP_HOST'])) {
|
||||
// Purge cache
|
||||
if (basename($path) == $config['file_index']) {
|
||||
@ -1004,8 +1098,9 @@ function bumpThread($id) {
|
||||
if (event('bump', $id))
|
||||
return true;
|
||||
|
||||
if ($config['try_smarter'])
|
||||
$build_pages[] = thread_find_page($id);
|
||||
if ($config['try_smarter']) {
|
||||
$build_pages = array_merge(range(1, thread_find_page($id)), $build_pages);
|
||||
}
|
||||
|
||||
$query = prepare(sprintf("UPDATE ``posts_%s`` SET `bump` = :time WHERE `id` = :id AND `thread` IS NULL", $board['uri']));
|
||||
$query->bindValue(':time', time(), PDO::PARAM_INT);
|
||||
@ -1491,56 +1586,65 @@ function checkMute() {
|
||||
}
|
||||
}
|
||||
|
||||
function buildIndex() {
|
||||
function buildIndex($global_api = "yes") {
|
||||
global $board, $config, $build_pages;
|
||||
|
||||
$pages = getPages();
|
||||
if (!$config['try_smarter'])
|
||||
$antibot = create_antibot($board['uri']);
|
||||
if (!$config['smart_build']) {
|
||||
$pages = getPages();
|
||||
if (!$config['try_smarter'])
|
||||
$antibot = create_antibot($board['uri']);
|
||||
|
||||
if ($config['api']['enabled']) {
|
||||
$api = new Api();
|
||||
$catalog = array();
|
||||
if ($config['api']['enabled']) {
|
||||
$api = new Api();
|
||||
$catalog = array();
|
||||
}
|
||||
}
|
||||
|
||||
for ($page = 1; $page <= $config['max_pages']; $page++) {
|
||||
$filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page));
|
||||
$jsonFilename = $board['dir'] . ($page - 1) . '.json'; // pages should start from 0
|
||||
|
||||
if (!$config['api']['enabled'] && $config['try_smarter'] && isset($build_pages) && !empty($build_pages)
|
||||
&& !in_array($page, $build_pages) && is_file($filename))
|
||||
continue;
|
||||
$content = index($page);
|
||||
if (!$content)
|
||||
break;
|
||||
|
||||
// json api
|
||||
if ($config['api']['enabled']) {
|
||||
$threads = $content['threads'];
|
||||
$json = json_encode($api->translatePage($threads));
|
||||
$jsonFilename = $board['dir'] . ($page - 1) . '.json'; // pages should start from 0
|
||||
file_write($jsonFilename, $json);
|
||||
|
||||
$catalog[$page-1] = $threads;
|
||||
}
|
||||
|
||||
if ($config['api']['enabled'] && $config['try_smarter'] && isset($build_pages) && !empty($build_pages)
|
||||
&& !in_array($page, $build_pages) && is_file($filename))
|
||||
if ((!$config['api']['enabled'] || $global_api == "skip" || $config['smart_build']) && $config['try_smarter']
|
||||
&& isset($build_pages) && !empty($build_pages) && !in_array($page, $build_pages) )
|
||||
continue;
|
||||
|
||||
if ($config['try_smarter']) {
|
||||
$antibot = create_antibot($board['uri'], 0 - $page);
|
||||
$content['current_page'] = $page;
|
||||
}
|
||||
$antibot->reset();
|
||||
$content['pages'] = $pages;
|
||||
$content['pages'][$page-1]['selected'] = true;
|
||||
$content['btn'] = getPageButtons($content['pages']);
|
||||
$content['antibot'] = $antibot;
|
||||
if (!$config['smart_build']) {
|
||||
$content = index($page);
|
||||
if (!$content)
|
||||
break;
|
||||
|
||||
file_write($filename, Element('index.html', $content));
|
||||
// json api
|
||||
if ($config['api']['enabled']) {
|
||||
$threads = $content['threads'];
|
||||
$json = json_encode($api->translatePage($threads));
|
||||
file_write($jsonFilename, $json);
|
||||
|
||||
$catalog[$page-1] = $threads;
|
||||
}
|
||||
|
||||
if ($config['api']['enabled'] && $global_api != "skip" && $config['try_smarter'] && isset($build_pages)
|
||||
&& !empty($build_pages) && !in_array($page, $build_pages) )
|
||||
continue;
|
||||
|
||||
if ($config['try_smarter']) {
|
||||
$antibot = create_antibot($board['uri'], 0 - $page);
|
||||
$content['current_page'] = $page;
|
||||
}
|
||||
$antibot->reset();
|
||||
$content['pages'] = $pages;
|
||||
$content['pages'][$page-1]['selected'] = true;
|
||||
$content['btn'] = getPageButtons($content['pages']);
|
||||
$content['antibot'] = $antibot;
|
||||
|
||||
file_write($filename, Element('index.html', $content));
|
||||
}
|
||||
else {
|
||||
file_unlink($filename);
|
||||
file_unlink($jsonFilename);
|
||||
}
|
||||
}
|
||||
|
||||
if ($page < $config['max_pages']) {
|
||||
if (!$config['smart_build'] && $page < $config['max_pages']) {
|
||||
for (;$page<=$config['max_pages'];$page++) {
|
||||
$filename = $board['dir'] . ($page==1 ? $config['file_index'] : sprintf($config['file_page'], $page));
|
||||
file_unlink($filename);
|
||||
@ -1553,14 +1657,22 @@ function buildIndex() {
|
||||
}
|
||||
|
||||
// json api catalog
|
||||
if ($config['api']['enabled']) {
|
||||
$json = json_encode($api->translateCatalog($catalog));
|
||||
$jsonFilename = $board['dir'] . 'catalog.json';
|
||||
file_write($jsonFilename, $json);
|
||||
if ($config['api']['enabled'] && $global_api != "skip") {
|
||||
if ($config['smart_build']) {
|
||||
$jsonFilename = $board['dir'] . 'catalog.json';
|
||||
file_unlink($jsonFilename);
|
||||
$jsonFilename = $board['dir'] . 'threads.json';
|
||||
file_unlink($jsonFilename);
|
||||
}
|
||||
else {
|
||||
$json = json_encode($api->translateCatalog($catalog));
|
||||
$jsonFilename = $board['dir'] . 'catalog.json';
|
||||
file_write($jsonFilename, $json);
|
||||
|
||||
$json = json_encode($api->translateCatalog($catalog, true));
|
||||
$jsonFilename = $board['dir'] . 'threads.json';
|
||||
file_write($jsonFilename, $json);
|
||||
$json = json_encode($api->translateCatalog($catalog, true));
|
||||
$jsonFilename = $board['dir'] . 'threads.json';
|
||||
file_write($jsonFilename, $json);
|
||||
}
|
||||
}
|
||||
|
||||
if ($config['try_smarter'])
|
||||
@ -2049,51 +2161,62 @@ function buildThread($id, $return = false, $mod = false) {
|
||||
cache::delete("thread_{$board['uri']}_{$id}");
|
||||
}
|
||||
|
||||
$query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id`", $board['uri']));
|
||||
$query->bindValue(':id', $id, PDO::PARAM_INT);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
if (!isset($thread)) {
|
||||
$thread = new Thread($post, $mod ? '?/' : $config['root'], $mod);
|
||||
} else {
|
||||
$thread->add(new Post($post, $mod ? '?/' : $config['root'], $mod));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any posts were found
|
||||
if (!isset($thread))
|
||||
error($config['error']['nonexistant']);
|
||||
|
||||
$hasnoko50 = $thread->postCount() >= $config['noko50_min'];
|
||||
$antibot = $mod || $return ? false : create_antibot($board['uri'], $id);
|
||||
|
||||
$body = Element('thread.html', array(
|
||||
'board' => $board,
|
||||
'thread' => $thread,
|
||||
'body' => $thread->build(),
|
||||
'config' => $config,
|
||||
'id' => $id,
|
||||
'mod' => $mod,
|
||||
'hasnoko50' => $hasnoko50,
|
||||
'isnoko50' => false,
|
||||
'antibot' => $antibot,
|
||||
'boardlist' => createBoardlist($mod),
|
||||
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
|
||||
));
|
||||
|
||||
if ($config['try_smarter'] && !$mod)
|
||||
$build_pages[] = thread_find_page($id);
|
||||
|
||||
// json api
|
||||
if ($config['api']['enabled']) {
|
||||
$api = new Api();
|
||||
$json = json_encode($api->translateThread($thread));
|
||||
if (!$config['smart_build'] || $return || $mod) {
|
||||
$query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id`", $board['uri']));
|
||||
$query->bindValue(':id', $id, PDO::PARAM_INT);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
if (!isset($thread)) {
|
||||
$thread = new Thread($post, $mod ? '?/' : $config['root'], $mod);
|
||||
} else {
|
||||
$thread->add(new Post($post, $mod ? '?/' : $config['root'], $mod));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any posts were found
|
||||
if (!isset($thread))
|
||||
error($config['error']['nonexistant']);
|
||||
|
||||
$hasnoko50 = $thread->postCount() >= $config['noko50_min'];
|
||||
$antibot = $mod || $return ? false : create_antibot($board['uri'], $id);
|
||||
|
||||
$body = Element('thread.html', array(
|
||||
'board' => $board,
|
||||
'thread' => $thread,
|
||||
'body' => $thread->build(),
|
||||
'config' => $config,
|
||||
'id' => $id,
|
||||
'mod' => $mod,
|
||||
'hasnoko50' => $hasnoko50,
|
||||
'isnoko50' => false,
|
||||
'antibot' => $antibot,
|
||||
'boardlist' => createBoardlist($mod),
|
||||
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
|
||||
));
|
||||
|
||||
// json api
|
||||
if ($config['api']['enabled']) {
|
||||
$api = new Api();
|
||||
$json = json_encode($api->translateThread($thread));
|
||||
$jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json';
|
||||
file_write($jsonFilename, $json);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json';
|
||||
file_write($jsonFilename, $json);
|
||||
file_unlink($jsonFilename);
|
||||
}
|
||||
|
||||
if ($return) {
|
||||
if ($config['smart_build'] && !$return && !$mod) {
|
||||
$noko50fn = $board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id);
|
||||
file_unlink($noko50fn);
|
||||
|
||||
file_unlink($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $id));
|
||||
} else if ($return) {
|
||||
return $body;
|
||||
} else {
|
||||
$noko50fn = $board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id);
|
||||
|
@ -7,9 +7,6 @@
|
||||
*
|
||||
* You can copy values from config.php (defaults) and paste them here.
|
||||
*/
|
||||
require_once "lib/htmlpurifier-4.6.0/library/HTMLPurifier.auto.php";
|
||||
require_once "8chan-functions.php";
|
||||
|
||||
// Note - you may want to change some of these in secrets.php instead of here
|
||||
// See the secrets.example.php file
|
||||
$config['db']['server'] = 'localhost';
|
||||
@ -177,19 +174,7 @@
|
||||
$config['hour_max_threads'] = 10;
|
||||
$config['filters'][] = array(
|
||||
'condition' => array(
|
||||
'custom' => function($post) {
|
||||
global $config, $board;
|
||||
if (!$config['hour_max_threads']) return false;
|
||||
|
||||
if ($post['op']) {
|
||||
$query = prepare(sprintf('SELECT COUNT(*) AS `count` FROM ``posts_%s`` WHERE `thread` IS NULL AND FROM_UNIXTIME(`time`) > DATE_SUB(NOW(), INTERVAL 1 HOUR);', $board['uri']));
|
||||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
|
||||
$query->execute() or error(db_error($query));
|
||||
$r = $query->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
return ($r['count'] > $config['hour_max_threads']);
|
||||
}
|
||||
}
|
||||
'custom' => 'max_posts_per_hour'
|
||||
),
|
||||
'action' => 'reject',
|
||||
'message' => 'On this board, to prevent raids the number of threads that can be created per hour is limited. Please try again later, or post in an existing thread.'
|
||||
@ -212,9 +197,14 @@ $config['enable_antibot'] = false;
|
||||
$config['spam']['unicode'] = false;
|
||||
$config['twig_cache'] = false;
|
||||
$config['report_captcha'] = true;
|
||||
|
||||
$config['page_404'] = 'page_404';
|
||||
|
||||
// 8chan specific mod pages
|
||||
require '8chan-mod-pages.php';
|
||||
require '8chan-mod-config.php';
|
||||
|
||||
// Load instance functions later on
|
||||
require_once 'instance-functions.php';
|
||||
|
||||
// Load database credentials
|
||||
require "secrets.php";
|
||||
|
||||
|
24
inc/instance-functions.php
Normal file
24
inc/instance-functions.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
require_once("inc/8chan-functions.php");
|
||||
require_once("inc/8chan-mod-pages.php");
|
||||
|
||||
require_once "lib/htmlpurifier-4.6.0/library/HTMLPurifier.auto.php";
|
||||
|
||||
|
||||
function max_posts_per_hour($post) {
|
||||
global $config, $board;
|
||||
if (!$config['hour_max_threads']) return false;
|
||||
|
||||
if ($post['op']) {
|
||||
$query = prepare(sprintf('SELECT COUNT(*) AS `count` FROM ``posts_%s`` WHERE `thread` IS NULL AND FROM_UNIXTIME(`time`) > DATE_SUB(NOW(), INTERVAL 1 HOUR);', $board['uri']));
|
||||
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
|
||||
$query->execute() or error(db_error($query));
|
||||
$r = $query->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
return ($r['count'] > $config['hour_max_threads']);
|
||||
}
|
||||
}
|
||||
|
||||
function page_404() {
|
||||
include('404.php');
|
||||
}
|
@ -3333,10 +3333,14 @@ function mod_theme_configure($theme_name) {
|
||||
$query->bindValue(':value', $_POST[$conf['name']]);
|
||||
$query->execute() or error(db_error($query));
|
||||
}
|
||||
|
||||
|
||||
$query = prepare("INSERT INTO ``theme_settings`` VALUES(:theme, NULL, NULL)");
|
||||
$query->bindValue(':theme', $theme_name);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
// Clean cache
|
||||
Cache::delete("themes");
|
||||
Cache::delete("theme_settings_".$theme);
|
||||
|
||||
$result = true;
|
||||
$message = false;
|
||||
@ -3384,11 +3388,15 @@ function mod_theme_uninstall($theme_name) {
|
||||
|
||||
if (!hasPermission($config['mod']['themes']))
|
||||
error($config['error']['noaccess']);
|
||||
|
||||
|
||||
$query = prepare("DELETE FROM ``theme_settings`` WHERE `theme` = :theme");
|
||||
$query->bindValue(':theme', $theme_name);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
// Clean cache
|
||||
Cache::delete("themes");
|
||||
Cache::delete("theme_settings_".$theme);
|
||||
|
||||
header('Location: ?/themes', true, $config['redirect_http']);
|
||||
}
|
||||
|
||||
|
200
smart_build.php
Normal file
200
smart_build.php
Normal file
@ -0,0 +1,200 @@
|
||||
<?php
|
||||
require_once("inc/functions.php");
|
||||
|
||||
if (!$config['smart_build']) {
|
||||
die('You need to enable $config["smart_build"]');
|
||||
}
|
||||
|
||||
$config['smart_build'] = false; // Let's disable it, so we can build the page for real
|
||||
|
||||
function after_open_board() { global $config;
|
||||
$config['smart_build'] = false;
|
||||
};
|
||||
|
||||
function sb_board($b, $page = 1) { global $config, $build_pages; $page = (int)$page;
|
||||
if ($page < 1) return false;
|
||||
if (!openBoard($b)) return false;
|
||||
if ($page > $config['max_pages']) return false;
|
||||
$config['try_smarter'] = true;
|
||||
$build_pages = array($page);
|
||||
buildIndex("skip");
|
||||
return true;
|
||||
}
|
||||
|
||||
function sb_api_board($b, $page = 0) { $page = (int)$page;
|
||||
return sb_board($b, $page + 1);
|
||||
}
|
||||
|
||||
function sb_thread($b, $thread, $slugcheck = false) { global $config; $thread = (int)$thread;
|
||||
if ($thread < 1) return false;
|
||||
|
||||
if (!preg_match('/^'.$config['board_regex'].'$/u', $b)) return false;
|
||||
|
||||
if (Cache::get("thread_exists_".$b."_".$thread) == "no") return false;
|
||||
|
||||
$query = prepare(sprintf("SELECT MAX(`id`) AS `max` FROM ``posts_%s``", $b));
|
||||
if (!$query->execute()) return false;
|
||||
|
||||
$s = $query->fetch(PDO::FETCH_ASSOC);
|
||||
$max = $s['max'];
|
||||
|
||||
if ($thread > $max) return false;
|
||||
|
||||
$query = prepare(sprintf("SELECT `id` FROM ``posts_%s`` WHERE `id` = :id AND `thread` IS NULL", $b));
|
||||
$query->bindValue(':id', $thread);
|
||||
|
||||
if (!$query->execute() || !$query->fetch(PDO::FETCH_ASSOC) ) {
|
||||
Cache::set("thread_exists_".$b."_".$thread, "no");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($slugcheck == 50) { // Should we really generate +50 page? Maybe there are not enough posts anyway
|
||||
global $request;
|
||||
$r = str_replace("+50", "", $request);
|
||||
$r = substr($r, 1); // Cut the slash
|
||||
|
||||
if (file_exists($r)) return false;
|
||||
}
|
||||
|
||||
if (!openBoard($b)) return false;
|
||||
buildThread($thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
function sb_thread_slugcheck50($b, $thread) {
|
||||
return sb_thread($b, $thread, 50);
|
||||
}
|
||||
|
||||
function sb_api($b) { global $config;
|
||||
if (!openBoard($b)) return false;
|
||||
$config['try_smarter'] = true;
|
||||
$build_pages = array(-1);
|
||||
buildIndex();
|
||||
return true;
|
||||
}
|
||||
|
||||
function sb_ukko() {
|
||||
rebuildTheme("ukko", "post-thread");
|
||||
return true;
|
||||
}
|
||||
|
||||
function sb_catalog($b) {
|
||||
if (!openBoard($b)) return false;
|
||||
|
||||
rebuildTheme("catalog", "post-thread", $b);
|
||||
return true;
|
||||
}
|
||||
|
||||
function sb_recent() {
|
||||
rebuildTheme("recent", "post-thread");
|
||||
return true;
|
||||
}
|
||||
|
||||
function sb_sitemap() {
|
||||
rebuildTheme("sitemap", "all");
|
||||
return true;
|
||||
}
|
||||
|
||||
$entrypoints = array();
|
||||
|
||||
$entrypoints['/%b/'] = 'sb_board';
|
||||
$entrypoints['/%b/'.$config['file_index']] = 'sb_board';
|
||||
$entrypoints['/%b/'.$config['file_page']] = 'sb_board';
|
||||
$entrypoints['/%b/%d.json'] = 'sb_api_board';
|
||||
if ($config['api']['enabled']) {
|
||||
$entrypoints['/%b/threads.json'] = 'sb_api';
|
||||
$entrypoints['/%b/catalog.json'] = 'sb_api';
|
||||
}
|
||||
|
||||
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page']] = 'sb_thread';
|
||||
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page50']] = 'sb_thread_slugcheck50';
|
||||
if ($config['api']['enabled']) {
|
||||
$entrypoints['/%b/'.$config['dir']['res'].'%d.json'] = 'sb_thread';
|
||||
}
|
||||
|
||||
$entrypoints['/*/'] = 'sb_ukko';
|
||||
$entrypoints['/*/index.html'] = 'sb_ukko';
|
||||
$entrypoints['/recent.html'] = 'sb_recent';
|
||||
$entrypoints['/%b/catalog.html'] = 'sb_catalog';
|
||||
$entrypoints['/sitemap.xml'] = 'sb_sitemap';
|
||||
|
||||
$reached = false;
|
||||
|
||||
$request = $_SERVER['REQUEST_URI'];
|
||||
list($request) = explode('?', $request);
|
||||
|
||||
foreach ($entrypoints as $id => $fun) {
|
||||
$id = '@^' . preg_quote($id, '@') . '$@u';
|
||||
|
||||
$id = str_replace('%b', '('.$config['board_regex'].')', $id);
|
||||
$id = str_replace('%d', '([0-9]+)', $id);
|
||||
$id = str_replace('%s', '[a-zA-Z0-9-]+', $id);
|
||||
|
||||
$matches = null;
|
||||
|
||||
if (preg_match ($id, $request, $matches)) {
|
||||
array_shift($matches);
|
||||
|
||||
$reached = call_user_func_array($fun, $matches);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function die_404() { global $config;
|
||||
if (!$config['page_404']) {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
header("Status: 404 Not Found");
|
||||
echo "<h1>404 Not Found</h1><p>Page doesn't exist<hr><address>vichan</address>";
|
||||
}
|
||||
elseif (is_callable($config['page_404'])) {
|
||||
$config['page_404']();
|
||||
}
|
||||
else {
|
||||
header("Location: ".$config['page_404']);
|
||||
}
|
||||
header("X-Accel-Expires: 120");
|
||||
die();
|
||||
}
|
||||
|
||||
if ($reached) {
|
||||
if ($request[strlen($request)-1] == '/') {
|
||||
$request .= 'index.html';
|
||||
}
|
||||
$request = '.'.$request;
|
||||
|
||||
if (!file_exists($request)) {
|
||||
die_404();
|
||||
}
|
||||
|
||||
header("HTTP/1.1 200 OK");
|
||||
header("Status: 200 OK");
|
||||
if (preg_match('/\.json$/', $request)) {
|
||||
header("Content-Type", "application/json");
|
||||
}
|
||||
elseif (preg_match('/\.js$/', $request)) {
|
||||
header("Content-Type", "text/javascript; charset=utf-8");
|
||||
}
|
||||
elseif (preg_match('/\.xml$/', $request)) {
|
||||
header("Content-Type", "application/xml");
|
||||
}
|
||||
else {
|
||||
header("Content-Type", "text/html; charset=utf-8");
|
||||
}
|
||||
header("Cache-Control: public, nocache, no-cache, max-age=0, must-revalidate");
|
||||
header("Expires: Fri, 22 Feb 1991 06:00:00 GMT");
|
||||
header("Last-Modified: ".date('r', filemtime($request)));
|
||||
|
||||
//if (isset ($_SERVER['HTTP_ACCEPT_ENCODING']) && preg_match('/gzip/', $_SERVER['HTTP_ACCEPT_ENCODING']) && file_exists($request.".gz")) {
|
||||
// header("Content-Encoding: gzip");
|
||||
// $file = fopen($request.".gz", 'r');
|
||||
//}
|
||||
//else {
|
||||
$file = fopen($request, 'r');
|
||||
//}
|
||||
fpassthru($file);
|
||||
fclose($file);
|
||||
}
|
||||
else {
|
||||
die_404();
|
||||
}
|
@ -20,12 +20,25 @@
|
||||
if ($action == 'all') {
|
||||
foreach ($boards as $board) {
|
||||
$b = new Catalog();
|
||||
$b->build($settings, $board);
|
||||
|
||||
if ($config['smart_build']) {
|
||||
file_unlink($config['dir']['home'] . $board . '/catalog.html');
|
||||
}
|
||||
else {
|
||||
$b->build($settings, $board);
|
||||
}
|
||||
|
||||
if (php_sapi_name() === "cli") echo "Rebuilding $board catalog...\n";
|
||||
}
|
||||
} elseif ($action == 'post-thread' || ($settings['update_on_posts'] && $action == 'post') || ($settings['update_on_posts'] && $action == 'post-delete') && (in_array($board, $boards) | $settings['all'])) {
|
||||
$b = new Catalog();
|
||||
$b->build($settings, $board);
|
||||
|
||||
if ($config['smart_build']) {
|
||||
file_unlink($config['dir']['home'] . $board . '/catalog.html');
|
||||
}
|
||||
else {
|
||||
$b->build($settings, $board);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,8 +46,12 @@
|
||||
class Catalog {
|
||||
public function build($settings, $board_name) {
|
||||
global $config, $board;
|
||||
|
||||
openBoard($board_name);
|
||||
|
||||
if ($board['uri'] != $board_name) {
|
||||
if (!openBoard($board_name)) {
|
||||
error(sprintf(_("Board %s doesn't exist"), $board_name));
|
||||
}
|
||||
}
|
||||
|
||||
$recent_images = array();
|
||||
$recent_posts = array();
|
||||
|
@ -24,8 +24,14 @@
|
||||
|
||||
$this->excluded = explode(' ', $settings['exclude']);
|
||||
|
||||
if ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete')
|
||||
file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings));
|
||||
if ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') {
|
||||
if ($config['smart_build']) {
|
||||
file_unlink($config['dir']['home'] . $settings['html']);
|
||||
}
|
||||
else {
|
||||
file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build news page
|
||||
|
@ -10,30 +10,37 @@
|
||||
// - boards (board list changed)
|
||||
// - post (a post has been made)
|
||||
// - thread (a thread has been made)
|
||||
|
||||
if ($action != 'all') {
|
||||
if ($action != 'post-thread' && $action != 'post-delete')
|
||||
return;
|
||||
|
||||
if ($action != 'post-thread' && $action != 'post-delete')
|
||||
return;
|
||||
|
||||
if (isset($settings['regen_time']) && $settings['regen_time'] > 0) {
|
||||
if ($last_gen = @filemtime($settings['path'])) {
|
||||
if (time() - $last_gen < (int)$settings['regen_time'])
|
||||
return; // Too soon
|
||||
if (isset($settings['regen_time']) && $settings['regen_time'] > 0) {
|
||||
if ($last_gen = @filemtime($settings['path'])) {
|
||||
if (time() - $last_gen < (int)$settings['regen_time'])
|
||||
return; // Too soon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$boards = explode(' ', $settings['boards']);
|
||||
|
||||
$threads = array();
|
||||
|
||||
foreach ($boards as $board) {
|
||||
$query = query(sprintf("SELECT `id` AS `thread_id`, (SELECT `time` FROM ``posts_%s`` WHERE `thread` = `thread_id` OR `id` = `thread_id` ORDER BY `time` DESC LIMIT 1) AS `lastmod` FROM ``posts_%s`` WHERE `thread` IS NULL", $board, $board)) or error(db_error());
|
||||
$threads[$board] = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($config['smart_build']) {
|
||||
file_unlink($settings['path']);
|
||||
}
|
||||
else {
|
||||
$boards = explode(' ', $settings['boards']);
|
||||
|
||||
$threads = array();
|
||||
|
||||
foreach ($boards as $board) {
|
||||
$query = query(sprintf("SELECT `id` AS `thread_id`, (SELECT `time` FROM ``posts_%s`` WHERE `thread` = `thread_id` OR `id` = `thread_id` ORDER BY `time` DESC LIMIT 1) AS `lastmod` FROM ``posts_%s`` WHERE `thread` IS NULL", $board, $board)) or error(db_error());
|
||||
$threads[$board] = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
file_write($settings['path'], Element('themes/sitemap/sitemap.xml', Array(
|
||||
'settings' => $settings,
|
||||
'config' => $config,
|
||||
'threads' => $threads,
|
||||
'boards' => $boards,
|
||||
)));
|
||||
file_write($settings['path'], Element('themes/sitemap/sitemap.xml', Array(
|
||||
'settings' => $settings,
|
||||
'config' => $config,
|
||||
'threads' => $threads,
|
||||
'boards' => $boards,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,7 @@
|
||||
function ukko_install($settings) {
|
||||
if (!file_exists($settings['uri']))
|
||||
@mkdir($settings['uri'], 0777) or error("Couldn't create " . $settings['uri'] . ". Check permissions.", true);
|
||||
file_write($settings['uri'] . '/ukko.js', Element('themes/ukko/ukko.js', array()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
require 'info.php';
|
||||
|
||||
function ukko_build($action, $settings) {
|
||||
global $config;
|
||||
|
||||
$ukko = new ukko();
|
||||
$ukko->settings = $settings;
|
||||
|
||||
@ -9,8 +11,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
file_write($settings['uri'] . '/index.html', $ukko->build());
|
||||
file_write($settings['uri'] . '/ukko.js', Element('themes/ukko/ukko.js', array()));
|
||||
if ($config['smart_build']) {
|
||||
file_unlink($settings['uri'] . '/index.html');
|
||||
}
|
||||
else {
|
||||
file_write($settings['uri'] . '/index.html', $ukko->build());
|
||||
}
|
||||
}
|
||||
|
||||
class ukko {
|
||||
|
0
tmp/cache/.gitkeep
vendored
Normal file
0
tmp/cache/.gitkeep
vendored
Normal file
0
tmp/locks/.gitkeep
Normal file
0
tmp/locks/.gitkeep
Normal file
Loading…
x
Reference in New Issue
Block a user