mirror of
https://github.com/Circlepuller/Tinyboard.git
synced 2025-01-16 21:08:30 +01:00
Removed a lot of unnecessary code.
This commit is contained in:
parent
f677a7c013
commit
4be8f91f3b
@ -1,357 +0,0 @@
|
||||
<?php
|
||||
class CzaksCaptcha {
|
||||
var $content = array();
|
||||
|
||||
var $width, $height, $color, $charset, $style;
|
||||
|
||||
function __construct($text, $left, $top, $charset=false) {
|
||||
if (!$charset) {
|
||||
$charset = 'abcdefghijklmnopqrstuvwxyz';
|
||||
}
|
||||
|
||||
$len = mb_strlen($text, 'utf-8');
|
||||
|
||||
$this->width = $left;
|
||||
$this->height = $top;
|
||||
|
||||
$this->charset = preg_split('//u', $charset);
|
||||
|
||||
$this->style = "";
|
||||
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$this->content[] = array(mb_substr($text, $i, 1, 'utf-8'), "top" => $top / 2 - $top / 4,
|
||||
"left" => $left/10 + 9*$left*$i/10/$len,
|
||||
"position" => "absolute");
|
||||
}
|
||||
|
||||
$this->color = "hsla(".rand(1,360).", 76%, 78%, 1)";
|
||||
|
||||
$this->add_junk();
|
||||
$this->mutate_sizes();
|
||||
$this->mutate_positions();
|
||||
$this->mutate_transform();
|
||||
$this->mutate_anchors();
|
||||
$this->randomize();
|
||||
$this->mutate_containers();
|
||||
$this->mutate_margins();
|
||||
$this->mutate_styles();
|
||||
$this->randomize();
|
||||
}
|
||||
|
||||
function mutate_sizes() {
|
||||
foreach ($this->content as &$v) {
|
||||
if (!isset ($v['font-size']))
|
||||
$v['font-size'] = rand($this->height/3 - 4, $this->height/3 + 8);
|
||||
}
|
||||
}
|
||||
function mutate_positions() {
|
||||
foreach ($this->content as &$v) {
|
||||
$v['top'] += rand(-10,10);
|
||||
$v['left'] += rand(-10,10);
|
||||
}
|
||||
}
|
||||
function mutate_transform() {
|
||||
$fromto = array('6'=>'9', '9'=>'6', '8'=>'8', '0'=>'0',
|
||||
'z'=>'z', 's'=>'s', 'n'=>'u', 'u'=>'n',
|
||||
'a'=>'ɐ', 'e'=>'ə', 'p'=>'d', 'd'=>'p',
|
||||
'A'=>'∀', 'E'=>'∃', 'H'=>'H', 'o'=>'o',
|
||||
'O'=>'O');
|
||||
|
||||
foreach ($this->content as &$v) {
|
||||
$basefrom = -20;
|
||||
$baseto = 20;
|
||||
|
||||
if (isset($fromto[$v[0]]) && rand(0,1)) {
|
||||
$v[0] = $fromto[$v[0]];
|
||||
$basefrom = 160;
|
||||
$baseto = 200;
|
||||
}
|
||||
|
||||
$v['transform'] = 'rotate('.rand($basefrom,$baseto).'deg)';
|
||||
$v['-ms-transform'] = 'rotate('.rand($basefrom,$baseto).'deg)';
|
||||
$v['-webkit-transform'] = 'rotate('.rand($basefrom,$baseto).'deg)';
|
||||
}
|
||||
}
|
||||
function randomize(&$a = false) {
|
||||
if ($a === false) {
|
||||
$a = &$this->content;
|
||||
}
|
||||
|
||||
shuffle($a);
|
||||
|
||||
foreach ($a as &$v) {
|
||||
$this->shuffle_assoc($v);
|
||||
|
||||
if (is_array ($v[0])) {
|
||||
$this->randomize($v[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function add_junk() {
|
||||
$count = rand(200, 300);
|
||||
|
||||
while ($count--) {
|
||||
$elem = array();
|
||||
|
||||
$elem['top'] = rand(0, $this->height);
|
||||
$elem['left'] = rand(0, $this->width);
|
||||
|
||||
$elem['position'] = 'absolute';
|
||||
|
||||
$elem[0] = $this->charset[rand(0, count($this->charset)-1)];
|
||||
|
||||
switch($t = rand (0,9)) {
|
||||
case 0:
|
||||
$elem['display'] = 'none'; break;
|
||||
case 1:
|
||||
$elem['top'] = rand(-60, -90); break;
|
||||
case 2:
|
||||
$elem['left'] = rand(-40, -70); break;
|
||||
case 3:
|
||||
$elem['top'] = $this->height + rand(10, 60); break;
|
||||
case 4:
|
||||
$elem['left'] = $this->width + rand(10, 60); break;
|
||||
case 5:
|
||||
$elem['color'] = $this->color; break;
|
||||
case 6:
|
||||
$elem['visibility'] = 'hidden'; break;
|
||||
case 7:
|
||||
$elem['height'] = rand(0,2);
|
||||
$elem['overflow'] = 'hidden'; break;
|
||||
case 8:
|
||||
$elem['width'] = rand(0,1);
|
||||
$elem['overflow'] = 'hidden'; break;
|
||||
case 9:
|
||||
$elem['font-size'] = rand(2, 6); break;
|
||||
}
|
||||
|
||||
$this->content[] = $elem;
|
||||
}
|
||||
}
|
||||
|
||||
function mutate_anchors() {
|
||||
foreach ($this->content as &$elem) {
|
||||
if (rand(0,1)) {
|
||||
$elem['right'] = $this->width - $elem['left'] - (int)(0.5*$elem['font-size']);
|
||||
unset($elem['left']);
|
||||
}
|
||||
if (rand(0,1)) {
|
||||
$elem['bottom'] = $this->height - $elem['top'] - (int)(1.5*$elem['font-size']);
|
||||
unset($elem['top']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mutate_containers() {
|
||||
for ($i = 0; $i <= 80; $i++) {
|
||||
$new = [];
|
||||
$new['width'] = rand(0, $this->width*2);
|
||||
$new['height'] = rand(0, $this->height*2);
|
||||
$new['top'] = rand(-$this->height * 2, $this->height * 2);
|
||||
$new['bottom'] = $this->height - ($new['top'] + $new['height']);
|
||||
$new['left'] = rand(-$this->width * 2, $this->width * 2);
|
||||
$new['right'] = $this->width - ($new['left'] + $new['width']);
|
||||
|
||||
$new['position'] = 'absolute';
|
||||
|
||||
$new[0] = [];
|
||||
|
||||
$cnt = rand(0,10);
|
||||
for ($j = 0; $j < $cnt; $j++) {
|
||||
$elem = array_pop($this->content);
|
||||
if (!$elem) break;
|
||||
|
||||
if (isset($elem['top'])) $elem['top'] -= $new['top'];
|
||||
if (isset($elem['bottom'])) $elem['bottom'] -= $new['bottom'];
|
||||
if (isset($elem['left'])) $elem['left'] -= $new['left'];
|
||||
if (isset($elem['right'])) $elem['right'] -= $new['right'];
|
||||
|
||||
$new[0][] = $elem;
|
||||
}
|
||||
|
||||
if (rand (0,1)) unset($new['top']);
|
||||
else unset($new['bottom']);
|
||||
if (rand (0,1)) unset($new['left']);
|
||||
else unset($new['right']);
|
||||
|
||||
$this->content[] = $new;
|
||||
|
||||
shuffle($this->content);
|
||||
}
|
||||
}
|
||||
|
||||
function mutate_margins(&$a = false) {
|
||||
if ($a === false) {
|
||||
$a = &$this->content;
|
||||
}
|
||||
|
||||
foreach ($a as &$v) {
|
||||
$ary = ['top', 'left', 'bottom', 'right'];
|
||||
shuffle($ary);
|
||||
$cnt = rand(0,4);
|
||||
$ary = array_slice($ary, 0, $cnt);
|
||||
|
||||
foreach ($ary as $prop) {
|
||||
$margin = rand(-1000, 1000);
|
||||
|
||||
$v['margin-'.$prop] = $margin;
|
||||
|
||||
if (isset($v[$prop])) {
|
||||
$v[$prop] -= $margin;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($v[0])) {
|
||||
$this->mutate_margins($v[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mutate_styles(&$a = false) {
|
||||
if ($a === false) {
|
||||
$a = &$this->content;
|
||||
}
|
||||
|
||||
foreach ($a as &$v) {
|
||||
$content = $v[0];
|
||||
unset($v[0]);
|
||||
$styles = array_splice($v, 0, rand(0, 6));
|
||||
$v[0] = $content;
|
||||
|
||||
$id_or_class = rand(0,1);
|
||||
$param = $id_or_class ? "id" : "class";
|
||||
$prefix = $id_or_class ? "#" : ".";
|
||||
$genname = "zz-".base_convert(rand(1,999999999), 10, 36);
|
||||
|
||||
if ($styles || rand(0,1)) {
|
||||
$this->style .= $prefix.$genname."{";
|
||||
$this->style .= $this->rand_whitespace();
|
||||
|
||||
foreach ($styles as $k => $val) {
|
||||
if (is_int($val)) {
|
||||
$val = "".$val."px";
|
||||
}
|
||||
|
||||
$this->style .= "$k:";
|
||||
$this->style .= $this->rand_whitespace();
|
||||
$this->style .= "$val;";
|
||||
$this->style .= $this->rand_whitespace();
|
||||
}
|
||||
$this->style .= "}";
|
||||
$this->style .= $this->rand_whitespace();
|
||||
}
|
||||
|
||||
$v[$param] = $genname;
|
||||
|
||||
if (is_array($v[0])) {
|
||||
$this->mutate_styles($v[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function to_html(&$a = false) {
|
||||
$inside = true;
|
||||
|
||||
if ($a === false) {
|
||||
if ($this->style) {
|
||||
echo "<style type='text/css'>";
|
||||
echo $this->style;
|
||||
echo "</style>";
|
||||
}
|
||||
|
||||
echo "<div style='position: relative; width: ".$this->width."px; height: ".$this->height."px; overflow: hidden; background-color: ".$this->color."'>";
|
||||
$a = &$this->content;
|
||||
$inside = false;
|
||||
}
|
||||
|
||||
foreach ($a as &$v) {
|
||||
$letter = $v[0];
|
||||
|
||||
unset ($v[0]);
|
||||
|
||||
echo "<div";
|
||||
echo $this->rand_whitespace(1);
|
||||
|
||||
if (isset ($v['id'])) {
|
||||
echo "id='$v[id]'";
|
||||
echo $this->rand_whitespace(1);
|
||||
|
||||
unset ($v['id']);
|
||||
}
|
||||
if (isset ($v['class'])) {
|
||||
echo "class='$v[class]'";
|
||||
echo $this->rand_whitespace(1);
|
||||
|
||||
unset ($v['class']);
|
||||
}
|
||||
|
||||
echo "style='";
|
||||
|
||||
foreach ($v as $k => $val) {
|
||||
if (is_int($val)) {
|
||||
$val = "".$val."px";
|
||||
}
|
||||
|
||||
echo "$k:";
|
||||
echo $this->rand_whitespace();
|
||||
echo "$val;";
|
||||
echo $this->rand_whitespace();
|
||||
|
||||
}
|
||||
|
||||
echo "'>";
|
||||
echo $this->rand_whitespace();
|
||||
|
||||
if (is_array ($letter)) {
|
||||
$this->to_html($letter);
|
||||
}
|
||||
else {
|
||||
echo $letter;
|
||||
}
|
||||
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
if (!$inside) {
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function rand_whitespace($r = 0) {
|
||||
switch (rand($r,4)) {
|
||||
case 0:
|
||||
return "";
|
||||
case 1:
|
||||
return "\n";
|
||||
case 2:
|
||||
return "\t";
|
||||
case 3:
|
||||
return " ";
|
||||
case 4:
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function shuffle_assoc(&$array) {
|
||||
$keys = array_keys($array);
|
||||
|
||||
shuffle($keys);
|
||||
|
||||
foreach($keys as $key) {
|
||||
$new[$key] = $array[$key];
|
||||
}
|
||||
|
||||
$array = $new;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//$charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789卐";
|
||||
|
||||
//(new CzaksCaptcha("hotwheels", 300, 80, $charset))->to_html();
|
||||
?>
|
@ -1,16 +0,0 @@
|
||||
<?php
|
||||
// We are using a custom path here to connect to the database.
|
||||
// Why? Performance reasons.
|
||||
|
||||
$pdo = new PDO("mysql:dbname=database_name;host=localhost", "database_user", "database_password", array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
|
||||
|
||||
|
||||
// Captcha expiration:
|
||||
$expires_in = 120; // 120 seconds
|
||||
|
||||
// Captcha dimensions:
|
||||
$width = 250;
|
||||
$height = 80;
|
||||
|
||||
// Captcha length:
|
||||
$length = 6;
|
@ -1,9 +0,0 @@
|
||||
SET NAMES utf8;
|
||||
|
||||
CREATE TABLE `captchas` (
|
||||
`cookie` VARCHAR(50),
|
||||
`extra` VARCHAR(200),
|
||||
`text` VARCHAR(255),
|
||||
`created_at` INT(11),
|
||||
PRIMARY KEY (cookie, extra)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
@ -1,85 +0,0 @@
|
||||
<?php
|
||||
$mode = @$_GET['mode'];
|
||||
|
||||
require_once("captcha.php");
|
||||
|
||||
function rand_string($length, $charset) {
|
||||
$ret = "";
|
||||
while ($length--) {
|
||||
$ret .= mb_substr($charset, rand(0, mb_strlen($charset, 'utf-8')-1), 1, 'utf-8');
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function cleanup ($pdo, $expires_in) {
|
||||
$pdo->prepare("DELETE FROM `captchas` WHERE `created_at` < ?")->execute([time() - $expires_in]);
|
||||
}
|
||||
|
||||
switch ($mode) {
|
||||
// Request: GET entrypoint.php?mode=get&extra=1234567890
|
||||
// Response: JSON: cookie => "generatedcookie", captchahtml => "captchahtml", expires_in => 120
|
||||
case "get":
|
||||
if (!isset ($_GET['extra'])) {
|
||||
die();
|
||||
}
|
||||
|
||||
header("Content-type: application/json");
|
||||
|
||||
$extra = $_GET['extra'];
|
||||
|
||||
require_once("config.php");
|
||||
|
||||
$text = rand_string($length, $extra);
|
||||
|
||||
$captcha = new CzaksCaptcha($text, $width, $height, $extra);
|
||||
|
||||
$cookie = rand_string(20, "abcdefghijklmnopqrstuvwxyz");
|
||||
|
||||
ob_start();
|
||||
$captcha->to_html();
|
||||
$html = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$query = $pdo->prepare("INSERT INTO `captchas` (`cookie`, `extra`, `text`, `created_at`) VALUES (?, ?, ?, ?)");
|
||||
$query->execute( [$cookie, $extra, $text, time()]);
|
||||
|
||||
echo json_encode(["cookie" => $cookie, "captchahtml" => $html, "expires_in" => $expires_in]);
|
||||
|
||||
break;
|
||||
|
||||
// Request: GET entrypoint.php?mode=check&cookie=generatedcookie&extra=1234567890&text=captcha
|
||||
// Response: 0 OR 1
|
||||
case "check":
|
||||
if (!isset ($_GET['mode'])
|
||||
|| !isset ($_GET['cookie'])
|
||||
|| !isset ($_GET['extra'])
|
||||
|| !isset ($_GET['text'])) {
|
||||
die();
|
||||
}
|
||||
|
||||
require_once("config.php");
|
||||
|
||||
cleanup($pdo, $expires_in);
|
||||
|
||||
$query = $pdo->prepare("SELECT * FROM `captchas` WHERE `cookie` = ? AND `extra` = ?");
|
||||
$query->execute([$_GET['cookie'], $_GET['extra']]);
|
||||
|
||||
$ary = $query->fetchAll();
|
||||
|
||||
if (!$ary) {
|
||||
echo "0";
|
||||
}
|
||||
else {
|
||||
$query = $pdo->prepare("DELETE FROM `captchas` WHERE `cookie` = ? AND `extra` = ?");
|
||||
$query->execute([$_GET['cookie'], $_GET['extra']]);
|
||||
|
||||
if ($ary[0]['text'] !== $_GET['text']) {
|
||||
echo "0";
|
||||
}
|
||||
else {
|
||||
echo "1";
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
I integrated this from: https://github.com/ctrlcctrlv/infinity/commit/62a6dac022cb338f7b719d0c35a64ab3efc64658
|
||||
|
||||
<strike>First import the captcha/dbschema.sql in your database</strike> it is no longer required.
|
||||
|
||||
In inc/captcha/config.php change the database_name database_user database_password to your own settings.
|
||||
|
||||
Add js/captcha.js in your instance-config.php or config.php
|
||||
|
||||
Go to Line 305 in the /inc/config file and copy the settings in instance config, while changing the url to your website.
|
||||
Go to the line beneath it if you only want to enable it when posting a new thread.
|
146
inc/config.php
146
inc/config.php
@ -103,7 +103,7 @@
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Cache, lock and queue settings
|
||||
* Cache settings
|
||||
* ====================
|
||||
*/
|
||||
|
||||
@ -137,12 +137,6 @@
|
||||
// (this file will be explicitly loaded during cache hit, but not during cache miss).
|
||||
$config['cache_config'] = false;
|
||||
|
||||
// Define a lock driver.
|
||||
$config['lock']['enabled'] = 'fs';
|
||||
|
||||
// Define a queue driver.
|
||||
$config['queue']['enabled'] = 'fs'; // xD
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Cookie settings
|
||||
@ -281,8 +275,6 @@
|
||||
'raw',
|
||||
'embed',
|
||||
'g-recaptcha-response',
|
||||
'captcha_cookie',
|
||||
'captcha_text',
|
||||
'spoiler',
|
||||
'page',
|
||||
'file_url',
|
||||
@ -298,26 +290,6 @@
|
||||
// Public and private key pair from https://www.google.com/recaptcha/admin/create
|
||||
$config['recaptcha_public'] = '6LcXTcUSAAAAAKBxyFWIt2SO8jwx4W7wcSMRoN3f';
|
||||
$config['recaptcha_private'] = '6LcXTcUSAAAAAOGVbVdhmEM1_SyRF4xTKe8jbzf_';
|
||||
|
||||
// Enable Custom Captcha you need to change a couple of settings
|
||||
//Read more at: /captcha/instructions.md
|
||||
$config['captcha'] = array();
|
||||
|
||||
// Enable custom captcha provider
|
||||
$config['captcha']['enabled'] = false;
|
||||
|
||||
//New thread captcha
|
||||
//Require solving a captcha to post a thread.
|
||||
//Default off.
|
||||
$config['new_thread_capt'] = false;
|
||||
|
||||
// Custom captcha get provider path (if not working get the absolute path aka your url.)
|
||||
$config['captcha']['provider_get'] = '../inc/captcha/entrypoint.php';
|
||||
// Custom captcha check provider path
|
||||
$config['captcha']['provider_check'] = '../inc/captcha/entrypoint.php';
|
||||
|
||||
// Custom captcha extra field (eg. charset)
|
||||
$config['captcha']['extra'] = 'abcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
// Ability to lock a board for normal users and still allow mods to post. Could also be useful for making an archive board
|
||||
$config['board_locked'] = false;
|
||||
@ -1025,7 +997,6 @@
|
||||
// $config['additional_javascript'][] = 'js/auto-reload.js';
|
||||
// $config['additional_javascript'][] = 'js/post-hover.js';
|
||||
// $config['additional_javascript'][] = 'js/style-select.js';
|
||||
// $config['additional_javascript'][] = 'js/captcha.js';
|
||||
|
||||
// Where these script files are located on the web. Defaults to $config['root'].
|
||||
// $config['additional_javascript_url'] = 'http://static.example.org/tinyboard-javascript-stuff/';
|
||||
@ -1133,7 +1104,7 @@
|
||||
$config['error']['delete_too_soon'] = _('You\'ll have to wait another %s before deleting that.');
|
||||
$config['error']['mime_exploit'] = _('MIME type detection XSS exploit (IE) detected; post discarded.');
|
||||
$config['error']['invalid_embed'] = _('Couldn\'t make sense of the URL of the video you tried to embed.');
|
||||
$config['error']['captcha'] = _('You seem to have mistyped the verification.');
|
||||
$config['error']['captcha'] = _('You seem to have failed the verification.');
|
||||
|
||||
|
||||
// Moderator errors
|
||||
@ -1236,76 +1207,7 @@
|
||||
|
||||
// Try not to build pages when we shouldn't have to.
|
||||
$config['try_smarter'] = true;
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Advanced build
|
||||
* ====================
|
||||
*/
|
||||
|
||||
// Strategies for file generation. Also known as an "advanced build". If you don't have performance
|
||||
// issues, you can safely ignore that part, because it's hard to configure and won't even work on
|
||||
// your free webhosting.
|
||||
//
|
||||
// A strategy is a function, that given the PHP environment and ($fun, $array) variable pair, returns
|
||||
// an $action array or false.
|
||||
//
|
||||
// $fun - a controller function name, see inc/controller.php. This is named after functions, so that
|
||||
// we can generate the files in daemon.
|
||||
//
|
||||
// $array - arguments to be passed
|
||||
//
|
||||
// $action - action to be taken. It's an array, and the first element of it is one of the following:
|
||||
// * "immediate" - generate the page immediately
|
||||
// * "defer" - defer page generation to a moment a worker daemon gets to build it (serving a stale
|
||||
// page in the meantime). The remaining arguments are daemon-specific. Daemon isn't
|
||||
// implemented yet :DDDD inb4 while(true) { generate(Queue::Get()) }; (which is probably it).
|
||||
// * "build_on_load" - defer page generation to a moment, when the user actually accesses the page.
|
||||
// This is a smart_build behaviour. You shouldn't use this one too much, if you
|
||||
// use it for active boards, the server may choke due to a possible race condition.
|
||||
// See my blog post: https://engine.vichan.net/blog/res/2.html
|
||||
//
|
||||
// So, let's assume we want to build a thread 1324 on board /b/, because a new post appeared there.
|
||||
// We try the first strategy, giving it arguments: 'sb_thread', array('b', 1324). The strategy will
|
||||
// now return a value $action, denoting an action to do. If $action is false, we try another strategy.
|
||||
//
|
||||
// As I said, configuration isn't easy.
|
||||
//
|
||||
// 1. chmod 0777 directories: tmp/locks/ and tmp/queue/.
|
||||
// 2. serve 403 and 404 requests to go thru smart_build.php
|
||||
// for nginx, this blog post contains config snippets: https://engine.vichan.net/blog/res/2.html
|
||||
// 3. disable indexes in your webserver
|
||||
// 4. launch any number of daemons (eg. twice your number of threads?) using the command:
|
||||
// $ tools/worker.php
|
||||
// You don't need to do that step if you are not going to use the "defer" option.
|
||||
// 5. enable smart_build_helper (see below)
|
||||
// 6. edit the strategies (see inc/functions.php for the builtin ones). You can use lambdas. I will test
|
||||
// various ones and include one that works best for me.
|
||||
$config['generation_strategies'] = array();
|
||||
// Add a sane strategy. It forces to immediately generate a page user is about to land on. Otherwise,
|
||||
// it has no opinion, so it needs a fallback strategy.
|
||||
$config['generation_strategies'][] = 'strategy_sane';
|
||||
// Add an immediate catch-all strategy. This is the default function of imageboards: generate all pages
|
||||
// on post time.
|
||||
$config['generation_strategies'][] = 'strategy_immediate';
|
||||
// NOT RECOMMENDED: Instead of an all-"immediate" strategy, you can use an all-"build_on_load" one (used
|
||||
// to be initialized using $config['smart_build']; ) for all pages instead of those to be build
|
||||
// immediately. A rebuild done in this mode should remove all your static files
|
||||
// $config['generation_strategies'][1] = 'strategy_smart_build';
|
||||
|
||||
// Deprecated. Leave it false. See above.
|
||||
$config['smart_build'] = false;
|
||||
|
||||
// Use smart_build.php for dispatching missing requests. It may be useful without smart_build or advanced
|
||||
// build, for example it will regenerate the missing files.
|
||||
$config['smart_build_helper'] = true;
|
||||
|
||||
// smart_build.php: when a file doesn't exist, where should we redirect?
|
||||
$config['page_404'] = '/404.html';
|
||||
|
||||
// Extra controller entrypoints. Controller is used only by smart_build and advanced build.
|
||||
$config['controller_entrypoints'] = array();
|
||||
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Mod settings
|
||||
@ -1706,45 +1608,6 @@
|
||||
// Example: Adding the pre-markup post body to the API as "com_nomarkup".
|
||||
// $config['api']['extra_fields'] = array('body_nomarkup' => 'com_nomarkup');
|
||||
|
||||
/*
|
||||
* ==================
|
||||
* NNTPChan settings
|
||||
* ==================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Please keep in mind that NNTPChan support in vichan isn't finished yet / is in an experimental
|
||||
* state. Please join #nntpchan on Rizon in order to peer with someone.
|
||||
*/
|
||||
|
||||
$config['nntpchan'] = array();
|
||||
|
||||
// Enable NNTPChan integration
|
||||
$config['nntpchan']['enabled'] = false;
|
||||
|
||||
// NNTP server
|
||||
$config['nntpchan']['server'] = "localhost:1119";
|
||||
|
||||
// Global dispatch array. Add your boards to it to enable them. Please make
|
||||
// sure that this setting is set in a global context.
|
||||
$config['nntpchan']['dispatch'] = array(); // 'overchan.test' => 'test'
|
||||
|
||||
// Trusted peer - an IP address of your NNTPChan instance. This peer will have
|
||||
// increased capabilities, eg.: will evade spamfilter.
|
||||
$config['nntpchan']['trusted_peer'] = '127.0.0.1';
|
||||
|
||||
// Salt for message ID generation. Keep it long and secure.
|
||||
$config['nntpchan']['salt'] = 'change_me+please';
|
||||
|
||||
// A local message ID domain. Make sure to change it.
|
||||
$config['nntpchan']['domain'] = 'example.vichan.net';
|
||||
|
||||
// An NNTPChan group name.
|
||||
// Please set this setting in your board/config.php, not globally.
|
||||
$config['nntpchan']['group'] = false; // eg. 'overchan.test'
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ====================
|
||||
* Other/uncategorized
|
||||
@ -1842,8 +1705,5 @@
|
||||
// You can set it to a higher value, to further migrate to other password hashing function.
|
||||
$config['password_crypt_version'] = 1;
|
||||
|
||||
// Use CAPTCHA for reports?
|
||||
$config['report_captcha'] = false;
|
||||
|
||||
// Allowed HTML tags in ?/edit_pages.
|
||||
$config['allowed_html'] = 'a[href|title],p,br,li,ol,ul,strong,em,u,h2,b,i,tt,div,img[src|alt|title],hr';
|
||||
|
@ -1,108 +0,0 @@
|
||||
<?php
|
||||
|
||||
// This file contains the controller part of vichan
|
||||
|
||||
// don't bother with that unless you use smart build or advanced build
|
||||
// you can use those parts for your own implementations though :^)
|
||||
|
||||
defined('TINYBOARD') or exit;
|
||||
|
||||
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", 3600);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($slugcheck && $config['slugify']) {
|
||||
global $request;
|
||||
|
||||
$link = link_for(array("id" => $thread), $slugcheck === 50, array("uri" => $b));
|
||||
$link = "/".$b."/".$config['dir']['res'].$link;
|
||||
|
||||
if ($link != $request) {
|
||||
header("Location: $link", true, 301);
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
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_slugcheck($b, $thread) {
|
||||
return sb_thread($b, $thread, true);
|
||||
}
|
||||
function sb_thread_slugcheck50($b, $thread) {
|
||||
return sb_thread($b, $thread, 50);
|
||||
}
|
||||
|
||||
function sb_api($b) { global $config, $build_pages;
|
||||
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;
|
||||
}
|
||||
|
@ -21,9 +21,6 @@ require_once 'inc/database.php';
|
||||
require_once 'inc/events.php';
|
||||
require_once 'inc/api.php';
|
||||
require_once 'inc/mod/auth.php';
|
||||
require_once 'inc/lock.php';
|
||||
require_once 'inc/queue.php';
|
||||
require_once 'inc/polyfill.php';
|
||||
|
||||
// the user is not currently logged in as a moderator
|
||||
$mod = false;
|
||||
@ -92,8 +89,6 @@ function loadConfig() {
|
||||
'db',
|
||||
'api',
|
||||
'cache',
|
||||
'lock',
|
||||
'queue',
|
||||
'cookies',
|
||||
'error',
|
||||
'dir',
|
||||
@ -564,10 +559,6 @@ function openBoard($uri) {
|
||||
if ($b) {
|
||||
setupBoard($b);
|
||||
|
||||
if (function_exists('after_open_board')) {
|
||||
after_open_board();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1343,7 +1334,7 @@ function thread_find_page($thread) {
|
||||
}
|
||||
|
||||
// $brief means that we won't need to generate anything yet
|
||||
function index($page, $mod=false, $brief = false) {
|
||||
function index($page, $mod=false) {
|
||||
global $board, $config, $debug;
|
||||
|
||||
$body = '';
|
||||
@ -1414,10 +1405,7 @@ function index($page, $mod=false, $brief = false) {
|
||||
}
|
||||
|
||||
$threads[] = $thread;
|
||||
|
||||
if (!$brief) {
|
||||
$body .= $thread->build(true);
|
||||
}
|
||||
$body .= $thread->build(true);
|
||||
}
|
||||
|
||||
if ($config['file_board']) {
|
||||
@ -1639,10 +1627,9 @@ function checkMute() {
|
||||
function buildIndex($global_api = "yes") {
|
||||
global $board, $config, $build_pages;
|
||||
|
||||
$catalog_api_action = generation_strategy('sb_api', array($board['uri']));
|
||||
|
||||
$pages = null;
|
||||
$antibot = null;
|
||||
$pages = getPages();
|
||||
if ($config['try_smarter'])
|
||||
$antibot = create_antibot($board['uri']);
|
||||
|
||||
if ($config['api']['enabled']) {
|
||||
$api = new Api();
|
||||
@ -1653,54 +1640,43 @@ function buildIndex($global_api = "yes") {
|
||||
$filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page));
|
||||
$jsonFilename = $board['dir'] . ($page - 1) . '.json'; // pages should start from 0
|
||||
|
||||
$wont_build_this_page = $config['try_smarter'] && isset($build_pages) && !empty($build_pages) && !in_array($page, $build_pages);
|
||||
|
||||
if ((!$config['api']['enabled'] || $global_api == "skip") && $wont_build_this_page)
|
||||
if ((!$config['api']['enabled'] || $global_api == "skip") && $config['try_smarter'] && isset($build_pages)
|
||||
&& !empty($build_pages) && !in_array($page, $build_pages))
|
||||
continue;
|
||||
|
||||
$action = generation_strategy('sb_board', array($board['uri'], $page));
|
||||
if ($action == 'rebuild' || $catalog_api_action == 'rebuild') {
|
||||
$content = index($page, false, $wont_build_this_page);
|
||||
if (!$content)
|
||||
break;
|
||||
$content = index($page);
|
||||
if (!$content)
|
||||
break;
|
||||
|
||||
// json api
|
||||
if ($config['api']['enabled']) {
|
||||
$threads = $content['threads'];
|
||||
$json = json_encode($api->translatePage($threads));
|
||||
file_write($jsonFilename, $json);
|
||||
// json api
|
||||
if ($config['api']['enabled']) {
|
||||
$threads = $content['threads'];
|
||||
$json = json_encode($api->translatePage($threads));
|
||||
file_write($jsonFilename, $json);
|
||||
|
||||
$catalog[$page-1] = $threads;
|
||||
|
||||
if ($wont_build_this_page) continue;
|
||||
}
|
||||
|
||||
if ($config['try_smarter']) {
|
||||
$antibot = create_antibot($board['uri'], 0 - $page);
|
||||
$content['current_page'] = $page;
|
||||
}
|
||||
elseif (!$antibot) {
|
||||
$antibot = create_antibot($board['uri']);
|
||||
}
|
||||
$antibot->reset();
|
||||
if (!$pages) {
|
||||
$pages = getPages();
|
||||
}
|
||||
$content['pages'] = $pages;
|
||||
$content['pages'][$page-1]['selected'] = true;
|
||||
$content['btn'] = getPageButtons($content['pages']);
|
||||
$content['antibot'] = $antibot;
|
||||
|
||||
file_write($filename, Element('index.html', $content));
|
||||
$catalog[$page-1] = $threads;
|
||||
}
|
||||
elseif ($action == 'delete' || $catalog_api_action == 'delete') {
|
||||
file_unlink($filename);
|
||||
file_unlink($jsonFilename);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
// $action is an action for our last page
|
||||
if (($catalog_api_action == 'rebuild' || $action == 'rebuild' || $action == 'delete') && $page < $config['max_pages']) {
|
||||
if ($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);
|
||||
@ -1714,21 +1690,13 @@ function buildIndex($global_api = "yes") {
|
||||
|
||||
// json api catalog
|
||||
if ($config['api']['enabled'] && $global_api != "skip") {
|
||||
if ($catalog_api_action == 'delete') {
|
||||
$jsonFilename = $board['dir'] . 'catalog.json';
|
||||
file_unlink($jsonFilename);
|
||||
$jsonFilename = $board['dir'] . 'threads.json';
|
||||
file_unlink($jsonFilename);
|
||||
}
|
||||
elseif ($catalog_api_action == 'rebuild') {
|
||||
$json = json_encode($api->translateCatalog($catalog));
|
||||
$jsonFilename = $board['dir'] . 'catalog.json';
|
||||
file_write($jsonFilename, $json);
|
||||
$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'])
|
||||
@ -2237,71 +2205,57 @@ 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,
|
||||
'menu' => createMenu(),
|
||||
'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);
|
||||
|
||||
$action = generation_strategy('sb_thread', array($board['uri'], $id));
|
||||
|
||||
if ($action == 'rebuild' || $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,
|
||||
'menu' => createMenu(),
|
||||
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
|
||||
));
|
||||
|
||||
// json api
|
||||
if ($config['api']['enabled'] && !$mod) {
|
||||
$api = new Api();
|
||||
$json = json_encode($api->translateThread($thread));
|
||||
$jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json';
|
||||
file_write($jsonFilename, $json);
|
||||
}
|
||||
}
|
||||
elseif($action == 'delete') {
|
||||
// json api
|
||||
if ($config['api']['enabled'] && !$mod) {
|
||||
$api = new Api();
|
||||
$json = json_encode($api->translateThread($thread));
|
||||
$jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json';
|
||||
file_unlink($jsonFilename);
|
||||
file_write($jsonFilename, $json);
|
||||
}
|
||||
|
||||
if ($action == 'delete' && !$return && !$mod) {
|
||||
$noko50fn = $board['dir'] . $config['dir']['res'] . link_for(array('id' => $id), true);
|
||||
file_unlink($noko50fn);
|
||||
|
||||
file_unlink($board['dir'] . $config['dir']['res'] . link_for(array('id' => $id)));
|
||||
} elseif ($return) {
|
||||
if ($return) {
|
||||
return $body;
|
||||
} elseif ($action == 'rebuild') {
|
||||
} else {
|
||||
$noko50fn = $board['dir'] . $config['dir']['res'] . link_for($thread, true);
|
||||
if ($hasnoko50 || file_exists($noko50fn)) {
|
||||
if ($hasnoko50 || file_exists($noko50fn))
|
||||
buildThread50($id, $return, $mod, $thread, $antibot);
|
||||
}
|
||||
|
||||
|
||||
file_write($board['dir'] . $config['dir']['res'] . link_for($thread), $body);
|
||||
}
|
||||
}
|
||||
@ -2779,61 +2733,3 @@ function markdown($s) {
|
||||
|
||||
return $pd->text($s);
|
||||
}
|
||||
|
||||
function generation_strategy($fun, $array=array()) { global $config;
|
||||
$action = false;
|
||||
|
||||
foreach ($config['generation_strategies'] as $s) {
|
||||
if ($action = $s($fun, $array)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($action[0]) {
|
||||
case 'immediate':
|
||||
return 'rebuild';
|
||||
case 'defer':
|
||||
// Ok, it gets interesting here :)
|
||||
get_queue('generate')->push(serialize(array('build', $fun, $array, $action)));
|
||||
return 'ignore';
|
||||
case 'build_on_load':
|
||||
return 'delete';
|
||||
}
|
||||
}
|
||||
|
||||
function strategy_immediate($fun, $array) {
|
||||
return array('immediate');
|
||||
}
|
||||
|
||||
function strategy_smart_build($fun, $array) {
|
||||
return array('build_on_load');
|
||||
}
|
||||
|
||||
function strategy_sane($fun, $array) { global $config;
|
||||
if (php_sapi_name() == 'cli') return false;
|
||||
else if (isset($_POST['mod'])) return false;
|
||||
// Thread needs to be done instantly. Same with a board page, but only if posting a new thread.
|
||||
else if ($fun == 'sb_thread' || ($fun == 'sb_board' && $array[1] == 1 && isset ($_POST['page']))) return array('immediate');
|
||||
else return false;
|
||||
}
|
||||
|
||||
// My first, test strategy.
|
||||
function strategy_first($fun, $array) {
|
||||
switch ($fun) {
|
||||
case 'sb_thread':
|
||||
return array('defer');
|
||||
case 'sb_board':
|
||||
if ($array[1] > 8) return array('build_on_load');
|
||||
else return array('defer');
|
||||
case 'sb_api':
|
||||
return array('defer');
|
||||
case 'sb_catalog':
|
||||
return array('defer');
|
||||
case 'sb_recent':
|
||||
return array('build_on_load');
|
||||
case 'sb_sitemap':
|
||||
return array('build_on_load');
|
||||
case 'sb_ukko':
|
||||
return array('defer');
|
||||
}
|
||||
}
|
||||
|
39
inc/lock.php
39
inc/lock.php
@ -1,39 +0,0 @@
|
||||
<?php
|
||||
class Lock {
|
||||
function __construct($key) { global $config;
|
||||
if ($config['lock']['enabled'] == 'fs') {
|
||||
$key = str_replace('/', '::', $key);
|
||||
$key = str_replace("\0", '', $key);
|
||||
|
||||
$this->f = fopen("tmp/locks/$key", "w");
|
||||
}
|
||||
}
|
||||
|
||||
// Get a shared lock
|
||||
function get($nonblock = false) { global $config;
|
||||
if ($config['lock']['enabled'] == 'fs') {
|
||||
$wouldblock = false;
|
||||
flock($this->f, LOCK_SH | ($nonblock ? LOCK_NB : 0), $wouldblock);
|
||||
if ($nonblock && $wouldblock) return false;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Get an exclusive lock
|
||||
function get_ex($nonblock = false) { global $config;
|
||||
if ($config['lock']['enabled'] == 'fs') {
|
||||
$wouldblock = false;
|
||||
flock($this->f, LOCK_EX | ($nonblock ? LOCK_NB : 0), $wouldblock);
|
||||
if ($nonblock && $wouldblock) return false;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Free a lock
|
||||
function free() { global $config;
|
||||
if ($config['lock']['enabled'] == 'fs') {
|
||||
flock($this->f, LOCK_UN);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2016 vichan-devel
|
||||
*/
|
||||
|
||||
defined('TINYBOARD') or exit;
|
||||
|
||||
function gen_msgid($board, $id) {
|
||||
global $config;
|
||||
|
||||
$b = preg_replace("/[^0-9a-zA-Z$]/", 'x', $board);
|
||||
$salt = sha1($board . "|" . $id . "|" . $config['nntpchan']['salt']);
|
||||
$salt = substr($salt, 0, 7);
|
||||
$salt = base_convert($salt, 16, 36);
|
||||
|
||||
return "<$b.$id.$salt@".$config['nntpchan']['domain'].">";
|
||||
}
|
||||
|
||||
|
||||
function gen_nntp($headers, $files) {
|
||||
if (count($files) == 0) {
|
||||
}
|
||||
else if (count($files) == 1 && $files[0]['type'] == 'text/plain') {
|
||||
$content = $files[0]['text'] . "\r\n";
|
||||
$headers['Content-Type'] = "text/plain; charset=UTF-8";
|
||||
}
|
||||
else {
|
||||
$boundary = sha1($headers['Message-Id']);
|
||||
$content = "";
|
||||
$headers['Content-Type'] = "multipart/mixed; boundary=$boundary";
|
||||
foreach ($files as $file) {
|
||||
$content .= "--$boundary\r\n";
|
||||
if (isset($file['name'])) {
|
||||
$file['name'] = preg_replace('/[\r\n\0"]/', '', $file['name']);
|
||||
$content .= "Content-Disposition: form-data; filename=\"$file[name]\"; name=\"attachment\"\r\n";
|
||||
}
|
||||
$type = explode('/', $file['type'])[0];
|
||||
if ($type == 'text') {
|
||||
$file['type'] .= '; charset=UTF-8';
|
||||
}
|
||||
$content .= "Content-Type: $file[type]\r\n";
|
||||
if ($type != 'text' && $type != 'message') {
|
||||
$file['text'] = base64_encode($file['text']);
|
||||
$content .= "Content-Transfer-Encoding: base64\r\n";
|
||||
}
|
||||
$content .= "\r\n";
|
||||
$content .= $file['text'];
|
||||
$content .= "\r\n";
|
||||
}
|
||||
$content .= "--$boundary--\r\n";
|
||||
|
||||
$headers['Mime-Version'] = '1.0';
|
||||
}
|
||||
//$headers['Content-Length'] = strlen($content);
|
||||
$headers['Date'] = date('r', $headers['Date']);
|
||||
$out = "";
|
||||
foreach ($headers as $id => $val) {
|
||||
$val = str_replace("\n", "\n\t", $val);
|
||||
$out .= "$id: $val\r\n";
|
||||
}
|
||||
$out .= "\r\n";
|
||||
$out .= $content;
|
||||
return $out;
|
||||
}
|
||||
|
||||
function nntp_publish($msg, $id) {
|
||||
global $config;
|
||||
$server = $config["nntpchan"]["server"];
|
||||
$s = fsockopen("tcp://$server");
|
||||
fgets($s);
|
||||
fputs($s, "MODE STREAM\r\n");
|
||||
fgets($s);
|
||||
fputs($s, "TAKETHIS $id\r\n");
|
||||
fputs($s, $msg);
|
||||
fputs($s, "\r\n.\r\n");
|
||||
fgets($s);
|
||||
fputs($s, "QUIT\r\n");
|
||||
fclose($s);
|
||||
}
|
||||
|
||||
function post2nntp($post, $msgid) {
|
||||
global $config;
|
||||
|
||||
$headers = array();
|
||||
$files = array();
|
||||
|
||||
$headers['Message-Id'] = $msgid;
|
||||
$headers['Newsgroups'] = $config['nntpchan']['group'];
|
||||
$headers['Date'] = time();
|
||||
$headers['Subject'] = $post['subject'] ? $post['subject'] : "None";
|
||||
$headers['From'] = $post['name'] . " <poster@" . $config['nntpchan']['domain'] . ">";
|
||||
|
||||
if ($post['email'] == 'sage') {
|
||||
$headers['X-Sage'] = true;
|
||||
}
|
||||
|
||||
if (!$post['op']) {
|
||||
// Get muh parent
|
||||
$query = prepare("SELECT `message_id` FROM ``nntp_references`` WHERE `board` = :board AND `id` = :id");
|
||||
$query->bindValue(':board', $post['board']);
|
||||
$query->bindValue(':id', $post['thread']);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
if ($result = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
$headers['References'] = $result['message_id'];
|
||||
}
|
||||
else {
|
||||
return false; // We don't have OP. Discarding.
|
||||
}
|
||||
}
|
||||
|
||||
// Let's parse the body a bit.
|
||||
$body = trim($post['body_nomarkup']);
|
||||
$body = preg_replace('/\r?\n/', "\r\n", $body);
|
||||
$body = preg_replace_callback('@>>(>/([a-zA-Z0-9_+-]+)/)?([0-9]+)@', function($o) use ($post) {
|
||||
if ($o[1]) {
|
||||
$board = $o[2];
|
||||
}
|
||||
else {
|
||||
$board = $post['board'];
|
||||
}
|
||||
$id = $o[3];
|
||||
|
||||
$query = prepare("SELECT `message_id_digest` FROM ``nntp_references`` WHERE `board` = :board AND `id` = :id");
|
||||
$query->bindValue(':board', $board);
|
||||
$query->bindValue(':id', $id);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
if ($result = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
return ">>".substr($result['message_id_digest'], 0, 18);
|
||||
}
|
||||
else {
|
||||
return $o[0]; // Should send URL imo
|
||||
}
|
||||
}, $body);
|
||||
$body = preg_replace('/>>>>([0-9a-fA-F])+/', '>>\1', $body);
|
||||
|
||||
|
||||
$files[] = array('type' => 'text/plain', 'text' => $body);
|
||||
|
||||
foreach ($post['files'] as $id => $file) {
|
||||
$fc = array();
|
||||
|
||||
$fc['type'] = $file['type'];
|
||||
$fc['text'] = file_get_contents($file['file_path']);
|
||||
$fc['name'] = $file['name'];
|
||||
|
||||
$files[] = $fc;
|
||||
}
|
||||
|
||||
return array($headers, $files);
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
define('TINYBOARD', 'fuck yeah');
|
||||
require_once('nntpchan.php');
|
||||
|
||||
|
||||
die();
|
||||
|
||||
$time = time();
|
||||
echo "\n@@@@ Thread:\n";
|
||||
echo $m0 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.0000.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None"],
|
||||
[['type' => 'text/plain', 'text' => "THIS IS A NEW TEST THREAD"]]);
|
||||
echo "\n@@@@ Single msg:\n";
|
||||
echo $m1 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.1234.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"],
|
||||
[['type' => 'text/plain', 'text' => "hello world, with no image :("]]);
|
||||
echo "\n@@@@ Single msg and pseudoimage:\n";
|
||||
echo $m2 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.2137.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"],
|
||||
[['type' => 'text/plain', 'text' => "hello world, now with an image!"],
|
||||
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif.gif"]]);
|
||||
echo "\n@@@@ Single msg and two pseudoimages:\n";
|
||||
echo $m3 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.1488.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"],
|
||||
[['type' => 'text/plain', 'text' => "hello world, now WITH TWO IMAGES!!!"],
|
||||
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif.gif"],
|
||||
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif2.gif"]]);
|
||||
shoveitup($m0, "<1234.0000.".$time."@example.vichan.net>");
|
||||
sleep(1);
|
||||
shoveitup($m1, "<1234.1234.".$time."@example.vichan.net>");
|
||||
sleep(1);
|
||||
shoveitup($m2, "<1234.2137.".$time."@example.vichan.net>");
|
||||
shoveitup($m3, "<1234.1488.".$time."@example.vichan.net>");
|
||||
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
// PHP 5.4
|
||||
|
||||
if (!function_exists('hex2bin')) {
|
||||
function hex2bin($data) {
|
||||
return pack("H*" , $hex_string);
|
||||
}
|
||||
}
|
||||
|
||||
// PHP 5.6
|
||||
|
||||
if (!function_exists('hash_equals')) {
|
||||
function hash_equals($ours, $theirs) {
|
||||
$ours = (string)$ours;
|
||||
$theirs = (string)$theirs;
|
||||
|
||||
$tlen = strlen($theirs);
|
||||
$olen = strlen($ours);
|
||||
|
||||
$answer = 0;
|
||||
for ($i = 0; $i < $tlen; $i++) {
|
||||
$answer |= ord($ours[$olen > $i ? $i : 0]) ^ ord($theirs[$i]);
|
||||
}
|
||||
|
||||
return $answer === 0 && $olen === $tlen;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Queue {
|
||||
function __construct($key) { global $config;
|
||||
if ($config['queue']['enabled'] == 'fs') {
|
||||
$this->lock = new Lock($key);
|
||||
$key = str_replace('/', '::', $key);
|
||||
$key = str_replace("\0", '', $key);
|
||||
$this->key = "tmp/queue/$key/";
|
||||
}
|
||||
}
|
||||
|
||||
function push($str) { global $config;
|
||||
if ($config['queue']['enabled'] == 'fs') {
|
||||
$this->lock->get_ex();
|
||||
file_put_contents($this->key.microtime(true), $str);
|
||||
$this->lock->free();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
function pop($n = 1) { global $config;
|
||||
if ($config['queue']['enabled'] == 'fs') {
|
||||
$this->lock->get_ex();
|
||||
$dir = opendir($this->key);
|
||||
$paths = array();
|
||||
while ($n > 0) {
|
||||
$path = readdir($dir);
|
||||
if ($path === FALSE) break;
|
||||
elseif ($path == '.' || $path == '..') continue;
|
||||
else { $paths[] = $path; $n--; }
|
||||
}
|
||||
$out = array();
|
||||
foreach ($paths as $v) {
|
||||
$out []= file_get_contents($this->key.$v);
|
||||
unlink($this->key.$v);
|
||||
}
|
||||
$this->lock->free();
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't use the constructor. Use the get_queue function.
|
||||
$queues = array();
|
||||
|
||||
function get_queue($name) { global $queues;
|
||||
return $queues[$name] = isset ($queues[$name]) ? $queues[$name] : new Queue($name);
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
// vichan's routing mechanism
|
||||
|
||||
// don't bother with that unless you use smart build or advanced build
|
||||
// you can use those parts for your own implementations though :^)
|
||||
|
||||
defined('TINYBOARD') or exit;
|
||||
|
||||
function route($path) { global $config;
|
||||
$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_slugcheck';
|
||||
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page50']] = 'sb_thread_slugcheck50';
|
||||
if ($config['slugify']) {
|
||||
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page_slug']] = 'sb_thread_slugcheck';
|
||||
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page50_slug']] = '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['/%b/index.rss'] = 'sb_catalog';
|
||||
$entrypoints['/sitemap.xml'] = 'sb_sitemap';
|
||||
|
||||
$entrypoints = array_merge($entrypoints, $config['controller_entrypoints']);
|
||||
|
||||
$reached = false;
|
||||
|
||||
list($request) = explode('?', $path);
|
||||
|
||||
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 = array($fun, $matches);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $reached;
|
||||
}
|
||||
|
81
install.php
81
install.php
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
// Installation/upgrade file
|
||||
define('VERSION', '5.1.4');
|
||||
define('VERSION', '5.2.0');
|
||||
require 'inc/functions.php';
|
||||
loadConfig();
|
||||
|
||||
@ -9,25 +9,11 @@ loadConfig();
|
||||
class SaltGen {
|
||||
public $salt_length = 128;
|
||||
|
||||
// Best function I could think of for non-SSL PHP 5
|
||||
private function generate_install_salt() {
|
||||
$ret = "";
|
||||
|
||||
// This is bad! But what else can we do sans OpenSSL?
|
||||
for ($i = 0; $i < $this->salt_length; ++$i) {
|
||||
$s = pack("c", mt_rand(0,255));
|
||||
$ret = $ret . $s;
|
||||
}
|
||||
|
||||
return base64_encode($ret);
|
||||
}
|
||||
|
||||
// Best function of the lot. Works with any PHP version as long as OpenSSL extension is on
|
||||
private function generate_install_salt_openssl() {
|
||||
$ret = openssl_random_pseudo_bytes($this->salt_length, $strong);
|
||||
if (!$strong) {
|
||||
if (!$strong)
|
||||
error(_("Misconfigured system: OpenSSL returning weak salts. Cannot continue."));
|
||||
}
|
||||
return base64_encode($ret);
|
||||
}
|
||||
|
||||
@ -37,13 +23,10 @@ class SaltGen {
|
||||
|
||||
// TODO: Perhaps add mcrypt as an option? Maybe overkill.
|
||||
public function generate() {
|
||||
if (extension_loaded('openssl')) {
|
||||
if (extension_loaded('openssl'))
|
||||
return "OSSL." . $this->generate_install_salt_openssl();
|
||||
} else if (defined('PHP_MAJOR_VERSION') && PHP_MAJOR_VERSION >= 7) {
|
||||
else
|
||||
return "PHP7." . $this->generate_install_salt_php7();
|
||||
} else {
|
||||
return "INSECURE." . $this->generate_install_salt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -561,7 +544,8 @@ if (file_exists($config['has_installed'])) {
|
||||
break;
|
||||
}
|
||||
case '4.4.98-pre':
|
||||
if (!$twig) load_twig();
|
||||
if (!$twig)
|
||||
load_twig();
|
||||
$twig->clearCacheFiles();
|
||||
case '4.4.98':
|
||||
case '4.5.0':
|
||||
@ -590,12 +574,11 @@ if (file_exists($config['has_installed'])) {
|
||||
case '4.9.90':
|
||||
case '4.9.91':
|
||||
case '4.9.92':
|
||||
foreach ($boards as &$board) {
|
||||
query(sprintf('ALTER TABLE ``posts_%s`` ADD `slug` VARCHAR(255) DEFAULT NULL AFTER `embed`;', $board['uri'])) or error(db_error());
|
||||
}
|
||||
case '4.9.93':
|
||||
query('ALTER TABLE ``mods`` CHANGE `password` `password` VARCHAR(255) NOT NULL;') or error(db_error());
|
||||
query('ALTER TABLE ``mods`` CHANGE `salt` `salt` VARCHAR(64) NOT NULL;') or error(db_error());
|
||||
foreach ($boards as &$board)
|
||||
query(sprintf('ALTER TABLE ``posts_%s`` ADD `slug` VARCHAR(255) DEFAULT NULL AFTER `embed`;', $board['uri'])) or error(db_error());
|
||||
case '4.9.93':
|
||||
query('ALTER TABLE ``mods`` CHANGE `password` `password` VARCHAR(255) NOT NULL;') or error(db_error());
|
||||
query('ALTER TABLE ``mods`` CHANGE `salt` `salt` VARCHAR(64) NOT NULL;') or error(db_error());
|
||||
case '5.0.0':
|
||||
query('ALTER TABLE ``mods`` CHANGE `salt` `version` VARCHAR(64) NOT NULL;') or error(db_error());
|
||||
case '5.0.1':
|
||||
@ -611,9 +594,8 @@ if (file_exists($config['has_installed'])) {
|
||||
UNIQUE KEY `u_pages` (`name`,`board`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;') or error(db_error());
|
||||
case '5.1.1':
|
||||
foreach ($boards as &$board) {
|
||||
query(sprintf("ALTER TABLE ``posts_%s`` ADD `cycle` int(1) NOT NULL AFTER `locked`", $board['uri'])) or error(db_error());
|
||||
}
|
||||
foreach ($boards as &$board)
|
||||
query(sprintf("ALTER TABLE ``posts_%s`` ADD `cycle` int(1) NOT NULL AFTER `locked`", $board['uri'])) or error(db_error());
|
||||
case '5.1.2':
|
||||
query('CREATE TABLE IF NOT EXISTS ``nntp_references`` (
|
||||
`board` varchar(60) NOT NULL,
|
||||
@ -635,6 +617,9 @@ if (file_exists($config['has_installed'])) {
|
||||
`created_at` int(11),
|
||||
PRIMARY KEY (`cookie`,`extra`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;') or error(db_error());
|
||||
case '5.2.0-dev-1':
|
||||
query('DROP TABLE IF EXISTS ``nntp_references``;
|
||||
DROP TABLE IF EXISTS ``captchas``;') or error(db_error());
|
||||
case false:
|
||||
// TODO: enhance Tinyboard -> vichan upgrade path.
|
||||
query("CREATE TABLE IF NOT EXISTS ``search_queries`` ( `ip` varchar(39) NOT NULL, `time` int(11) NOT NULL, `query` text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;") or error(db_error());
|
||||
@ -647,11 +632,11 @@ if (file_exists($config['has_installed'])) {
|
||||
break;
|
||||
default:
|
||||
$page['title'] = 'Unknown version';
|
||||
$page['body'] = '<p style="text-align:center">vichan was unable to determine what version is currently installed.</p>';
|
||||
$page['body'] = '<p style="text-align:center">Tinyboard was unable to determine what version is currently installed.</p>';
|
||||
break;
|
||||
case VERSION:
|
||||
$page['title'] = 'Already installed';
|
||||
$page['body'] = '<p style="text-align:center">It appears that vichan is already installed (' . $version . ') and there is nothing to upgrade! Delete <strong>' . $config['has_installed'] . '</strong> to reinstall.</p>';
|
||||
$page['body'] = '<p style="text-align:center">It appears that Tinyboard is already installed (' . $version . ') and there is nothing to upgrade! Delete <strong>' . $config['has_installed'] . '</strong> to reinstall.</p>';
|
||||
break;
|
||||
}
|
||||
|
||||
@ -729,17 +714,17 @@ if ($step == 0) {
|
||||
$tests = array(
|
||||
array(
|
||||
'category' => 'PHP',
|
||||
'name' => 'PHP ≥ 5.4',
|
||||
'result' => PHP_VERSION_ID >= 50400,
|
||||
'name' => 'PHP ≥ 7.0',
|
||||
'result' => PHP_VERSION_ID >= 70000,
|
||||
'required' => true,
|
||||
'message' => 'vichan requires PHP 5.4 or better.',
|
||||
'message' => 'Tinyboard requires PHP 7.0 or better.',
|
||||
),
|
||||
array(
|
||||
'category' => 'PHP',
|
||||
'name' => 'PHP ≥ 5.6',
|
||||
'result' => PHP_VERSION_ID >= 50600,
|
||||
'name' => 'PHP ≥ 7.2',
|
||||
'result' => PHP_VERSION_ID >= 70200,
|
||||
'required' => false,
|
||||
'message' => 'vichan works best on PHP 5.6 or better.',
|
||||
'message' => 'Tinyboard works best on PHP 7.2 or better.',
|
||||
),
|
||||
array(
|
||||
'category' => 'PHP',
|
||||
@ -750,10 +735,10 @@ if ($step == 0) {
|
||||
),
|
||||
array(
|
||||
'category' => 'PHP',
|
||||
'name' => 'OpenSSL extension installed or PHP ≥ 7.0',
|
||||
'result' => (extension_loaded('openssl') || (defined('PHP_MAJOR_VERSION') && PHP_MAJOR_VERSION >= 7)),
|
||||
'name' => 'OpenSSL extension installed',
|
||||
'result' => extension_loaded('openssl'),
|
||||
'required' => false,
|
||||
'message' => 'It is highly recommended that you install the PHP <a href="http://www.php.net/manual/en/openssl.installation.php">OpenSSL</a> extension and/or use PHP version 7 or above. <strong>If you do not, it is possible that the IP addresses of users of your site could be compromised — see <a href="https://github.com/vichan-devel/vichan/issues/284">vichan issue #284.</a></strong> Installing the OpenSSL extension allows vichan to generate a secure salt automatically for you.',
|
||||
'message' => 'It is highly recommended that you install the PHP <a href="http://www.php.net/manual/en/openssl.installation.php">OpenSSL</a> extension. Installing the OpenSSL extension allows Tinyboard to generate a secure salt automatically for you.',
|
||||
),
|
||||
array(
|
||||
'category' => 'Database',
|
||||
@ -851,28 +836,28 @@ if ($step == 0) {
|
||||
'name' => getcwd(),
|
||||
'result' => is_writable('.'),
|
||||
'required' => true,
|
||||
'message' => 'vichan does not have permission to create directories (boards) here. You will need to <code>chmod</code> (or operating system equivalent) appropriately.'
|
||||
'message' => 'Tinyboard does not have permission to create directories (boards) here. You will need to <code>chmod</code> (or operating system equivalent) appropriately.'
|
||||
),
|
||||
array(
|
||||
'category' => 'File permissions',
|
||||
'name' => getcwd() . '/templates/cache',
|
||||
'result' => is_writable('templates') || (is_dir('templates/cache') && is_writable('templates/cache')),
|
||||
'required' => true,
|
||||
'message' => 'You must give vichan permission to create (and write to) the <code>templates/cache</code> directory or performance will be drastically reduced.'
|
||||
'message' => 'You must give Tinyboard permission to create (and write to) the <code>templates/cache</code> directory or performance will be drastically reduced.'
|
||||
),
|
||||
array(
|
||||
'category' => 'File permissions',
|
||||
'name' => getcwd() . '/tmp/cache',
|
||||
'result' => is_dir('tmp/cache') && is_writable('tmp/cache'),
|
||||
'required' => true,
|
||||
'message' => 'You must give vichan permission to write to the <code>tmp/cache</code> directory.'
|
||||
'message' => 'You must give Tinyboard permission to write to the <code>tmp/cache</code> directory.'
|
||||
),
|
||||
array(
|
||||
'category' => 'File permissions',
|
||||
'name' => getcwd() . '/inc/instance-config.php',
|
||||
'result' => is_writable('inc/instance-config.php'),
|
||||
'required' => false,
|
||||
'message' => 'vichan does not have permission to make changes to <code>inc/instance-config.php</code>. To complete the installation, you will be asked to manually copy and paste code into the file instead.'
|
||||
'message' => 'Tinyboard does not have permission to make changes to <code>inc/instance-config.php</code>. To complete the installation, you will be asked to manually copy and paste code into the file instead.'
|
||||
),
|
||||
array(
|
||||
'category' => 'Misc',
|
||||
@ -884,10 +869,10 @@ if ($step == 0) {
|
||||
),
|
||||
array(
|
||||
'category' => 'Misc',
|
||||
'name' => 'vichan installed using git',
|
||||
'name' => 'Tinyboard installed using git',
|
||||
'result' => is_dir('.git'),
|
||||
'required' => false,
|
||||
'message' => 'vichan is still beta software and it\'s not going to come out of beta any time soon. As there are often many months between releases yet changes and bug fixes are very frequent, it\'s recommended to use the git repository to maintain your vichan installation. Using git makes upgrading much easier.'
|
||||
'message' => 'Tinyboard is still beta software and it\'s not going to come out of beta any time soon. As there are often many months between releases yet changes and bug fixes are very frequent, it\'s recommended to use the git repository to maintain your Tinyboard installation. Using git makes upgrading much easier.'
|
||||
)
|
||||
);
|
||||
|
||||
|
33
install.sql
33
install.sql
@ -314,39 +314,6 @@ CREATE TABLE IF NOT EXISTS `pages` (
|
||||
UNIQUE KEY `u_pages` (`name`,`board`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `nntp_references`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nntp_references` (
|
||||
`board` varchar(30) NOT NULL,
|
||||
`id` int(11) unsigned NOT NULL,
|
||||
`message_id` varchar(255) CHARACTER SET ascii NOT NULL,
|
||||
`message_id_digest` varchar(40) CHARACTER SET ascii NOT NULL,
|
||||
`own` tinyint(1) NOT NULL,
|
||||
`headers` text,
|
||||
PRIMARY KEY (`message_id_digest`),
|
||||
UNIQUE KEY `message_id` (`message_id`),
|
||||
UNIQUE KEY `u_board_id` (`board`, `id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `captchas`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `captchas` (
|
||||
`cookie` VARCHAR(50),
|
||||
`extra` VARCHAR(200),
|
||||
`text` VARCHAR(255),
|
||||
`created_at` INT(11),
|
||||
PRIMARY KEY (`cookie`,`extra`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
|
@ -1,43 +0,0 @@
|
||||
var tout;
|
||||
|
||||
function redo_events(provider, extra) {
|
||||
$('.captcha .captcha_text, textarea[id="body"]').off("focus").one("focus", function() { actually_load_captcha(provider, extra); });
|
||||
}
|
||||
|
||||
function actually_load_captcha(provider, extra) {
|
||||
$('.captcha .captcha_text, textarea[id="body"]').off("focus");
|
||||
|
||||
if (tout !== undefined) {
|
||||
clearTimeout(tout);
|
||||
}
|
||||
|
||||
$.getJSON(provider, {mode: 'get', extra: extra}, function(json) {
|
||||
$(".captcha .captcha_cookie").val(json.cookie);
|
||||
$(".captcha .captcha_html").html(json.captchahtml);
|
||||
|
||||
setTimeout(function() {
|
||||
redo_events(provider, extra);
|
||||
}, json.expires_in * 1000);
|
||||
});
|
||||
}
|
||||
|
||||
function load_captcha(provider, extra) {
|
||||
$(function() {
|
||||
$(".captcha>td").html("<input class='captcha_text' type='text' name='captcha_text' size='32' maxlength='6' autocomplete='off'>"+
|
||||
"<input class='captcha_cookie' name='captcha_cookie' type='hidden'>"+
|
||||
"<div class='captcha_html'></div>");
|
||||
|
||||
$("#quick-reply .captcha .captcha_text").prop("placeholder", _("Verification"));
|
||||
|
||||
$(".captcha .captcha_html").on("click", function() { actually_load_captcha(provider, extra); });
|
||||
$(document).on("ajax_after_post", function() { actually_load_captcha(provider, extra); });
|
||||
redo_events(provider, extra);
|
||||
|
||||
$(window).on("quick-reply", function() {
|
||||
redo_events(provider, extra);
|
||||
$("#quick-reply .captcha .captcha_html").html($("form:not(#quick-reply) .captcha .captcha_html").html());
|
||||
$("#quick-reply .captcha .captcha_cookie").val($("form:not(#quick-reply) .captcha .captcha_cookie").html());
|
||||
$("#quick-reply .captcha .captcha_html").on("click", function() { actually_load_captcha(provider, extra); });
|
||||
});
|
||||
});
|
||||
}
|
486
post.php
486
post.php
@ -11,170 +11,6 @@ if ((!isset($_POST['mod']) || !$_POST['mod']) && $config['board_locked']) {
|
||||
error("Board is locked");
|
||||
}
|
||||
|
||||
$dropped_post = false;
|
||||
|
||||
// Is it a post coming from NNTP? Let's extract it and pretend it's a normal post.
|
||||
if (isset($_GET['Newsgroups']) && $config['nntpchan']['enabled']) {
|
||||
if ($_SERVER['REMOTE_ADDR'] != $config['nntpchan']['trusted_peer']) {
|
||||
error("NNTPChan: Forbidden. $_SERVER[REMOTE_ADDR] is not a trusted peer");
|
||||
}
|
||||
|
||||
$_POST = array();
|
||||
$_POST['json_response'] = true;
|
||||
|
||||
$headers = json_encode($_GET);
|
||||
|
||||
if (!isset ($_GET['Message-Id'])) {
|
||||
if (!isset ($_GET['Message-ID'])) {
|
||||
error("NNTPChan: No message ID");
|
||||
}
|
||||
else $msgid = $_GET['Message-ID'];
|
||||
}
|
||||
else $msgid = $_GET['Message-Id'];
|
||||
|
||||
$groups = preg_split("/,\s*/", $_GET['Newsgroups']);
|
||||
if (count($groups) != 1) {
|
||||
error("NNTPChan: Messages can go to only one newsgroup");
|
||||
}
|
||||
$group = $groups[0];
|
||||
|
||||
if (!isset($config['nntpchan']['dispatch'][$group])) {
|
||||
error("NNTPChan: We don't synchronize $group");
|
||||
}
|
||||
$xboard = $config['nntpchan']['dispatch'][$group];
|
||||
|
||||
$ref = null;
|
||||
if (isset ($_GET['References'])) {
|
||||
$refs = preg_split("/,\s*/", $_GET['References']);
|
||||
|
||||
if (count($refs) > 1) {
|
||||
error("NNTPChan: We don't support multiple references");
|
||||
}
|
||||
|
||||
$ref = $refs[0];
|
||||
|
||||
$query = prepare("SELECT `board`,`id` FROM ``nntp_references`` WHERE `message_id` = :ref");
|
||||
$query->bindValue(':ref', $ref);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
$ary = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (count($ary) == 0) {
|
||||
error("NNTPChan: We don't have $ref that $msgid references");
|
||||
}
|
||||
|
||||
$p_id = $ary[0]['id'];
|
||||
$p_board = $ary[0]['board'];
|
||||
|
||||
if ($p_board != $xboard) {
|
||||
error("NNTPChan: Cross board references not allowed. Tried to reference $p_board on $xboard");
|
||||
}
|
||||
|
||||
$_POST['thread'] = $p_id;
|
||||
}
|
||||
|
||||
$date = isset($_GET['Date']) ? strtotime($_GET['Date']) : time();
|
||||
|
||||
list($ct) = explode('; ', $_GET['Content-Type']);
|
||||
|
||||
$query = prepare("SELECT COUNT(*) AS `c` FROM ``nntp_references`` WHERE `message_id` = :msgid");
|
||||
$query->bindValue(":msgid", $msgid);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
$a = $query->fetch(PDO::FETCH_ASSOC);
|
||||
if ($a['c'] > 0) {
|
||||
error("NNTPChan: We already have this post. Post discarded.");
|
||||
}
|
||||
|
||||
if ($ct == 'text/plain') {
|
||||
$content = file_get_contents("php://input");
|
||||
}
|
||||
elseif ($ct == 'multipart/mixed' || $ct == 'multipart/form-data') {
|
||||
_syslog(LOG_INFO, "MM: Files: ".print_r($GLOBALS, true)); // Debug
|
||||
|
||||
$content = '';
|
||||
|
||||
$newfiles = array();
|
||||
foreach ($_FILES['attachment']['error'] as $id => $error) {
|
||||
if ($_FILES['attachment']['type'][$id] == 'text/plain') {
|
||||
$content .= file_get_contents($_FILES['attachment']['tmp_name'][$id]);
|
||||
}
|
||||
elseif ($_FILES['attachment']['type'][$id] == 'message/rfc822') { // Signed message, ignore for now
|
||||
}
|
||||
else { // A real attachment :^)
|
||||
$file = array();
|
||||
$file['name'] = $_FILES['attachment']['name'][$id];
|
||||
$file['type'] = $_FILES['attachment']['type'][$id];
|
||||
$file['size'] = $_FILES['attachment']['size'][$id];
|
||||
$file['tmp_name'] = $_FILES['attachment']['tmp_name'][$id];
|
||||
$file['error'] = $_FILES['attachment']['error'][$id];
|
||||
|
||||
$newfiles["file$id"] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
$_FILES = $newfiles;
|
||||
}
|
||||
else {
|
||||
error("NNTPChan: Wrong mime type: $ct");
|
||||
}
|
||||
|
||||
$_POST['subject'] = isset($_GET['Subject']) ? ($_GET['Subject'] == 'None' ? '' : $_GET['Subject']) : '';
|
||||
$_POST['board'] = $xboard;
|
||||
|
||||
if (isset ($_GET['From'])) {
|
||||
list($name, $mail) = explode(" <", $_GET['From'], 2);
|
||||
$mail = preg_replace('/>\s+$/', '', $mail);
|
||||
|
||||
$_POST['name'] = $name;
|
||||
//$_POST['email'] = $mail;
|
||||
$_POST['email'] = '';
|
||||
}
|
||||
|
||||
if (isset ($_GET['X_Sage'])) {
|
||||
$_POST['email'] = 'sage';
|
||||
}
|
||||
|
||||
$content = preg_replace_callback('/>>([0-9a-fA-F]{6,})/', function($id) use ($xboard) {
|
||||
$id = $id[1];
|
||||
|
||||
$query = prepare("SELECT `board`,`id` FROM ``nntp_references`` WHERE `message_id_digest` LIKE :rule");
|
||||
$idx = $id . "%";
|
||||
$query->bindValue(':rule', $idx);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
$ary = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
if (count($ary) == 0) {
|
||||
return ">>>>$id";
|
||||
}
|
||||
else {
|
||||
$ret = array();
|
||||
foreach ($ary as $v) {
|
||||
if ($v['board'] != $xboard) {
|
||||
$ret[] = ">>>/".$v['board']."/".$v['id'];
|
||||
}
|
||||
else {
|
||||
$ret[] = ">>".$v['id'];
|
||||
}
|
||||
}
|
||||
return implode($ret, ", ");
|
||||
}
|
||||
}, $content);
|
||||
|
||||
$_POST['body'] = $content;
|
||||
|
||||
$dropped_post = array(
|
||||
'date' => $date,
|
||||
'board' => $xboard,
|
||||
'msgid' => $msgid,
|
||||
'headers' => $headers,
|
||||
'from_nntp' => true,
|
||||
);
|
||||
}
|
||||
elseif (isset($_GET['Newsgroups'])) {
|
||||
error("NNTPChan: NNTPChan support is disabled");
|
||||
}
|
||||
|
||||
if (isset($_POST['delete'])) {
|
||||
// Delete
|
||||
|
||||
@ -291,21 +127,18 @@ if (isset($_POST['delete'])) {
|
||||
if (count($report) > $config['report_limit'])
|
||||
error($config['error']['toomanyreports']);
|
||||
|
||||
if ($config['report_captcha'] && !isset($_POST['captcha_text'], $_POST['captcha_cookie'])) {
|
||||
error($config['error']['bot']);
|
||||
}
|
||||
if ($config['recaptcha']) {
|
||||
if (!isset($_POST['g-recaptcha-response']))
|
||||
error($config['error']['bot']);
|
||||
|
||||
if ($config['report_captcha']) {
|
||||
$resp = file_get_contents($config['captcha']['provider_check'] . "?" . http_build_query([
|
||||
'mode' => 'check',
|
||||
'text' => $_POST['captcha_text'],
|
||||
'extra' => $config['captcha']['extra'],
|
||||
'cookie' => $_POST['captcha_cookie']
|
||||
]));
|
||||
// Check what reCAPTCHA has to say...
|
||||
$resp = json_decode(file_get_contents(sprintf('https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s',
|
||||
$config['recaptcha_private'],
|
||||
urlencode($_POST['g-recaptcha-response']),
|
||||
$_SERVER['REMOTE_ADDR'])), true);
|
||||
|
||||
if ($resp !== '1') {
|
||||
error($config['error']['captcha']);
|
||||
}
|
||||
if (!$resp['success'])
|
||||
error($config['error']['captcha']);
|
||||
}
|
||||
|
||||
$reason = escape_markup_modifiers($_POST['reason']);
|
||||
@ -318,11 +151,10 @@ if (isset($_POST['delete'])) {
|
||||
|
||||
$post = $query->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$error = event('report', array('ip' => $_SERVER['REMOTE_ADDR'], 'board' => $board['uri'], 'post' => $post, 'reason' => $reason, 'link' => link_for($post)));
|
||||
$error = event('report', array('ip' => $_SERVER['REMOTE_ADDR'], 'board' => $board['uri'], 'post' => $post, 'reason' => $reason, 'link' => link_for($post)));
|
||||
|
||||
if ($error) {
|
||||
error($error);
|
||||
}
|
||||
if ($error)
|
||||
error($error);
|
||||
|
||||
if ($config['syslog'])
|
||||
_syslog(LOG_INFO, 'Reported post: ' .
|
||||
@ -348,8 +180,8 @@ if (isset($_POST['delete'])) {
|
||||
header('Content-Type: text/json');
|
||||
echo json_encode(array('success' => true));
|
||||
}
|
||||
} elseif (isset($_POST['post']) || $dropped_post) {
|
||||
if (!isset($_POST['body'], $_POST['board']) && !$dropped_post)
|
||||
} elseif (isset($_POST['post'])) {
|
||||
if (!isset($_POST['body'], $_POST['board']))
|
||||
error($config['error']['bot']);
|
||||
|
||||
$post = array('board' => $_POST['board'], 'files' => array());
|
||||
@ -376,85 +208,63 @@ if (isset($_POST['delete'])) {
|
||||
} else
|
||||
$post['op'] = true;
|
||||
|
||||
// Check if banned
|
||||
checkBan($board['uri']);
|
||||
|
||||
if (!$dropped_post) {
|
||||
// Check for CAPTCHA right after opening the board so the "return" link is in there
|
||||
if ($config['recaptcha']) {
|
||||
if (!isset($_POST['g-recaptcha-response']))
|
||||
error($config['error']['bot']);
|
||||
|
||||
// Check if banned
|
||||
checkBan($board['uri']);
|
||||
// Check what reCAPTCHA has to say...
|
||||
$resp = json_decode(file_get_contents(sprintf('https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s',
|
||||
$config['recaptcha_private'],
|
||||
urlencode($_POST['g-recaptcha-response']),
|
||||
$_SERVER['REMOTE_ADDR'])), true);
|
||||
|
||||
// Check for CAPTCHA right after opening the board so the "return" link is in there
|
||||
if ($config['recaptcha']) {
|
||||
if (!isset($_POST['g-recaptcha-response']))
|
||||
error($config['error']['bot']);
|
||||
|
||||
// Check what reCAPTCHA has to say...
|
||||
$resp = json_decode(file_get_contents(sprintf('https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s',
|
||||
$config['recaptcha_private'],
|
||||
urlencode($_POST['g-recaptcha-response']),
|
||||
$_SERVER['REMOTE_ADDR'])), true);
|
||||
|
||||
if (!$resp['success']) {
|
||||
error($config['error']['captcha']);
|
||||
}
|
||||
// Same, but now with our custom captcha provider
|
||||
if (($config['captcha']['enabled']) || (($post['op']) && ($config['new_thread_capt'])) ) {
|
||||
$resp = file_get_contents($config['captcha']['provider_check'] . "?" . http_build_query([
|
||||
'mode' => 'check',
|
||||
'text' => $_POST['captcha_text'],
|
||||
'extra' => $config['captcha']['extra'],
|
||||
'cookie' => $_POST['captcha_cookie']
|
||||
]));
|
||||
if ($resp !== '1') {
|
||||
error($config['error']['captcha'] .
|
||||
'<script>if (actually_load_captcha !== undefined) actually_load_captcha("'.$config['captcha']['provider_get'].'", "'.$config['captcha']['extra'].'");</script>');
|
||||
}
|
||||
if (!$resp['success'])
|
||||
error($config['error']['captcha']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) ||
|
||||
(!$post['op'] && $_POST['post'] == $config['button_reply'])))
|
||||
error($config['error']['bot']);
|
||||
|
||||
// Check the referrer
|
||||
if ($config['referer_match'] !== false &&
|
||||
(!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], rawurldecode($_SERVER['HTTP_REFERER']))))
|
||||
error($config['error']['referer']);
|
||||
|
||||
checkDNSBL();
|
||||
|
||||
if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) ||
|
||||
(!$post['op'] && $_POST['post'] == $config['button_reply'])))
|
||||
error($config['error']['bot']);
|
||||
|
||||
if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) {
|
||||
check_login(false);
|
||||
if (!$mod) {
|
||||
// Liar. You're not a mod.
|
||||
error($config['error']['notamod']);
|
||||
}
|
||||
|
||||
$post['sticky'] = $post['op'] && isset($_POST['sticky']);
|
||||
$post['locked'] = $post['op'] && isset($_POST['lock']);
|
||||
$post['raw'] = isset($_POST['raw']);
|
||||
|
||||
if ($post['sticky'] && !hasPermission($config['mod']['sticky'], $board['uri']))
|
||||
error($config['error']['noaccess']);
|
||||
if ($post['locked'] && !hasPermission($config['mod']['lock'], $board['uri']))
|
||||
error($config['error']['noaccess']);
|
||||
if ($post['raw'] && !hasPermission($config['mod']['rawhtml'], $board['uri']))
|
||||
error($config['error']['noaccess']);
|
||||
}
|
||||
|
||||
if (!$post['mod']) {
|
||||
$post['antispam_hash'] = checkSpam(array($board['uri'], isset($post['thread']) ? $post['thread'] : ($config['try_smarter'] && isset($_POST['page']) ? 0 - (int)$_POST['page'] : null)));
|
||||
if ($post['antispam_hash'] === true)
|
||||
error($config['error']['spam']);
|
||||
// Check the referrer
|
||||
if ($config['referer_match'] !== false &&
|
||||
(!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], rawurldecode($_SERVER['HTTP_REFERER']))))
|
||||
error($config['error']['referer']);
|
||||
|
||||
checkDNSBL();
|
||||
|
||||
|
||||
if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) {
|
||||
check_login(false);
|
||||
if (!$mod) {
|
||||
// Liar. You're not a mod.
|
||||
error($config['error']['notamod']);
|
||||
}
|
||||
|
||||
if ($config['robot_enable'] && $config['robot_mute']) {
|
||||
checkMute();
|
||||
}
|
||||
$post['sticky'] = $post['op'] && isset($_POST['sticky']);
|
||||
$post['locked'] = $post['op'] && isset($_POST['lock']);
|
||||
$post['raw'] = isset($_POST['raw']);
|
||||
|
||||
if ($post['sticky'] && !hasPermission($config['mod']['sticky'], $board['uri']))
|
||||
error($config['error']['noaccess']);
|
||||
if ($post['locked'] && !hasPermission($config['mod']['lock'], $board['uri']))
|
||||
error($config['error']['noaccess']);
|
||||
if ($post['raw'] && !hasPermission($config['mod']['rawhtml'], $board['uri']))
|
||||
error($config['error']['noaccess']);
|
||||
}
|
||||
else {
|
||||
$mod = $post['mod'] = false;
|
||||
|
||||
if (!$post['mod']) {
|
||||
$post['antispam_hash'] = checkSpam(array($board['uri'], isset($post['thread']) ? $post['thread'] : ($config['try_smarter'] && isset($_POST['page']) ? 0 - (int)$_POST['page'] : null)));
|
||||
if ($post['antispam_hash'] === true)
|
||||
error($config['error']['spam']);
|
||||
}
|
||||
|
||||
if ($config['robot_enable'] && $config['robot_mute'])
|
||||
checkMute();
|
||||
|
||||
//Check if thread exists
|
||||
if (!$post['op']) {
|
||||
@ -466,11 +276,8 @@ if (isset($_POST['delete'])) {
|
||||
// Non-existant
|
||||
error($config['error']['nonexistant']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else
|
||||
$thread = false;
|
||||
}
|
||||
|
||||
|
||||
// Check for an embed field
|
||||
if ($config['enable_embedding'] && isset($_POST['embed']) && !empty($_POST['embed'])) {
|
||||
@ -485,9 +292,8 @@ if (isset($_POST['delete'])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isset($post['embed'])) {
|
||||
if (!isset($post['embed']))
|
||||
error($config['error']['invalid_embed']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPermission($config['mod']['bypass_field_disable'], $board['uri'])) {
|
||||
@ -565,53 +371,41 @@ if (isset($_POST['delete'])) {
|
||||
$post['body'] = $_POST['body'];
|
||||
$post['password'] = $_POST['password'];
|
||||
$post['has_file'] = (!isset($post['embed']) && (($post['op'] && !isset($post['no_longer_require_an_image_for_op']) && $config['force_image_op']) || count($_FILES) > 0));
|
||||
|
||||
if (!$dropped_post) {
|
||||
|
||||
if (!($post['has_file'] || isset($post['embed'])) || (($post['op'] && $config['force_body_op']) || (!$post['op'] && $config['force_body']))) {
|
||||
$stripped_whitespace = preg_replace('/[\s]/u', '', $post['body']);
|
||||
if ($stripped_whitespace == '') {
|
||||
error($config['error']['tooshort_body']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$post['op']) {
|
||||
// Check if thread is locked
|
||||
// but allow mods to post
|
||||
if ($thread['locked'] && !hasPermission($config['mod']['postinlocked'], $board['uri']))
|
||||
error($config['error']['locked']);
|
||||
|
||||
$numposts = numPosts($post['thread']);
|
||||
|
||||
if ($config['reply_hard_limit'] != 0 && $config['reply_hard_limit'] <= $numposts['replies'])
|
||||
error($config['error']['reply_hard_limit']);
|
||||
|
||||
if ($post['has_file'] && $config['image_hard_limit'] != 0 && $config['image_hard_limit'] <= $numposts['images'])
|
||||
error($config['error']['image_hard_limit']);
|
||||
}
|
||||
if (!($post['has_file'] || isset($post['embed'])) || (($post['op'] && $config['force_body_op']) || (!$post['op'] && $config['force_body']))) {
|
||||
$stripped_whitespace = preg_replace('/[\s]/u', '', $post['body']);
|
||||
if ($stripped_whitespace == '')
|
||||
error($config['error']['tooshort_body']);
|
||||
}
|
||||
else {
|
||||
if (!$post['op']) {
|
||||
$numposts = numPosts($post['thread']);
|
||||
}
|
||||
|
||||
if (!$post['op']) {
|
||||
// Check if thread is locked
|
||||
// but allow mods to post
|
||||
if ($thread['locked'] && !hasPermission($config['mod']['postinlocked'], $board['uri']))
|
||||
error($config['error']['locked']);
|
||||
|
||||
$numposts = numPosts($post['thread']);
|
||||
|
||||
if ($config['reply_hard_limit'] != 0 && $config['reply_hard_limit'] <= $numposts['replies'])
|
||||
error($config['error']['reply_hard_limit']);
|
||||
|
||||
if ($post['has_file'] && $config['image_hard_limit'] != 0 && $config['image_hard_limit'] <= $numposts['images'])
|
||||
error($config['error']['image_hard_limit']);
|
||||
}
|
||||
|
||||
if ($post['has_file']) {
|
||||
// Determine size sanity
|
||||
$size = 0;
|
||||
if ($config['multiimage_method'] == 'split') {
|
||||
foreach ($_FILES as $key => $file) {
|
||||
foreach ($_FILES as $key => $file)
|
||||
$size += $file['size'];
|
||||
}
|
||||
} elseif ($config['multiimage_method'] == 'each') {
|
||||
foreach ($_FILES as $key => $file) {
|
||||
if ($file['size'] > $size) {
|
||||
if ($file['size'] > $size)
|
||||
$size = $file['size'];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
error(_('Unrecognized file size determination method.'));
|
||||
}
|
||||
|
||||
if ($size > $config['max_filesize'])
|
||||
error(sprintf3($config['error']['filesize'], array(
|
||||
@ -643,7 +437,7 @@ if (isset($_POST['delete'])) {
|
||||
|
||||
$trip = generate_tripcode($post['name']);
|
||||
$post['name'] = $trip[0];
|
||||
$post['trip'] = isset($trip[1]) ? $trip[1] : ''; // XX: Dropped posts and tripcodes
|
||||
$post['trip'] = isset($trip[1]) ? $trip[1] : ''; // XX: Tripcodes
|
||||
|
||||
$noko = false;
|
||||
if (strtolower($post['email']) == 'noko') {
|
||||
@ -652,7 +446,8 @@ if (isset($_POST['delete'])) {
|
||||
} elseif (strtolower($post['email']) == 'nonoko'){
|
||||
$noko = false;
|
||||
$post['email'] = '';
|
||||
} else $noko = $config['always_noko'];
|
||||
} else
|
||||
$noko = $config['always_noko'];
|
||||
|
||||
if ($post['has_file']) {
|
||||
$i = 0;
|
||||
@ -683,20 +478,19 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($post['files'])) $post['has_file'] = false;
|
||||
if (empty($post['files']))
|
||||
$post['has_file'] = false;
|
||||
|
||||
if (!$dropped_post) {
|
||||
// Check for a file
|
||||
if ($post['op'] && !isset($post['no_longer_require_an_image_for_op'])) {
|
||||
if (!$post['has_file'] && $config['force_image_op'])
|
||||
error($config['error']['noimage']);
|
||||
}
|
||||
|
||||
// Check for too many files
|
||||
if (sizeof($post['files']) > $config['max_images'])
|
||||
error($config['error']['toomanyimages']);
|
||||
// Check for a file
|
||||
if ($post['op'] && !isset($post['no_longer_require_an_image_for_op'])) {
|
||||
if (!$post['has_file'] && $config['force_image_op'])
|
||||
error($config['error']['noimage']);
|
||||
}
|
||||
|
||||
// Check for too many files
|
||||
if (sizeof($post['files']) > $config['max_images'])
|
||||
error($config['error']['toomanyimages']);
|
||||
|
||||
if ($config['strip_combining_chars']) {
|
||||
$post['name'] = strip_combining_chars($post['name']);
|
||||
$post['email'] = strip_combining_chars($post['email']);
|
||||
@ -704,28 +498,25 @@ if (isset($_POST['delete'])) {
|
||||
$post['body'] = strip_combining_chars($post['body']);
|
||||
}
|
||||
|
||||
if (!$dropped_post) {
|
||||
// Check string lengths
|
||||
if (mb_strlen($post['name']) > 35)
|
||||
error(sprintf($config['error']['toolong'], 'name'));
|
||||
if (mb_strlen($post['email']) > 40)
|
||||
error(sprintf($config['error']['toolong'], 'email'));
|
||||
if (mb_strlen($post['subject']) > 100)
|
||||
error(sprintf($config['error']['toolong'], 'subject'));
|
||||
if (!$mod && mb_strlen($post['body']) > $config['max_body'])
|
||||
error($config['error']['toolong_body']);
|
||||
if (mb_strlen($post['password']) > 20)
|
||||
error(sprintf($config['error']['toolong'], 'password'));
|
||||
}
|
||||
// Check string lengths
|
||||
if (mb_strlen($post['name']) > 35)
|
||||
error(sprintf($config['error']['toolong'], 'name'));
|
||||
if (mb_strlen($post['email']) > 40)
|
||||
error(sprintf($config['error']['toolong'], 'email'));
|
||||
if (mb_strlen($post['subject']) > 100)
|
||||
error(sprintf($config['error']['toolong'], 'subject'));
|
||||
if (!$mod && mb_strlen($post['body']) > $config['max_body'])
|
||||
error($config['error']['toolong_body']);
|
||||
if (mb_strlen($post['password']) > 20)
|
||||
error(sprintf($config['error']['toolong'], 'password'));
|
||||
|
||||
wordfilters($post['body']);
|
||||
|
||||
$post['body'] = escape_markup_modifiers($post['body']);
|
||||
|
||||
if ($mod && isset($post['raw']) && $post['raw']) {
|
||||
if ($mod && isset($post['raw']) && $post['raw'])
|
||||
$post['body'] .= "\n<tinyboard raw html>1</tinyboard>";
|
||||
}
|
||||
|
||||
if (!$dropped_post)
|
||||
if (($config['country_flags'] && !$config['allow_no_country']) || ($config['country_flags'] && $config['allow_no_country'] && !isset($_POST['no_country']))) {
|
||||
$gi=geoip\geoip_open('inc/lib/geoip/GeoIPv6.dat', GEOIP_STANDARD);
|
||||
|
||||
@ -748,8 +539,7 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
}
|
||||
|
||||
if ($config['user_flag'] && isset($_POST['user_flag']))
|
||||
if (!empty($_POST['user_flag']) ){
|
||||
if ($config['user_flag'] && isset($_POST['user_flag']) && !empty($_POST['user_flag']) ){
|
||||
|
||||
$user_flag = $_POST['user_flag'];
|
||||
|
||||
@ -766,8 +556,7 @@ if (isset($_POST['delete'])) {
|
||||
$post['body'] .= "\n<tinyboard tag>" . $_POST['tag'] . "</tinyboard>";
|
||||
}
|
||||
|
||||
if (!$dropped_post)
|
||||
if ($config['proxy_save'] && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
if ($config['proxy_save'] && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$proxy = preg_replace("/[^0-9a-fA-F.,: ]/", '', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||
$post['body'] .= "\n<tinyboard proxy>".$proxy."</tinyboard>";
|
||||
}
|
||||
@ -839,7 +628,7 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPermission($config['mod']['bypass_filters'], $board['uri']) && !$dropped_post) {
|
||||
if (!hasPermission($config['mod']['bypass_filters'], $board['uri'])) {
|
||||
require_once 'inc/filters.php';
|
||||
|
||||
do_filters($post);
|
||||
@ -1042,17 +831,16 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
|
||||
// Do filters again if OCRing
|
||||
if ($config['tesseract_ocr'] && !hasPermission($config['mod']['bypass_filters'], $board['uri']) && !$dropped_post) {
|
||||
if ($config['tesseract_ocr'] && !hasPermission($config['mod']['bypass_filters'], $board['uri']))
|
||||
do_filters($post);
|
||||
}
|
||||
|
||||
if (!hasPermission($config['mod']['postunoriginal'], $board['uri']) && $config['robot_enable'] && checkRobot($post['body_nomarkup']) && !$dropped_post) {
|
||||
if (!hasPermission($config['mod']['postunoriginal'], $board['uri']) && $config['robot_enable'] && checkRobot($post['body_nomarkup'])) {
|
||||
undoImage($post);
|
||||
if ($config['robot_mute']) {
|
||||
|
||||
if ($config['robot_mute'])
|
||||
error(sprintf($config['error']['muted'], mute()));
|
||||
} else {
|
||||
else
|
||||
error($config['error']['unoriginal']);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove board directories before inserting them into the database.
|
||||
@ -1085,42 +873,6 @@ if (isset($_POST['delete'])) {
|
||||
$post['id'] = $id = post($post);
|
||||
$post['slug'] = slugify($post);
|
||||
|
||||
|
||||
if ($dropped_post && $dropped_post['from_nntp']) {
|
||||
$query = prepare("INSERT INTO ``nntp_references`` (`board`, `id`, `message_id`, `message_id_digest`, `own`, `headers`) VALUES ".
|
||||
"(:board , :id , :message_id , :message_id_digest , false, :headers)");
|
||||
|
||||
$query->bindValue(':board', $dropped_post['board']);
|
||||
$query->bindValue(':id', $id);
|
||||
$query->bindValue(':message_id', $dropped_post['msgid']);
|
||||
$query->bindValue(':message_id_digest', sha1($dropped_post['msgid']));
|
||||
$query->bindValue(':headers', $dropped_post['headers']);
|
||||
$query->execute() or error(db_error($query));
|
||||
} // ^^^^^ For inbound posts ^^^^^
|
||||
elseif ($config['nntpchan']['enabled'] && $config['nntpchan']['group']) {
|
||||
// vvvvv For outbound posts vvvvv
|
||||
|
||||
require_once('inc/nntpchan/nntpchan.php');
|
||||
$msgid = gen_msgid($post['board'], $post['id']);
|
||||
|
||||
list($headers, $files) = post2nntp($post, $msgid);
|
||||
|
||||
$message = gen_nntp($headers, $files);
|
||||
|
||||
$query = prepare("INSERT INTO ``nntp_references`` (`board`, `id`, `message_id`, `message_id_digest`, `own`, `headers`) VALUES ".
|
||||
"(:board , :id , :message_id , :message_id_digest , true , :headers)");
|
||||
|
||||
$query->bindValue(':board', $post['board']);
|
||||
$query->bindValue(':id', $post['id']);
|
||||
$query->bindValue(':message_id', $msgid);
|
||||
$query->bindValue(':message_id_digest', sha1($msgid));
|
||||
$query->bindValue(':headers', json_encode($headers));
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
// Let's broadcast it!
|
||||
nntp_publish($message, $msgid);
|
||||
}
|
||||
|
||||
insertFloodPost($post);
|
||||
|
||||
// Handle cyclical threads
|
||||
|
@ -1,86 +0,0 @@
|
||||
<?php
|
||||
require_once("inc/functions.php");
|
||||
require_once("inc/route.php");
|
||||
require_once("inc/controller.php");
|
||||
|
||||
if (!$config["smart_build_helper"]) {
|
||||
die('You need to enable $config["smart_build_helper"]');
|
||||
}
|
||||
|
||||
$config['smart_build'] = false; // Let's disable it, so we can build the page for real
|
||||
$config['generation_strategies'] = array('strategy_immediate');
|
||||
|
||||
function after_open_board() { global $config;
|
||||
$config['smart_build'] = false;
|
||||
$config['generation_strategies'] = array('strategy_immediate');
|
||||
};
|
||||
|
||||
$request = $_SERVER['REQUEST_URI'];
|
||||
|
||||
$route = route($request);
|
||||
|
||||
if (!$route) {
|
||||
$reached = false;
|
||||
}
|
||||
else {
|
||||
list ($fun, $args) = $route;
|
||||
$reached = call_user_func_array($fun, $args);
|
||||
}
|
||||
|
||||
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>";
|
||||
}
|
||||
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");
|
||||
}
|
||||
elseif (preg_match('/\.rss$/', $request)) {
|
||||
header("Content-Type", "application/rss+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();
|
||||
}
|
@ -79,27 +79,6 @@
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if config.captcha.enabled %}
|
||||
<tr class='captcha'>
|
||||
<th>
|
||||
{% trans %}Verification{% endtrans %}
|
||||
</th>
|
||||
<td>
|
||||
<script>load_captcha("{{ config.captcha.provider_get }}", "{{ config.captcha.extra }}");</script>
|
||||
</td>
|
||||
</tr>
|
||||
{% elseif config.new_thread_capt %}
|
||||
{% if not id %}
|
||||
<tr class='captcha'>
|
||||
<th>
|
||||
{% trans %}Verification{% endtrans %}
|
||||
</th>
|
||||
<td>
|
||||
<script>load_captcha("{{ config.captcha.provider_get }}", "{{ config.captcha.extra }}");</script>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if config.user_flag %}
|
||||
<tr>
|
||||
<th>{% trans %}Flag{% endtrans %}</th>
|
||||
|
@ -18,21 +18,13 @@
|
||||
public function build($action, $settings) {
|
||||
global $config, $_theme;
|
||||
|
||||
if ($action == 'all') {
|
||||
if ($action == 'all')
|
||||
copy('templates/themes/awsumchan/' . $settings['basecss'], $config['dir']['home'] . $settings['css']);
|
||||
}
|
||||
|
||||
$this->excluded = explode(' ', $settings['exclude']);
|
||||
|
||||
if ($action == 'all' || $action == 'news' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') {
|
||||
$action = generation_strategy('sb_recent', []);
|
||||
if ($action == 'delete') {
|
||||
file_unlink($config['dir']['home'] . $settings['html']);
|
||||
}
|
||||
elseif ($action == 'rebuild') {
|
||||
file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings));
|
||||
}
|
||||
}
|
||||
if ($action == 'all' || $action == 'news' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete')
|
||||
file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings));
|
||||
}
|
||||
|
||||
// Build news page
|
||||
|
@ -15,28 +15,14 @@
|
||||
|
||||
if ($action == 'all') {
|
||||
foreach ($boards as $board) {
|
||||
$b = new Catalog();
|
||||
|
||||
$action = generation_strategy("sb_catalog", array($board));
|
||||
if ($action == 'delete') {
|
||||
file_unlink($config['dir']['home'] . $board . '/catalog.html');
|
||||
file_unlink($config['dir']['home'] . $board . '/index.rss');
|
||||
}
|
||||
elseif ($action == 'rebuild') {
|
||||
if (in_array($board, $boards)) {
|
||||
$b = new Catalog();
|
||||
$b->build($settings, $board);
|
||||
}
|
||||
}
|
||||
} elseif ($action == 'post-thread' || ($settings['update_on_posts'] && $action == 'post') || ($settings['update_on_posts'] && $action == 'post-delete') && in_array($board, $boards)) {
|
||||
$b = new Catalog();
|
||||
|
||||
$action = generation_strategy("sb_catalog", array($board));
|
||||
if ($action == 'delete') {
|
||||
file_unlink($config['dir']['home'] . $board . '/catalog.html');
|
||||
file_unlink($config['dir']['home'] . $board . '/index.rss');
|
||||
}
|
||||
elseif ($action == 'rebuild') {
|
||||
$b->build($settings, $board);
|
||||
}
|
||||
$b->build($settings, $board);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,21 +18,13 @@
|
||||
public function build($action, $settings) {
|
||||
global $config, $_theme;
|
||||
|
||||
if ($action == 'all') {
|
||||
if ($action == 'all')
|
||||
copy('templates/themes/recent/' . $settings['basecss'], $config['dir']['home'] . $settings['css']);
|
||||
}
|
||||
|
||||
$this->excluded = explode(' ', $settings['exclude']);
|
||||
|
||||
if ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete') {
|
||||
$action = generation_strategy('sb_recent', array());
|
||||
if ($action == 'delete') {
|
||||
file_unlink($config['dir']['home'] . $settings['html']);
|
||||
}
|
||||
elseif ($action == 'rebuild') {
|
||||
if ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete')
|
||||
file_write($config['dir']['home'] . $settings['html'], $this->homepage($settings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build news page
|
||||
|
@ -23,26 +23,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
$action = generation_strategy('sb_sitemap', array());
|
||||
|
||||
if ($action == 'delete') {
|
||||
file_unlink($settings['path']);
|
||||
}
|
||||
elseif ($action == 'rebuild') {
|
||||
$boards = explode(' ', $settings['boards']);
|
||||
|
||||
$threads = array();
|
||||
|
||||
foreach ($boards as $board) {
|
||||
$query = query(sprintf("SELECT `id`, `id` AS `thread_id`, `slug`, (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,
|
||||
)));
|
||||
$boards = explode(' ', $settings['boards']);
|
||||
|
||||
$threads = array();
|
||||
|
||||
foreach ($boards as $board) {
|
||||
$query = query(sprintf("SELECT `id`, `id` AS `thread_id`, `slug`, (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,
|
||||
)));
|
||||
}
|
||||
|
@ -11,14 +11,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$action = generation_strategy('sb_ukko', array());
|
||||
|
||||
if ($action == 'delete') {
|
||||
file_unlink($settings['uri'] . '/index.html');
|
||||
}
|
||||
elseif ($action == 'rebuild') {
|
||||
file_write($settings['uri'] . '/index.html', $ukko->build());
|
||||
}
|
||||
file_write($settings['uri'] . '/index.html', $ukko->build());
|
||||
}
|
||||
|
||||
class ukko {
|
||||
|
@ -1,31 +0,0 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
/* worker.php - part of advanced build vichan feature */
|
||||
|
||||
require dirname(__FILE__) . '/inc/cli.php';
|
||||
require_once 'inc/controller.php';
|
||||
|
||||
$config['smart_build'] = false; // Let's disable it, so we can build the page for real
|
||||
$config['generation_strategies'] = array('strategy_immediate');
|
||||
|
||||
function after_open_board() { global $config;
|
||||
$config['smart_build'] = false;
|
||||
$config['generation_strategies'] = array('strategy_immediate');
|
||||
};
|
||||
|
||||
echo "Hello world!\n";
|
||||
|
||||
$queue = get_queue('generate');
|
||||
|
||||
while (true) {
|
||||
$q = $queue->pop(2);
|
||||
foreach ($q as $v) {
|
||||
list($__, $func, $ary, $action) = unserialize($v);
|
||||
echo "Starting to generate $func ".implode(" ", $ary)."... ";
|
||||
|
||||
call_user_func_array($func, $ary);
|
||||
|
||||
echo "done!\n";
|
||||
}
|
||||
if (!$q) usleep(20000); // 0.02s
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user