2010-11-02 12:54:50 +01:00
< ? php
2011-04-13 14:21:07 +02:00
if ( $_SERVER [ 'SCRIPT_FILENAME' ] == str_replace ( '\\' , '/' , __FILE__ )) {
// You cannot request this file directly.
header ( 'Location: ../' , true , 302 );
exit ;
}
2011-05-20 14:53:34 +02:00
register_shutdown_function ( 'fatal_error_handler' );
2011-02-16 06:21:14 +01:00
loadConfig ();
function loadConfig () {
2011-05-21 07:21:45 +02:00
global $board , $config , $__ip , $debug ;
2011-02-16 06:21:14 +01:00
require 'config.php' ;
if ( file_exists ( 'inc/instance-config.php' )) {
require 'instance-config.php' ;
}
2011-02-16 09:41:34 +01:00
if ( isset ( $board [ 'dir' ]) && file_exists ( $board [ 'dir' ] . '/config.php' )) {
require $board [ 'dir' ] . '/config.php' ;
}
2011-02-16 06:21:14 +01:00
2011-05-21 07:21:45 +02:00
if ( $config [ 'debug' ]) {
if ( ! isset ( $debug ))
$debug = Array ( 'sql' );
$debug [ 'start' ] = time ();
}
2011-03-26 08:23:15 +01:00
if ( ! isset ( $config [ 'url_stylesheet' ]))
$config [ 'url_stylesheet' ] = $config [ 'root' ] . 'style.css' ;
if ( ! isset ( $config [ 'url_javascript' ]))
2011-03-26 16:36:32 +01:00
$config [ 'url_javascript' ] = $config [ 'root' ] . 'main.js' ;
2011-03-26 08:23:15 +01:00
2011-02-16 06:24:23 +01:00
if ( ! isset ( $config [ 'post_url' ]))
2011-02-16 06:26:02 +01:00
$config [ 'post_url' ] = $config [ 'root' ] . $config [ 'file_post' ];
2011-02-16 06:21:14 +01:00
2011-02-16 06:24:23 +01:00
if ( ! isset ( $config [ 'url_match' ]))
$config [ 'url_match' ] = '/^' .
( preg_match ( $config [ 'url_regex' ], $config [ 'root' ]) ? '' :
2011-05-18 18:36:11 +02:00
( isset ( $_SERVER [ 'HTTPS' ]) && $_SERVER [ 'HTTPS' ] && $_SERVER [ 'HTTPS' ] != 'off' ? 'https' : 'http' ) .
2011-02-16 06:24:23 +01:00
':\/\/' . $_SERVER [ 'HTTP_HOST' ]) .
preg_quote ( $config [ 'root' ], '/' ) .
'(' .
str_replace ( '%s' , '\w{1,8}' , preg_quote ( $config [ 'board_path' ], '/' )) .
'|' .
str_replace ( '%s' , '\w{1,8}' , preg_quote ( $config [ 'board_path' ], '/' )) .
preg_quote ( $config [ 'file_index' ], '/' ) .
'|' .
str_replace ( '%s' , '\w{1,8}' , preg_quote ( $config [ 'board_path' ], '/' )) .
str_replace ( '%d' , '\d+' , preg_quote ( $config [ 'file_page' ], '/' )) .
'|' .
preg_quote ( $config [ 'file_mod' ], '/' ) .
'\?\/.+' .
')$/i' ;
2011-02-16 06:21:14 +01:00
2011-03-27 17:22:48 +02:00
if ( ! isset ( $config [ 'cookies' ][ 'path' ]))
$config [ 'cookies' ][ 'path' ] = $config [ 'root' ];
2011-02-16 06:24:23 +01:00
if ( ! isset ( $config [ 'dir' ][ 'static' ]))
2011-02-16 06:26:02 +01:00
$config [ 'dir' ][ 'static' ] = $config [ 'root' ] . 'static/' ;
2011-02-16 06:21:14 +01:00
2011-02-16 06:24:23 +01:00
if ( ! isset ( $config [ 'image_sticky' ]))
2011-02-16 06:26:02 +01:00
$config [ 'image_sticky' ] = $config [ 'dir' ][ 'static' ] . 'sticky.gif' ;
2011-02-16 06:24:23 +01:00
if ( ! isset ( $config [ 'image_locked' ]))
2011-02-16 06:26:02 +01:00
$config [ 'image_locked' ] = $config [ 'dir' ][ 'static' ] . 'locked.gif' ;
2011-02-16 06:24:23 +01:00
if ( ! isset ( $config [ 'image_deleted' ]))
2011-02-16 06:26:02 +01:00
$config [ 'image_deleted' ] = $config [ 'dir' ][ 'static' ] . 'deleted.png' ;
2011-02-16 06:24:23 +01:00
if ( ! isset ( $config [ 'image_zip' ]))
2011-02-16 06:26:02 +01:00
$config [ 'image_zip' ] = $config [ 'dir' ][ 'static' ] . 'zip.png' ;
2011-02-16 09:29:56 +01:00
2011-03-17 08:56:18 +01:00
if ( ! isset ( $config [ 'uri_thumb' ]))
$config [ 'uri_thumb' ] = $config [ 'root' ] . $board [ 'dir' ] . $config [ 'dir' ][ 'thumb' ];
else
$config [ 'uri_thumb' ] = sprintf ( $config [ 'uri_thumb' ], $board [ 'dir' ]);
if ( ! isset ( $config [ 'uri_img' ]))
$config [ 'uri_img' ] = $config [ 'root' ] . $board [ 'dir' ] . $config [ 'dir' ][ 'img' ];
else
$config [ 'uri_img' ] = sprintf ( $config [ 'uri_img' ], $board [ 'dir' ]);
2011-03-26 16:36:32 +01:00
if ( ! isset ( $config [ 'uri_stylesheets' ]))
$config [ 'uri_stylesheets' ] = $config [ 'root' ];
2011-02-16 09:29:56 +01:00
if ( $config [ 'root_file' ]) {
chdir ( $config [ 'root_file' ]);
}
if ( $config [ 'verbose_errors' ]) {
error_reporting ( E_ALL );
ini_set ( 'display_errors' , 1 );
}
2011-02-17 10:58:34 +01:00
2011-03-21 09:48:43 +01:00
if ( $config [ 'ipv6_ipv4' ] && isset ( $_SERVER [ 'REMOTE_ADDR' ])) {
2011-02-17 10:59:36 +01:00
// Keep the original address to properly comply with other board configurations
2011-02-17 10:58:34 +01:00
if ( ! isset ( $__ip ))
$__ip = $_SERVER [ 'REMOTE_ADDR' ];
// ::ffff:0.0.0.0
2011-02-28 06:04:06 +01:00
if ( preg_match ( '/^\:\:(ffff\:)?(\d+\.\d+\.\d+\.\d+)$/' , $__ip , $m ))
2011-03-01 11:26:04 +01:00
$_SERVER [ 'REMOTE_ADDR' ] = $m [ 2 ];
2011-02-17 10:58:34 +01:00
}
2011-04-22 16:24:15 +02:00
if ( $config [ 'memcached' ][ 'enabled' ])
memcached_open ();
2011-04-30 10:52:04 +02:00
}
function basic_error_function_because_the_other_isnt_loaded_yet ( $message ) {
if ( function_exists ( 'sql_close' )) sql_close ();
// Yes, this is horrible.
die ( '<!DOCTYPE html><html><head><title>Error</title>' .
'<style type="text/css">' .
'body{text-align:center;font-family:arial, helvetica, sans-serif;font-size:10pt;}' .
'p{padding:0;margin:20px 0;}' .
'p.c{font-size:11px;}' .
'</style></head>' .
'<body><h2>Error</h2>' . $message . '<hr/>' .
'<p class="c">This alternative error page is being displayed because the other couldn\'t be found or hasn\'t loaded yet.</p></body></html>' );
2011-04-22 16:24:15 +02:00
}
2011-04-22 16:45:32 +02:00
function fatal_error_handler () {
if ( $error = error_get_last ()) {
2011-04-22 16:55:51 +02:00
if ( $error [ 'type' ] == E_ERROR ) {
if ( function_exists ( 'error' )) {
error ( 'Caught fatal error: ' . $error [ 'message' ] . ' in <strong>' . $error [ 'file' ] . '</strong> on line ' . $error [ 'line' ]);
} else {
2011-05-20 14:53:34 +02:00
basic_error_function_because_the_other_isnt_loaded_yet ( 'Caught fatal error: ' . $error [ 'message' ] . ' in ' . $error [ 'file' ] . ' on line ' . $error [ 'line' ]);
2011-04-22 16:55:51 +02:00
}
}
2011-04-22 16:45:32 +02:00
}
}
2011-04-22 16:24:15 +02:00
// Memcached
function memcached_open () {
global $memcached , $config ;
if ( $memcached ) return ;
$memcached = new Memcached ();
$memcached -> addServers ( $config [ 'memcached' ][ 'servers' ]);
2011-02-16 06:21:14 +01:00
}
2011-04-13 15:47:47 +02:00
function loadThemeConfig ( $_theme ) {
global $config ;
2011-04-14 14:12:56 +02:00
if ( ! file_exists ( $config [ 'dir' ][ 'homepage' ] . '/' . $_theme . '/info.php' ))
2011-04-14 09:10:59 +02:00
return false ;
2011-04-13 15:47:47 +02:00
// Load theme information into $theme
2011-04-14 14:12:56 +02:00
include $config [ 'dir' ][ 'homepage' ] . '/' . $_theme . '/info.php' ;
2011-04-13 15:47:47 +02:00
return $theme ;
}
2011-04-14 12:43:34 +02:00
function rebuildTheme ( $action ) {
2011-04-14 20:59:04 +02:00
global $config , $_theme ;
2011-04-14 14:12:56 +02:00
2011-04-14 09:03:12 +02:00
$query = query ( " SELECT `value` AS `theme` FROM `theme_settings` WHERE `name` = 'theme' " ) or error ( db_error ());
if ( $theme = $query -> fetch ()) {
// A theme is installed
2011-04-14 14:12:56 +02:00
$_theme = $theme [ 'theme' ];
$theme = loadThemeConfig ( $_theme );
2011-04-14 09:03:12 +02:00
2011-04-14 14:12:56 +02:00
if ( file_exists ( $config [ 'dir' ][ 'homepage' ] . '/' . $_theme . '/theme.php' )) {
include $config [ 'dir' ][ 'homepage' ] . '/' . $_theme . '/theme.php' ;
$theme [ 'build_function' ]( $action , themeSettings ());
}
2011-04-14 09:03:12 +02:00
}
}
2011-04-13 15:47:47 +02:00
function themeSettings () {
$query = query ( " SELECT * FROM `theme_settings` " ) or error ( db_error ());
$settings = Array ();
while ( $s = $query -> fetch ()) {
$settings [ $s [ 'name' ]] = $s [ 'value' ];
}
return $settings ;
}
2010-11-04 12:58:51 +01:00
function sprintf3 ( $str , $vars , $delim = '%' ) {
$replaces = array ();
foreach ( $vars as $k => $v ) {
$replaces [ $delim . $k . $delim ] = $v ;
2010-11-04 12:30:23 +01:00
}
2010-11-04 12:58:51 +01:00
return str_replace ( array_keys ( $replaces ),
array_values ( $replaces ), $str );
}
2010-11-30 10:24:09 +01:00
function setupBoard ( $array ) {
2011-02-12 07:25:15 +01:00
global $board , $config ;
2010-11-30 10:24:09 +01:00
$board = Array (
'id' => $array [ 'id' ],
'uri' => $array [ 'uri' ],
'name' => $array [ 'title' ],
'title' => $array [ 'subtitle' ]);
2011-02-12 07:25:15 +01:00
$board [ 'dir' ] = sprintf ( $config [ 'board_path' ], $board [ 'uri' ]);
$board [ 'url' ] = sprintf ( $config [ 'board_abbreviation' ], $board [ 'uri' ]);
2010-11-30 10:24:09 +01:00
2011-02-16 09:41:34 +01:00
loadConfig ();
2010-11-30 10:24:09 +01:00
if ( ! file_exists ( $board [ 'dir' ])) mkdir ( $board [ 'dir' ], 0777 );
2011-02-12 07:25:15 +01:00
if ( ! file_exists ( $board [ 'dir' ] . $config [ 'dir' ][ 'img' ])) @ mkdir ( $board [ 'dir' ] . $config [ 'dir' ][ 'img' ], 0777 ) or error ( " Couldn't create " . $config [ 'dir' ][ 'img' ] . " . Check permissions. " , true );
if ( ! file_exists ( $board [ 'dir' ] . $config [ 'dir' ][ 'thumb' ])) @ mkdir ( $board [ 'dir' ] . $config [ 'dir' ][ 'thumb' ], 0777 ) or error ( " Couldn't create " . $config [ 'dir' ][ 'thumb' ] . " . Check permissions. " , true );
if ( ! file_exists ( $board [ 'dir' ] . $config [ 'dir' ][ 'res' ])) @ mkdir ( $board [ 'dir' ] . $config [ 'dir' ][ 'res' ], 0777 ) or error ( " Couldn't create " . $config [ 'dir' ][ 'res' ] . " . Check permissions. " , true );
2010-11-30 10:24:09 +01:00
}
2010-11-30 10:38:36 +01:00
function openBoard ( $uri ) {
2010-12-17 15:18:03 +01:00
$query = prepare ( " SELECT * FROM `boards` WHERE `uri` = :uri LIMIT 1 " );
$query -> bindValue ( ':uri' , $uri );
$query -> execute () or error ( db_error ( $query ));
if ( $board = $query -> fetch ()) {
setupBoard ( $board );
2010-11-30 10:38:36 +01:00
return true ;
} else return false ;
}
2011-05-20 09:19:27 +02:00
function file_write ( $path , $data ) {
2011-05-20 14:44:35 +02:00
global $config ;
if ( preg_match ( '/^scp:\/\/(.+)$/' , $path , $m )) {
// Experimental: secure copy...
$file = tempnam ( $config [ 'tmp' ], 'tinyboard-scp' );
// Write to temp file
file_write ( $file , $data );
// Call `scp` (yes, this is horrible)
$command = 'scp ' . escapeshellarg ( $file ) . ' ' . escapeshellarg ( $m [ 1 ]);
system ( $command );
// Delete temporary file
unlink ( $file );
2011-05-21 07:24:06 +02:00
return ;
2011-05-20 14:44:35 +02:00
}
2011-05-20 09:22:08 +02:00
if ( ! $fp = fopen ( $path , 'c' ))
error ( 'Unable to open file for writing: ' . $path );
2011-05-20 14:44:35 +02:00
2011-05-20 09:19:27 +02:00
// File locking
if ( ! flock ( $fp , LOCK_EX )) {
2011-05-20 09:22:08 +02:00
error ( 'Unable to lock file: ' . $path );
2011-05-20 09:19:27 +02:00
}
// Truncate file
ftruncate ( $fp , 0 );
// Write data
fwrite ( $fp , $data );
flock ( $fp , LOCK_UN );
fclose ( $fp );
}
2010-12-02 08:15:50 +01:00
function listBoards () {
2011-01-20 09:24:23 +01:00
$query = query ( " SELECT * FROM `boards` ORDER BY `uri` " ) or error ( db_error ());
2010-12-17 15:18:03 +01:00
$boards = $query -> fetchAll ();
2010-12-02 08:15:50 +01:00
return $boards ;
}
2011-01-18 07:11:28 +01:00
function checkFlood ( $post ) {
2011-02-12 07:25:15 +01:00
global $board , $config ;
2011-01-18 07:11:28 +01:00
$query = prepare ( sprintf ( " SELECT * FROM `posts_%s` WHERE (`ip` = :ip AND `time` >= :floodtime) OR (`ip` = :ip AND `body` = :body AND `time` >= :floodsameiptime) OR (`body` = :body AND `time` >= :floodsametime) LIMIT 1 " , $board [ 'uri' ]));
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
$query -> bindValue ( ':body' , $post [ 'body' ], PDO :: PARAM_INT );
2011-02-12 07:25:15 +01:00
$query -> bindValue ( ':floodtime' , time () - $config [ 'flood_time' ], PDO :: PARAM_INT );
$query -> bindValue ( ':floodsameiptime' , time () - $config [ 'flood_time_ip' ], PDO :: PARAM_INT );
$query -> bindValue ( ':floodsametime' , time () - $config [ 'flood_time_same' ], PDO :: PARAM_INT );
2011-01-18 07:11:28 +01:00
$query -> execute () or error ( db_error ( $query ));
return ( bool ) $query -> fetch ();
}
2011-01-01 15:37:52 +01:00
function until ( $timestamp ) {
$difference = $timestamp - time ();
if ( $difference < 60 ) {
return $difference . ' second' . ( $difference != 1 ? 's' : '' );
} elseif ( $difference < 60 * 60 ) {
return ( $num = round ( $difference / ( 60 ))) . ' minute' . ( $num != 1 ? 's' : '' );
} elseif ( $difference < 60 * 60 * 24 ) {
return ( $num = round ( $difference / ( 60 * 60 ))) . ' hour' . ( $num != 1 ? 's' : '' );
} elseif ( $difference < 60 * 60 * 24 * 7 ) {
return ( $num = round ( $difference / ( 60 * 60 * 24 ))) . ' day' . ( $num != 1 ? 's' : '' );
2011-01-02 17:27:34 +01:00
} elseif ( $difference < 60 * 60 * 24 * 365 ) {
2011-01-01 15:37:52 +01:00
return ( $num = round ( $difference / ( 60 * 60 * 24 * 7 ))) . ' week' . ( $num != 1 ? 's' : '' );
2011-03-01 11:26:04 +01:00
} else {
return ( $num = round ( $difference / ( 60 * 60 * 24 * 365 ))) . ' year' . ( $num != 1 ? 's' : '' );
}
}
function ago ( $timestamp ) {
$difference = time () - $timestamp ;
if ( $difference < 60 ) {
return $difference . ' second' . ( $difference != 1 ? 's' : '' );
} elseif ( $difference < 60 * 60 ) {
return ( $num = round ( $difference / ( 60 ))) . ' minute' . ( $num != 1 ? 's' : '' );
} elseif ( $difference < 60 * 60 * 24 ) {
return ( $num = round ( $difference / ( 60 * 60 ))) . ' hour' . ( $num != 1 ? 's' : '' );
} elseif ( $difference < 60 * 60 * 24 * 7 ) {
return ( $num = round ( $difference / ( 60 * 60 * 24 ))) . ' day' . ( $num != 1 ? 's' : '' );
} elseif ( $difference < 60 * 60 * 24 * 365 ) {
return ( $num = round ( $difference / ( 60 * 60 * 24 * 7 ))) . ' week' . ( $num != 1 ? 's' : '' );
2011-01-01 15:37:52 +01:00
} else {
2011-01-02 17:27:34 +01:00
return ( $num = round ( $difference / ( 60 * 60 * 24 * 365 ))) . ' year' . ( $num != 1 ? 's' : '' );
2011-01-01 15:37:52 +01:00
}
}
function formatDate ( $timestamp ) {
return date ( 'jS F, Y' , $timestamp );
}
2011-04-22 16:24:15 +02:00
function displayBan ( $ban ) {
2011-02-12 07:25:15 +01:00
global $config ;
2011-04-22 16:24:15 +02:00
$body = ' < div class = " ban " >
2011-01-01 15:37:52 +01:00
< h2 > You are banned ! ; _ ; </ h2 >
< p > You have been banned ' .
( $ban [ 'reason' ] ? 'for the following reason:' : 'for an unspecified reason.' ) .
'</p>' .
( $ban [ 'reason' ] ?
'<p class="reason">' .
$ban [ 'reason' ] .
'</p>'
: '' ) .
'<p>Your ban was filed on <strong>' .
formatDate ( $ban [ 'set' ]) .
2011-01-03 05:00:14 +01:00
'</strong>, and <span id="expires">' .
2011-01-01 15:37:52 +01:00
( $ban [ 'expires' ] ?
2011-01-03 05:00:14 +01:00
'expires <span id="countdown">' . until ( $ban [ 'expires' ]) . '</span> from now, which is on <strong>' .
2011-01-01 15:37:52 +01:00
formatDate ( $ban [ 'expires' ]) .
2011-01-03 05:00:14 +01:00
' </ strong >
2011-01-02 17:27:34 +01:00
< script >
// return date("jS F, Y", $timestamp);
var secondsLeft = ' . ($ban[' expires '] - time()) . '
var end = new Date () . getTime () + secondsLeft * 1000 ;
function updateExpiresTime () {
2011-01-03 05:00:14 +01:00
countdown . firstChild . nodeValue = until ( end );
2011-01-02 17:27:34 +01:00
}
function until ( end ) {
var now = new Date () . getTime ();
var diff = Math . round (( end - now ) / 1000 ); // in seconds
2011-01-03 05:00:14 +01:00
if ( diff < 0 ) {
document . getElementById ( " expires " ) . innerHTML = " has since expired. Refresh the page to continue. " ;
//location.reload(true);
clearInterval ( int );
return " " ;
} else if ( diff < 60 ) {
2011-01-02 17:27:34 +01:00
return diff + " second " + ( diff == 1 ? " " : " s " );
} else if ( diff < 60 * 60 ) {
return ( num = Math . round ( diff / ( 60 ))) + " minute " + ( num == 1 ? " " : " s " );
} else if ( diff < 60 * 60 * 24 ) {
return ( num = Math . round ( diff / ( 60 * 60 ))) + " hour " + ( num == 1 ? " " : " s " );
} else if ( diff < 60 * 60 * 24 * 7 ) {
return ( num = Math . round ( diff / ( 60 * 60 * 24 ))) + " day " + ( num == 1 ? " " : " s " );
} else if ( diff < 60 * 60 * 24 * 365 ) {
return ( num = Math . round ( diff / ( 60 * 60 * 24 * 7 ))) + " week " + ( num == 1 ? " " : " s " );
} else {
2011-03-27 13:40:29 +02:00
return ( num = Math . round ( diff / ( 60 * 60 * 24 * 365 ))) + " year " + ( num == 1 ? " " : " s " );
2011-01-02 17:27:34 +01:00
}
}
2011-01-03 05:00:14 +01:00
var countdown = document . getElementById ( " countdown " );
2011-01-02 17:27:34 +01:00
updateExpiresTime ();
2011-01-03 05:00:14 +01:00
var int = setInterval ( updateExpiresTime , 1000 );
2011-01-02 17:27:34 +01:00
</ script > '
2011-01-03 05:00:14 +01:00
: '<em>will not expire</em>.' ) .
' </ span ></ p >
2011-01-01 15:37:52 +01:00
< p > Your IP address is < strong > ' . $_SERVER[' REMOTE_ADDR '] . ' </ strong >.</ p >
2011-04-22 16:24:15 +02:00
</ div > ' ;
// Show banned page and exit
die ( Element ( 'page.html' , Array (
'config' => $config ,
'title' => 'Banned' ,
'subtitle' => 'You are banned!' ,
'body' => $body
)
));
}
function checkBan () {
global $config , $memcached ;
if ( ! isset ( $_SERVER [ 'REMOTE_ADDR' ])) {
// Server misconfiguration
return ;
}
if ( $config [ 'memcached' ][ 'enabled' ]) {
// Cached ban?
if ( $ban = $memcached -> get ( " ban_ ${ _SERVER['REMOTE_ADDR'] } " )) {
displayBan ( $ban );
}
}
$query = prepare ( " SELECT * FROM `bans` WHERE `ip` = :ip ORDER BY `expires` IS NULL DESC, `expires` DESC, `expires` DESC LIMIT 1 " );
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
$query -> execute () or error ( db_error ( $query ));
if ( $query -> rowCount () < 1 && $config [ 'ban_range' ]) {
$query = prepare ( " SELECT * FROM `bans` WHERE :ip REGEXP CONCAT('^', REPLACE(REPLACE(`ip`, '.', ' \\ .'), '*', '[0-9]*'), ' $ ') ORDER BY `expires` IS NULL DESC, `expires` DESC LIMIT 1 " );
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
$query -> execute () or error ( db_error ( $query ));
}
if ( $ban = $query -> fetch ()) {
if ( $ban [ 'expires' ] && $ban [ 'expires' ] < time ()) {
// Ban expired
$query = prepare ( " DELETE FROM `bans` WHERE `ip` = :ip AND `expires` = :expires LIMIT 1 " );
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
$query -> bindValue ( ':expires' , $ban [ 'expires' ], PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
if ( $config [ 'ban_range' ]) {
$query = prepare ( " DELETE FROM `bans` WHERE :ip REGEXP CONCAT('^', REPLACE(REPLACE(`ip`, '.', ' \\ .'), '*', '[0-9a-f]*'), ' $ ') AND `expires` = :expires LIMIT 1 " );
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
$query -> bindValue ( ':expires' , $ban [ 'expires' ], PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
}
return ;
}
2011-01-01 15:37:52 +01:00
2011-04-22 16:24:15 +02:00
if ( $config [ 'memcached' ][ 'enabled' ])
$memcached -> set ( " ban_ ${ _SERVER['REMOTE_ADDR'] } " , $ban , $ban [ 'expires' ]);
displayBan ( $ban );
2011-01-01 15:37:52 +01:00
}
}
2011-01-02 15:23:34 +01:00
function threadLocked ( $id ) {
global $board ;
$query = prepare ( sprintf ( " SELECT `locked` FROM `posts_%s` WHERE `id` = :id AND `thread` IS NULL LIMIT 1 " , $board [ 'uri' ]));
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ());
if ( ! $post = $query -> fetch ()) {
// Non-existant, so it can't be locked...
return false ;
}
return ( bool ) $post [ 'locked' ];
}
2010-11-30 13:12:54 +01:00
function threadExists ( $id ) {
2010-12-17 15:18:03 +01:00
global $board ;
$query = prepare ( sprintf ( " SELECT 1 FROM `posts_%s` WHERE `id` = :id AND `thread` IS NULL LIMIT 1 " , $board [ 'uri' ]));
2010-12-18 05:07:07 +01:00
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
2010-12-17 15:18:03 +01:00
$query -> execute () or error ( db_error ());
2010-11-30 13:12:54 +01:00
2010-12-17 15:18:03 +01:00
if ( $query -> rowCount ()) {
2010-11-30 13:12:54 +01:00
return true ;
} else return false ;
}
2010-11-04 12:58:51 +01:00
function post ( $post , $OP ) {
2010-12-17 15:18:03 +01:00
global $pdo , $board ;
2011-05-18 09:05:48 +02:00
$query = prepare ( sprintf ( " INSERT INTO `posts_%s` VALUES ( NULL, :thread, :subject, :email, :name, :trip, :capcode, :body, :time, :time, :thumb, :thumbwidth, :thumbheight, :file, :width, :height, :filesize, :filename, :filehash, :password, :ip, :sticky, :locked, :embed) " , $board [ 'uri' ]));
2010-12-17 15:18:03 +01:00
// Basic stuff
$query -> bindValue ( ':subject' , $post [ 'subject' ]);
$query -> bindValue ( ':email' , $post [ 'email' ]);
$query -> bindValue ( ':name' , $post [ 'name' ]);
$query -> bindValue ( ':trip' , $post [ 'trip' ]);
$query -> bindValue ( ':body' , $post [ 'body' ]);
$query -> bindValue ( ':time' , time (), PDO :: PARAM_INT );
$query -> bindValue ( ':password' , $post [ 'password' ]);
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
2011-01-02 11:15:59 +01:00
if ( $post [ 'mod' ] && $post [ 'sticky' ]) {
$query -> bindValue ( ':sticky' , 1 , PDO :: PARAM_INT );
} else {
$query -> bindValue ( ':sticky' , 0 , PDO :: PARAM_INT );
}
2010-12-17 15:18:03 +01:00
2011-01-02 12:25:17 +01:00
if ( $post [ 'mod' ] && $post [ 'locked' ]) {
$query -> bindValue ( ':locked' , 1 , PDO :: PARAM_INT );
} else {
$query -> bindValue ( ':locked' , 0 , PDO :: PARAM_INT );
}
2011-04-12 13:08:54 +02:00
if ( $post [ 'mod' ] && $post [ 'capcode' ]) {
$query -> bindValue ( ':capcode' , $post [ 'capcode' ], PDO :: PARAM_INT );
} else {
$query -> bindValue ( ':capcode' , NULL , PDO :: PARAM_NULL );
}
2011-05-18 09:05:48 +02:00
if ( ! empty ( $post [ 'embed' ])) {
$query -> bindValue ( ':embed' , $post [ 'embed' ]);
} else {
$query -> bindValue ( ':embed' , NULL , PDO :: PARAM_NULL );
}
2010-11-04 12:58:51 +01:00
if ( $OP ) {
2010-12-17 15:18:03 +01:00
// No parent thread, image
$query -> bindValue ( ':thread' , null , PDO :: PARAM_NULL );
2010-11-04 12:58:51 +01:00
} else {
2010-12-17 15:18:03 +01:00
$query -> bindValue ( ':thread' , $post [ 'thread' ], PDO :: PARAM_INT );
2010-11-04 12:58:51 +01:00
}
2010-12-17 15:18:03 +01:00
if ( $post [ 'has_file' ]) {
$query -> bindValue ( ':thumb' , $post [ 'thumb' ]);
$query -> bindValue ( ':thumbwidth' , $post [ 'thumbwidth' ], PDO :: PARAM_INT );
$query -> bindValue ( ':thumbheight' , $post [ 'thumbheight' ], PDO :: PARAM_INT );
$query -> bindValue ( ':file' , $post [ 'file' ]);
$query -> bindValue ( ':width' , $post [ 'width' ], PDO :: PARAM_INT );
$query -> bindValue ( ':height' , $post [ 'height' ], PDO :: PARAM_INT );
$query -> bindValue ( ':filesize' , $post [ 'filesize' ], PDO :: PARAM_INT );
2011-01-01 10:45:18 +01:00
$query -> bindValue ( ':filename' , $post [ 'filename' ]);
2011-04-13 12:57:41 +02:00
$query -> bindValue ( ':filehash' , $post [ 'file' ]);
2010-12-17 15:18:03 +01:00
} else {
$query -> bindValue ( ':thumb' , null , PDO :: PARAM_NULL );
$query -> bindValue ( ':thumbwidth' , null , PDO :: PARAM_NULL );
$query -> bindValue ( ':thumbheight' , null , PDO :: PARAM_NULL );
$query -> bindValue ( ':file' , null , PDO :: PARAM_NULL );
$query -> bindValue ( ':width' , null , PDO :: PARAM_NULL );
$query -> bindValue ( ':height' , null , PDO :: PARAM_NULL );
$query -> bindValue ( ':filesize' , null , PDO :: PARAM_NULL );
$query -> bindValue ( ':filename' , null , PDO :: PARAM_NULL );
$query -> bindValue ( ':filehash' , null , PDO :: PARAM_NULL );
}
$query -> execute () or error ( db_error ( $query ));
return $pdo -> lastInsertId ();
}
function bumpThread ( $id ) {
global $board ;
$query = prepare ( sprintf ( " UPDATE `posts_%s` SET `bump` = :time WHERE `id` = :id AND `thread` IS NULL " , $board [ 'uri' ]));
$query -> bindValue ( ':time' , time (), PDO :: PARAM_INT );
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
2010-11-04 12:58:51 +01:00
}
2011-01-18 14:41:43 +01:00
2011-01-21 03:14:55 +01:00
// Remove file from post
function deleteFile ( $id , $remove_entirely_if_already = true ) {
2011-02-12 07:25:15 +01:00
global $board , $config ;
2011-01-21 03:14:55 +01:00
$query = prepare ( sprintf ( " SELECT `thread`,`thumb`,`file` FROM `posts_%s` WHERE `id` = :id AND `thread` IS NOT NULL LIMIT 1 " , $board [ 'uri' ]));
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
if ( $query -> rowCount () < 1 ) {
2011-02-12 07:25:15 +01:00
error ( $config [ 'error' ][ 'invalidpost' ]);
2011-01-21 03:14:55 +01:00
}
$post = $query -> fetch ();
$query = prepare ( sprintf ( " UPDATE `posts_%s` SET `thumb` = NULL, `thumbwidth` = NULL, `thumbheight` = NULL, `filewidth` = NULL, `fileheight` = NULL, `filesize` = NULL, `filename` = NULL, `filehash` = NULL, `file` = :file WHERE `id` = :id OR `thread` = :id " , $board [ 'uri' ]));
if ( $post [ 'file' ] == 'deleted' && $remove_entirely_if_already ) {
// Already deleted; remove file fully
$query -> bindValue ( ':file' , null , PDO :: PARAM_NULL );
} else {
// Delete thumbnail
2011-02-12 07:25:15 +01:00
@ unlink ( $board [ 'dir' ] . $config [ 'dir' ][ 'thumb' ] . $post [ 'thumb' ]);
2011-01-21 03:14:55 +01:00
// Delete file
2011-02-12 07:25:15 +01:00
@ unlink ( $board [ 'dir' ] . $config [ 'dir' ][ 'img' ] . $post [ 'file' ]);
2011-01-21 03:14:55 +01:00
// Set file to 'deleted'
$query -> bindValue ( ':file' , 'deleted' , PDO :: PARAM_INT );
}
// Update database
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
buildThread ( $post [ 'thread' ]);
}
2011-01-18 14:41:43 +01:00
// Delete a post (reply or thread)
2011-02-11 13:02:30 +01:00
function deletePost ( $id , $error_if_doesnt_exist = true ) {
2011-02-12 07:25:15 +01:00
global $board , $config ;
2011-01-18 14:41:43 +01:00
// Select post and replies (if thread) in one query
$query = prepare ( sprintf ( " SELECT `id`,`thread`,`thumb`,`file` FROM `posts_%s` WHERE `id` = :id OR `thread` = :id " , $board [ 'uri' ]));
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
if ( $query -> rowCount () < 1 ) {
2011-02-11 13:02:30 +01:00
if ( $error_if_doesnt_exist )
2011-02-12 07:25:15 +01:00
error ( $config [ 'error' ][ 'invalidpost' ]);
2011-02-11 13:02:30 +01:00
else return false ;
2011-01-18 14:41:43 +01:00
}
// Delete posts and maybe replies
while ( $post = $query -> fetch ()) {
if ( ! $post [ 'thread' ]) {
// Delete thread HTML page
2011-02-12 07:25:15 +01:00
@ unlink ( $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] . sprintf ( $config [ 'file_page' ], $post [ 'id' ]));
2011-01-18 14:41:43 +01:00
} elseif ( $query -> rowCount () == 1 ) {
// Rebuild thread
$rebuild = $post [ 'thread' ];
}
if ( $post [ 'thumb' ]) {
// Delete thumbnail
2011-02-12 07:25:15 +01:00
@ unlink ( $board [ 'dir' ] . $config [ 'dir' ][ 'thumb' ] . $post [ 'thumb' ]);
2011-01-18 14:41:43 +01:00
}
if ( $post [ 'file' ]) {
// Delete file
2011-02-12 07:25:15 +01:00
@ unlink ( $board [ 'dir' ] . $config [ 'dir' ][ 'img' ] . $post [ 'file' ]);
2011-01-18 14:41:43 +01:00
}
}
$query = prepare ( sprintf ( " DELETE FROM `posts_%s` WHERE `id` = :id OR `thread` = :id " , $board [ 'uri' ]));
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
if ( isset ( $rebuild )) {
buildThread ( $rebuild );
}
2011-02-11 13:02:30 +01:00
return true ;
2011-01-18 14:41:43 +01:00
}
function clean () {
2011-02-12 07:25:15 +01:00
global $board , $config ;
$offset = round ( $config [ 'max_pages' ] * $config [ 'threads_per_page' ]);
2011-01-18 14:41:43 +01:00
// I too wish there was an easier way of doing this...
$query = prepare ( sprintf ( " SELECT `id` FROM `posts_%s` WHERE `thread` IS NULL ORDER BY `sticky` DESC, `bump` DESC LIMIT :offset, 9001 " , $board [ 'uri' ]));
$query -> bindValue ( ':offset' , $offset , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
while ( $post = $query -> fetch ()) {
deletePost ( $post [ 'id' ]);
}
}
2010-12-12 16:21:56 +01:00
function index ( $page , $mod = false ) {
2011-05-20 07:37:56 +02:00
global $board , $config , $memcached ;
2010-11-04 15:39:02 +01:00
2010-11-02 11:57:33 +01:00
$body = '' ;
2011-02-12 07:25:15 +01:00
$offset = round ( $page * $config [ 'threads_per_page' ] - $config [ 'threads_per_page' ]);
2010-12-17 15:18:03 +01:00
$query = prepare ( sprintf ( " SELECT * FROM `posts_%s` WHERE `thread` IS NULL ORDER BY `sticky` DESC, `bump` DESC LIMIT ?,? " , $board [ 'uri' ]));
$query -> bindValue ( 1 , $offset , PDO :: PARAM_INT );
2011-02-12 07:25:15 +01:00
$query -> bindValue ( 2 , $config [ 'threads_per_page' ], PDO :: PARAM_INT );
2010-12-17 15:18:03 +01:00
$query -> execute () or error ( db_error ( $query ));
if ( $query -> rowcount () < 1 && $page > 1 ) return false ;
while ( $th = $query -> fetch ()) {
2011-05-18 09:05:48 +02:00
$thread = new Thread ( $th [ 'id' ], $th [ 'subject' ], $th [ 'email' ], $th [ 'name' ], $th [ 'trip' ], $th [ 'capcode' ], $th [ 'body' ], $th [ 'time' ], $th [ 'thumb' ], $th [ 'thumbwidth' ], $th [ 'thumbheight' ], $th [ 'file' ], $th [ 'filewidth' ], $th [ 'fileheight' ], $th [ 'filesize' ], $th [ 'filename' ], $th [ 'ip' ], $th [ 'sticky' ], $th [ 'locked' ], $th [ 'embed' ], $mod ? '?/' : $config [ 'root' ], $mod );
2011-05-20 07:37:56 +02:00
2011-05-20 07:39:20 +02:00
if ( $config [ 'memcached' ][ 'enabled' ] && ! $mod ) {
2011-05-20 13:07:45 +02:00
if ( $built = $memcached -> get ( " theadindex_ { $board [ 'uri' ] } _ { $th [ 'id' ] } " )) {
2011-05-20 07:37:56 +02:00
$body .= $built ;
continue ;
}
}
2011-05-18 09:05:48 +02:00
$posts = prepare ( sprintf ( " SELECT * FROM `posts_%s` WHERE `thread` = ? ORDER BY `id` DESC LIMIT ? " , $board [ 'uri' ]));
2010-12-17 15:18:03 +01:00
$posts -> bindValue ( 1 , $th [ 'id' ]);
2011-02-16 13:32:43 +01:00
$posts -> bindValue ( 2 , ( $th [ 'sticky' ] ? $config [ 'threads_preview_sticky' ] : $config [ 'threads_preview' ]), PDO :: PARAM_INT );
2010-12-17 15:18:03 +01:00
$posts -> execute () or error ( db_error ( $posts ));
2011-02-17 07:07:36 +01:00
$num_images = 0 ;
while ( $po = $posts -> fetch ()) {
if ( $po [ 'file' ])
$num_images ++ ;
2011-05-19 13:42:53 +02:00
2011-05-18 09:05:48 +02:00
$thread -> add ( new Post ( $po [ 'id' ], $th [ 'id' ], $po [ 'subject' ], $po [ 'email' ], $po [ 'name' ], $po [ 'trip' ], $po [ 'capcode' ], $po [ 'body' ], $po [ 'time' ], $po [ 'thumb' ], $po [ 'thumbwidth' ], $po [ 'thumbheight' ], $po [ 'file' ], $po [ 'filewidth' ], $po [ 'fileheight' ], $po [ 'filesize' ], $po [ 'filename' ], $po [ 'ip' ], $po [ 'embed' ], $mod ? '?/' : $config [ 'root' ], $mod ));
2011-02-17 07:07:36 +01:00
}
2011-02-16 13:32:43 +01:00
if ( $posts -> rowCount () == ( $th [ 'sticky' ] ? $config [ 'threads_preview_sticky' ] : $config [ 'threads_preview' ])) {
2011-02-17 07:07:36 +01:00
$count = prepare ( sprintf ( " SELECT COUNT(`id`) as `num` FROM `posts_%s` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM `posts_%s` WHERE `file` IS NOT NULL AND `thread` = :thread " , $board [ 'uri' ], $board [ 'uri' ]));
$count -> bindValue ( ':thread' , $th [ 'id' ], PDO :: PARAM_INT );
2010-12-17 15:18:03 +01:00
$count -> execute () or error ( db_error ( $count ));
2011-02-17 07:07:36 +01:00
$c = $count -> fetch ();
$thread -> omitted = $c [ 'num' ] - ( $th [ 'sticky' ] ? $config [ 'threads_preview_sticky' ] : $config [ 'threads_preview' ]);
$c = $count -> fetch ();
$thread -> omitted_images = $c [ 'num' ] - $num_images ;
2010-11-02 11:57:33 +01:00
}
2010-12-17 15:18:03 +01:00
2010-11-02 11:57:33 +01:00
$thread -> posts = array_reverse ( $thread -> posts );
2011-05-20 07:37:56 +02:00
$built = '<div id="thread_' . $thread -> id . '">' . $thread -> build ( true ) . '</div>' ;
2011-05-20 07:39:20 +02:00
if ( $config [ 'memcached' ][ 'enabled' ] && ! $mod ) {
2011-05-20 13:07:45 +02:00
$memcached -> set ( " theadindex_ { $board [ 'uri' ] } _ { $th [ 'id' ] } " , $built , time () + $config [ 'memcached' ][ 'timeout' ]);
2011-05-20 07:37:56 +02:00
}
$body .= $built ;
2010-11-02 11:57:33 +01:00
}
2010-12-17 15:18:03 +01:00
2011-02-19 10:16:13 +01:00
return Array (
'board' => $board ,
'body' => $body ,
'post_url' => $config [ 'post_url' ],
2011-03-26 08:23:15 +01:00
'config' => $config ,
2011-02-19 10:16:13 +01:00
'boardlist' => createBoardlist ( $mod )
);
2010-11-02 11:57:33 +01:00
}
2010-12-16 11:28:38 +01:00
2011-02-17 08:37:18 +01:00
function getPageButtons ( $pages , $mod = false ) {
global $config , $board ;
$btn = Array ();
$root = ( $mod ? '?/' : $config [ 'root' ]) . $board [ 'dir' ];
foreach ( $pages as $num => $page ) {
if ( isset ( $page [ 'selected' ])) {
// Previous button
if ( $num == 0 ) {
// There is no previous page.
$btn [ 'prev' ] = 'Previous' ;
} else {
2011-02-22 07:52:26 +01:00
$loc = ( $mod ? '?/' . $board [ 'uri' ] . '/' : '' ) .
( $num == 1 ?
$config [ 'file_index' ]
:
sprintf ( $config [ 'file_page' ], $num )
);
$btn [ 'prev' ] = '<form action="' . ( $mod ? '' : $root . $loc ) . '" method="get">' .
( $mod ?
'<input type="hidden" name="status" value="301" />' .
'<input type="hidden" name="r" value="' . htmlentities ( $loc ) . '" />'
: '' ) .
'<input type="submit" value="Previous" /></form>' ;
2011-02-17 08:37:18 +01:00
}
if ( $num == count ( $pages ) - 1 ) {
// There is no next page.
$btn [ 'next' ] = 'Next' ;
} else {
2011-02-22 07:52:26 +01:00
$loc = ( $mod ? '?/' . $board [ 'uri' ] . '/' : '' ) . sprintf ( $config [ 'file_page' ], $num + 2 );
$btn [ 'next' ] = '<form action="' . ( $mod ? '' : $root . $loc ) . '" method="get">' .
( $mod ?
'<input type="hidden" name="status" value="301" />' .
'<input type="hidden" name="r" value="' . htmlentities ( $loc ) . '" />'
: '' ) .
'<input type="submit" value="Next" /></form>' ;
2011-02-17 08:37:18 +01:00
}
}
}
return $btn ;
}
2010-12-16 11:28:38 +01:00
function getPages ( $mod = false ) {
2011-02-12 07:25:15 +01:00
global $board , $config ;
2010-12-16 11:28:38 +01:00
2010-12-17 15:18:03 +01:00
// Count threads
$query = query ( sprintf ( " SELECT COUNT(`id`) as `num` FROM `posts_%s` WHERE `thread` IS NULL " , $board [ 'uri' ])) or error ( db_error ());
$count = current ( $query -> fetch ());
2011-02-12 07:25:15 +01:00
$count = floor (( $config [ 'threads_per_page' ] + $count - 1 ) / $config [ 'threads_per_page' ]);
2011-02-17 07:14:57 +01:00
if ( $count < 1 ) $count = 1 ;
2010-11-02 11:57:33 +01:00
$pages = Array ();
2011-02-12 07:25:15 +01:00
for ( $x = 0 ; $x < $count && $x < $config [ 'max_pages' ]; $x ++ ) {
2011-02-16 13:32:43 +01:00
$pages [] = Array (
'num' => $x + 1 ,
'link' => $x == 0 ? ( $mod ? '?/' : $config [ 'root' ]) . $board [ 'dir' ] . $config [ 'file_index' ] : ( $mod ? '?/' : $config [ 'root' ]) . $board [ 'dir' ] . sprintf ( $config [ 'file_page' ], $x + 1 )
);
2010-12-16 11:28:38 +01:00
}
return $pages ;
}
2011-01-18 14:41:43 +01:00
function makerobot ( $body ) {
2011-02-12 07:25:15 +01:00
global $config ;
2011-01-18 14:41:43 +01:00
$body = strtolower ( $body );
// Leave only letters
$body = preg_replace ( '/[^a-z]/i' , '' , $body );
// Remove repeating characters
2011-02-12 07:25:15 +01:00
if ( $config [ 'robot_strip_repeating' ])
2011-01-18 14:41:43 +01:00
$body = preg_replace ( '/(.)\\1+/' , '$1' , $body );
return sha1 ( $body );
}
function checkRobot ( $body ) {
$body = makerobot ( $body );
$query = prepare ( " SELECT 1 FROM `robot` WHERE `hash` = :hash LIMIT 1 " );
$query -> bindValue ( ':hash' , $body );
$query -> execute () or error ( db_error ( $query ));
2010-11-04 15:39:02 +01:00
2011-01-18 14:41:43 +01:00
if ( $query -> fetch ()) {
return true ;
} else {
// Insert new hash
$query = prepare ( " INSERT INTO `robot` VALUES (:hash) " );
$query -> bindValue ( ':hash' , $body );
$query -> execute () or error ( db_error ( $query ));
return false ;
}
}
2011-01-20 09:24:23 +01:00
function numPosts ( $id ) {
global $board ;
$query = prepare ( sprintf ( " SELECT COUNT(*) as `count` FROM `posts_%s` WHERE `thread` = :thread " , $board [ 'uri' ]));
$query -> bindValue ( ':thread' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
$result = $query -> fetch ();
return $result [ 'count' ];
}
function muteTime () {
2011-02-12 07:25:15 +01:00
global $config ;
2011-01-20 09:24:23 +01:00
// Find number of mutes in the past X hours
$query = prepare ( " SELECT COUNT(*) as `count` FROM `mutes` WHERE `time` >= :time AND `ip` = :ip " );
2011-02-16 10:37:57 +01:00
$query -> bindValue ( ':time' , time () - ( $config [ 'robot_mute_hour' ] * 3600 ), PDO :: PARAM_INT );
2011-01-20 09:24:23 +01:00
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
$query -> execute () or error ( db_error ( $query ));
$result = $query -> fetch ();
if ( $result [ 'count' ] == 0 ) return 0 ;
2011-02-12 07:25:15 +01:00
return pow ( $config [ 'robot_mute_multiplier' ], $result [ 'count' ]);
2011-01-20 09:24:23 +01:00
}
function mute () {
// Insert mute
$query = prepare ( " INSERT INTO `mutes` VALUES (:ip, :time) " );
$query -> bindValue ( ':time' , time (), PDO :: PARAM_INT );
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
$query -> execute () or error ( db_error ( $query ));
return muteTime ();
}
function checkMute () {
2011-05-19 13:24:17 +02:00
global $config , $memcached ;
if ( $config [ 'memcached' ][ 'enabled' ]) {
// Cached mute?
if (( $mute = $memcached -> get ( " mute_ ${ _SERVER['REMOTE_ADDR'] } " )) && ( $mutetime = $memcached -> get ( " mutetime_ ${ _SERVER['REMOTE_ADDR'] } " ))) {
error ( sprintf ( $config [ 'error' ][ 'youaremuted' ], $mute [ 'time' ] + $mutetime - time ()));
}
}
2011-02-16 10:37:57 +01:00
2011-01-20 09:24:23 +01:00
$mutetime = muteTime ();
if ( $mutetime > 0 ) {
// Find last mute time
$query = prepare ( " SELECT `time` FROM `mutes` WHERE `ip` = :ip ORDER BY `time` DESC LIMIT 1 " );
$query -> bindValue ( ':ip' , $_SERVER [ 'REMOTE_ADDR' ]);
$query -> execute () or error ( db_error ( $query ));
if ( ! $mute = $query -> fetch ()) {
// What!? He's muted but he's not muted...
return ;
}
if ( $mute [ 'time' ] + $mutetime > time ()) {
2011-05-19 13:24:17 +02:00
if ( $config [ 'memcached' ][ 'enabled' ]) {
$memcached -> set ( " mute_ ${ _SERVER['REMOTE_ADDR'] } " , $mute , $mute [ 'time' ] + $mutetime );
$memcached -> set ( " mutetime_ ${ _SERVER['REMOTE_ADDR'] } " , $mutetime , $mute [ 'time' ] + $mutetime );
}
2011-01-20 09:24:23 +01:00
// Not expired yet
2011-02-12 07:25:15 +01:00
error ( sprintf ( $config [ 'error' ][ 'youaremuted' ], $mute [ 'time' ] + $mutetime - time ()));
2011-01-20 09:24:23 +01:00
} else {
// Already expired
return ;
}
}
}
2011-02-17 12:03:52 +01:00
function createHiddenInputs () {
global $config ;
$inputs = Array ();
shuffle ( $config [ 'spam' ][ 'hidden_input_names' ]);
$hidden_input_names_x = 0 ;
$input_count = rand ( $config [ 'spam' ][ 'hidden_inputs_min' ], $config [ 'spam' ][ 'hidden_inputs_max' ]);
for ( $x = 0 ; $x < $input_count ; $x ++ ) {
if ( rand ( 0 , 2 ) == 0 || $hidden_input_names_x < 0 ) {
// Use an obscure name
$name = substr ( base64_encode ( sha1 ( rand ())), 0 , rand ( 2 , 40 ));
} else {
// Use a pre-defined confusing name
$name = $config [ 'spam' ][ 'hidden_input_names' ][ $hidden_input_names_x ++ ];
2011-02-17 14:36:50 +01:00
if ( $hidden_input_names_x >= count ( $config [ 'spam' ][ 'hidden_input_names' ]))
2011-02-17 12:03:52 +01:00
$hidden_input_names_x = - 1 ;
}
if ( rand ( 0 , 2 ) == 0 ) {
// Value must be null
$inputs [ $name ] = '' ;
} elseif ( rand ( 0 , 4 ) == 0 ) {
// Numeric value
$inputs [ $name ] = rand ( 0 , 100 );
} else {
// Obscure value
$inputs [ $name ] = substr ( base64_encode ( sha1 ( rand ())), 0 , rand ( 2 , 40 ));
}
}
$content = '' ;
foreach ( $inputs as $name => $value ) {
2011-02-17 12:11:11 +01:00
$display_type = rand ( 0 , 8 );
switch ( $display_type ) {
case 0 :
$content .= '<input type="hidden" name="' . htmlspecialchars ( $name ) . '" value="' . htmlspecialchars ( $value ) . '" />' ;
break ;
case 1 :
$content .= '<input style="display:none" name="' . htmlspecialchars ( $name ) . '" value="' . htmlspecialchars ( $value ) . '" />' ;
break ;
case 2 :
$content .= '<input type="hidden" value="' . htmlspecialchars ( $value ) . '" name="' . htmlspecialchars ( $name ) . '" />' ;
break ;
case 3 :
$content .= '<input type="hidden" name="' . htmlspecialchars ( $name ) . '" value="' . htmlspecialchars ( $value ) . '" />' ;
break ;
case 4 :
$content .= '<span style="display:none"><input type="text" name="' . htmlspecialchars ( $name ) . '" value="' . htmlspecialchars ( $value ) . '" /></span>' ;
break ;
case 5 :
$content .= '<div style="display:none"><input type="text" name="' . htmlspecialchars ( $name ) . '" value="' . htmlspecialchars ( $value ) . '" /></div>' ;
break ;
case 6 :
2011-04-14 12:43:34 +02:00
if ( ! empty ( $value ))
$content .= '<textarea style="display:none" name="' . htmlspecialchars ( $name ) . '">' . htmlspecialchars ( $value ) . '</textarea>' ;
else
$content .= '<input type="hidden" name="' . htmlspecialchars ( $name ) . '" value="' . htmlspecialchars ( $value ) . '" />' ;
2011-02-17 12:11:11 +01:00
break ;
case 7 :
2011-04-14 12:43:34 +02:00
if ( ! empty ( $value ))
$content .= '<textarea name="' . htmlspecialchars ( $name ) . '" style="display:none">' . htmlspecialchars ( $value ) . '</textarea>' ;
else
$content .= '<input type="hidden" name="' . htmlspecialchars ( $name ) . '" value="' . htmlspecialchars ( $value ) . '" />' ;
2011-02-17 12:11:11 +01:00
break ;
case 8 :
$content .= '<div style="display:none"><textarea name="' . htmlspecialchars ( $name ) . '" style="display:none">' . htmlspecialchars ( $value ) . '</textarea></div>' ;
break ;
}
2011-02-17 12:03:52 +01:00
}
// Create a hash to validate it after
// This is the tricky part.
// First, sort the keys in alphabetical order (A-Z)
ksort ( $inputs );
$hash = '' ;
// Iterate through each input
foreach ( $inputs as $name => $value ) {
$hash .= $name . '=' . $value ;
}
// Add a salt to the hash
$hash .= $config [ 'cookies' ][ 'salt' ];
// Use SHA1 for the hash
$hash = sha1 ( $hash );
// Append it to the HTML
$content .= '<input type="hidden" name="hash" value="' . $hash . '" />' ;
return $content ;
}
function checkSpam () {
global $config ;
if ( ! isset ( $_POST [ 'hash' ]))
return true ;
$hash = $_POST [ 'hash' ];
// Reconsturct the $inputs array
$inputs = Array ();
foreach ( $_POST as $name => $value ) {
if ( in_array ( $name , $config [ 'spam' ][ 'valid_inputs' ]))
continue ;
$inputs [ $name ] = $value ;
}
// Sort the inputs in alphabetical order (A-Z)
ksort ( $inputs );
$_hash = '' ;
// Iterate through each input
foreach ( $inputs as $name => $value ) {
$_hash .= $name . '=' . $value ;
}
// Add a salt to the hash
$_hash .= $config [ 'cookies' ][ 'salt' ];
// Use SHA1 for the hash
$_hash = sha1 ( $_hash );
return $hash != $_hash ;
}
2010-12-16 11:28:38 +01:00
function buildIndex () {
2011-02-12 07:25:15 +01:00
global $board , $config ;
2011-04-22 16:24:15 +02:00
2010-12-16 11:28:38 +01:00
$pages = getPages ();
2010-11-04 15:39:02 +01:00
2010-11-02 11:57:33 +01:00
$page = 1 ;
2011-02-12 07:25:15 +01:00
while ( $page <= $config [ 'max_pages' ] && $content = index ( $page )) {
$filename = $board [ 'dir' ] . ( $page == 1 ? $config [ 'file_index' ] : sprintf ( $config [ 'file_page' ], $page ));
2010-11-02 12:54:08 +01:00
if ( file_exists ( $filename )) $md5 = md5_file ( $filename );
2011-05-18 09:05:48 +02:00
2010-11-02 11:57:33 +01:00
$content [ 'pages' ] = $pages ;
2011-02-16 13:32:43 +01:00
$content [ 'pages' ][ $page - 1 ][ 'selected' ] = true ;
2011-02-17 08:37:18 +01:00
$content [ 'btn' ] = getPageButtons ( $content [ 'pages' ]);
2011-02-17 12:03:52 +01:00
$content [ 'hidden_inputs' ] = createHiddenInputs ();
2011-05-20 09:19:27 +02:00
file_write ( $filename , Element ( 'index.html' , $content ));
2010-11-30 09:57:32 +01:00
2010-11-02 12:54:08 +01:00
if ( isset ( $md5 ) && $md5 == md5_file ( $filename )) {
2010-11-02 11:57:33 +01:00
break ;
}
$page ++ ;
}
2011-02-12 07:25:15 +01:00
if ( $page < $config [ 'max_pages' ]) {
for (; $page <= $config [ 'max_pages' ]; $page ++ ) {
$filename = $page == 1 ? $config [ 'file_index' ] : sprintf ( $config [ 'file_page' ], $page );
2010-11-02 12:54:08 +01:00
@ unlink ( $filename );
2010-11-02 11:57:33 +01:00
}
}
}
2011-01-19 02:37:31 +01:00
2011-03-26 16:36:32 +01:00
function buildJavascript () {
global $config ;
$stylesheets = Array ();
foreach ( $config [ 'stylesheets' ] as $name => $uri ) {
$stylesheets [] = Array (
'name' => addslashes ( $name ),
'uri' => addslashes (( ! empty ( $uri ) ? $config [ 'uri_stylesheets' ] : '' ) . $uri ));
}
2011-05-20 09:19:27 +02:00
file_write ( $config [ 'file_script' ], Element ( 'main.js' , Array (
2011-03-26 16:36:32 +01:00
'config' => $config ,
'stylesheets' => $stylesheets
)));
}
2011-05-19 09:37:23 +02:00
function checkDNSBL () {
global $config ;
if ( isIPv6 ())
return ; // No IPv6 support yet.
if ( ! isset ( $_SERVER [ 'REMOTE_ADDR' ]))
return ; // Fix your web server configuration
// Reverse IP
$ip = ReverseIPOctets ( $_SERVER [ 'REMOTE_ADDR' ]);
2011-01-19 02:37:31 +01:00
2011-05-19 09:37:23 +02:00
foreach ( $config [ 'dnsbl' ] as & $blacklist ) {
$lookup = $ip . '.' . $blacklist ;
2011-05-19 10:04:47 +02:00
$host = gethostbyname ( $lookup );
2011-05-19 10:20:10 +02:00
if ( $host != $lookup ) {
2011-05-19 09:37:23 +02:00
// On NXDOMAIN (meaning it's not in the blacklist), gethostbyname() returns the host unchanged.
2011-05-19 10:04:47 +02:00
if ( preg_match ( '/^127\.0\.0\./' , $host ) && $host != '127.0.0.10' )
error ( sprintf ( $config [ 'error' ][ 'dnsbl' ], $blacklist ));
2011-05-19 09:37:23 +02:00
}
}
2011-01-19 02:37:31 +01:00
}
2011-02-17 10:32:11 +01:00
function isIPv6 () {
2011-02-17 11:08:32 +01:00
return strstr ( $_SERVER [ 'REMOTE_ADDR' ], ':' ) !== false ;
2011-02-17 10:32:11 +01:00
}
2011-02-20 07:19:57 +01:00
function ReverseIPOctets ( $ip ) {
$ipoc = explode ( '.' , $ip );
2011-01-19 02:37:31 +01:00
return $ipoc [ 3 ] . '.' . $ipoc [ 2 ] . '.' . $ipoc [ 1 ] . '.' . $ipoc [ 0 ];
}
2011-04-06 11:18:36 +02:00
function wordfilters ( & $body ) {
global $config ;
foreach ( $config [ 'wordfilters' ] as $filter ) {
if ( isset ( $filter [ 2 ]) && $filter [ 2 ]) {
$body = preg_replace ( $filter [ 0 ], $filter [ 1 ], $body );
} else {
$body = str_replace ( $filter [ 0 ], $filter [ 1 ], $body );
}
}
}
2011-04-14 20:59:04 +02:00
function quote ( $body , $quote = true ) {
2011-04-12 11:56:37 +02:00
$body = str_replace ( '<br/>' , " \n " , $body );
$body = strip_tags ( $body );
$body = preg_replace ( " /(^| \n )/ " , '$1>' , $body );
return $body . " \n " ;
}
2010-11-02 11:57:33 +01:00
function markup ( & $body ) {
2011-02-12 07:25:15 +01:00
global $board , $config ;
2011-01-02 12:14:51 +01:00
2011-01-02 12:16:18 +01:00
$body = utf8tohtml ( $body , true );
2011-03-02 03:19:46 +01:00
if ( $config [ 'wiki_markup' ]) {
2011-03-02 07:15:37 +01:00
$body = preg_replace ( " /(^| \n )==(.+?)== \n ?/m " , " <span class= \" heading \" > $ 2</span> " , $body );
2011-03-02 03:19:46 +01:00
$body = preg_replace ( " /'''(.+?)'''/m " , " <strong> $ 1</strong> " , $body );
$body = preg_replace ( " /''(.+?)''/m " , " <em> $ 1</em> " , $body );
$body = preg_replace ( " / \ * \ *(.+?) \ * \ */m " , " <span class= \" spoiler \" > $ 1</span> " , $body );
}
2011-02-12 07:25:15 +01:00
if ( $config [ 'markup_urls' ]) {
2011-03-27 17:20:03 +02:00
$body = preg_replace ( $config [ 'url_regex' ], " <a target= \" _blank \" rel= \" nofollow \" href= \" $ 0 \" > $ 0</a> " , $body , - 1 , $num_links );
2011-02-12 07:25:15 +01:00
if ( $num_links > $config [ 'max_links' ])
error ( $config [ 'error' ][ 'toomanylinks' ]);
2011-01-19 02:37:31 +01:00
}
2011-01-02 12:16:18 +01:00
2011-02-12 07:25:15 +01:00
if ( $config [ 'auto_unicode' ]) {
2010-11-02 11:57:33 +01:00
$body = str_replace ( '...' , '…' , $body );
$body = str_replace ( '<--' , '←' , $body );
2011-02-16 09:21:43 +01:00
$body = str_replace ( '-->' , '→' , $body );
2010-11-05 17:11:42 +01:00
// En and em- dashes are rendered exactly the same in
// most monospace fonts (they look the same in code
// editors).
$body = str_replace ( '---' , '—' , $body ); // em dash
2010-11-05 18:37:11 +01:00
$body = str_replace ( '--' , '– ' , $body ); // en dash
2010-11-02 11:57:33 +01:00
}
2010-11-04 15:39:02 +01:00
2010-11-04 08:22:57 +01:00
// Cites
2011-04-06 11:18:36 +02:00
if ( isset ( $board ) && preg_match_all ( '/(^|\s)>>(\d+?)(\s|$)/' , $body , $cites )) {
if ( count ( $cites [ 0 ]) > $config [ 'max_cites' ]) {
error ( $config [ 'error' ][ 'toomanycites' ]);
}
2011-04-22 16:24:15 +02:00
2010-11-04 08:22:57 +01:00
for ( $index = 0 ; $index < count ( $cites [ 0 ]); $index ++ ) {
$cite = $cites [ 2 ][ $index ];
2010-12-17 15:18:03 +01:00
$query = prepare ( sprintf ( " SELECT `thread`,`id` FROM `posts_%s` WHERE `id` = :id LIMIT 1 " , $board [ 'uri' ]));
$query -> bindValue ( ':id' , $cite );
$query -> execute () or error ( db_error ( $query ));
if ( $post = $query -> fetch ()) {
2011-04-06 11:18:36 +02:00
$replacement = '<a onclick="highlightReply(\'' . $cite . '\');" href="' .
$config [ 'root' ] . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] . ( $post [ 'thread' ] ? $post [ 'thread' ] : $post [ 'id' ]) . '.html#' . $cite . '">' .
'>>' . $cite .
'</a>' ;
$body = str_replace ( $cites [ 0 ][ $index ], $cites [ 1 ][ $index ] . $replacement . $cites [ 3 ][ $index ], $body );
2010-11-04 08:22:57 +01:00
}
2011-04-06 11:18:36 +02:00
}
}
// Cross-board linking
if ( preg_match_all ( '/(^|\s)>>>\/(\w+?)\/(\d+)?(\s|$)/' , $body , $cites )) {
if ( count ( $cites [ 0 ]) > $config [ 'max_cites' ]) {
error ( $config [ 'error' ][ 'toomanycross' ]);
}
2011-04-22 16:24:15 +02:00
2011-04-06 11:18:36 +02:00
for ( $index = 0 ; $index < count ( $cites [ 0 ]); $index ++ ) {
$_board = $cites [ 2 ][ $index ];
$cite = @ $cites [ 3 ][ $index ];
2011-01-02 12:14:51 +01:00
2011-04-06 11:18:36 +02:00
// Temporarily store board information because it will be overwritten
$tmp_board = $board [ 'uri' ];
2011-01-02 12:14:51 +01:00
2011-04-06 11:18:36 +02:00
// Check if the board exists, and load settings
if ( openBoard ( $_board )) {
if ( $cite ) {
$query = prepare ( sprintf ( " SELECT `thread`,`id` FROM `posts_%s` WHERE `id` = :id LIMIT 1 " , $board [ 'uri' ]));
$query -> bindValue ( ':id' , $cite );
$query -> execute () or error ( db_error ( $query ));
if ( $post = $query -> fetch ()) {
$replacement = '<a onclick="highlightReply(\'' . $cite . '\');" href="' .
$config [ 'root' ] . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] . ( $post [ 'thread' ] ? $post [ 'thread' ] : $post [ 'id' ]) . '.html#' . $cite . '">' .
'>>>/' . $_board . '/' . $cite .
'</a>' ;
$body = str_replace ( $cites [ 0 ][ $index ], $cites [ 1 ][ $index ] . $replacement . $cites [ 4 ][ $index ], $body );
}
} else {
$replacement = '<a href="' .
$config [ 'root' ] . $board [ 'dir' ] . $config [ 'file_index' ] . '">' .
'>>>/' . $_board . '/' .
'</a>' ;
$body = str_replace ( $cites [ 0 ][ $index ], $cites [ 1 ][ $index ] . $replacement . $cites [ 4 ][ $index ], $body );
}
}
2011-01-02 12:14:51 +01:00
2011-04-06 11:18:36 +02:00
// Restore main board settings
openBoard ( $tmp_board );
2010-11-02 11:57:33 +01:00
}
}
2011-04-06 11:18:36 +02:00
2010-11-04 15:39:02 +01:00
2010-11-02 11:57:33 +01:00
$body = str_replace ( " \r " , '' , $body );
2011-01-02 12:14:51 +01:00
2010-11-02 11:57:33 +01:00
$body = preg_replace ( " /(^| \n )([ \ s]+)?(>)([^ \n ]+)?( $ | \n )/m " , '$1$2<span class="quote">$3$4</span>$5' , $body );
2010-11-26 10:41:35 +01:00
2011-02-21 05:51:46 +01:00
if ( $config [ 'strip_superfluous_returns' ])
$body = preg_replace ( '/\s+$/' , '' , $body );
2010-11-02 11:57:33 +01:00
$body = preg_replace ( " / \n / " , '<br/>' , $body );
}
2010-11-04 15:39:02 +01:00
2011-04-12 10:02:20 +02:00
function html_entity_decode_utf8 ( $string ) {
static $trans_tbl ;
// replace numeric entities
$string = preg_replace ( '~&#x([0-9a-f]+);~ei' , 'code2utf(hexdec("\\1"))' , $string );
$string = preg_replace ( '~&#([0-9]+);~e' , 'code2utf(\\1)' , $string );
// replace literal entities
if ( ! isset ( $trans_tbl )) {
$trans_tbl = array ();
foreach ( get_html_translation_table ( HTML_ENTITIES ) as $val => $key )
$trans_tbl [ $key ] = utf8_encode ( $val );
}
return strtr ( $string , $trans_tbl );
}
// Returns the utf string corresponding to the unicode value (from php.net, courtesy - romans@void.lv)
function code2utf ( $num ) {
if ( $num < 128 )
return chr ( $num );
if ( $num < 2048 )
return chr (( $num >> 6 ) + 192 ) . chr (( $num & 63 ) + 128 );
if ( $num < 65536 )
return chr (( $num >> 12 ) + 224 ) . chr ((( $num >> 6 ) & 63 ) + 128 ) . chr (( $num & 63 ) + 128 );
if ( $num < 2097152 )
return chr (( $num >> 18 ) + 240 ) . chr ((( $num >> 12 ) & 63 ) + 128 ) . chr ((( $num >> 6 ) & 63 ) + 128 ) . chr (( $num & 63 ) + 128 );
return '' ;
}
2010-11-02 11:57:33 +01:00
function utf8tohtml ( $utf8 , $encodeTags = true ) {
$result = '' ;
for ( $i = 0 ; $i < strlen ( $utf8 ); $i ++ ) {
$char = $utf8 [ $i ];
$ascii = ord ( $char );
if ( $ascii < 128 ) {
// one-byte character
$result .= ( $encodeTags ) ? htmlentities ( $char ) : $char ;
} else if ( $ascii < 192 ) {
// non-utf8 character or not a start byte
} else if ( $ascii < 224 ) {
// two-byte character
$result .= htmlentities ( substr ( $utf8 , $i , 2 ), ENT_QUOTES , 'UTF-8' );
$i ++ ;
} else if ( $ascii < 240 ) {
// three-byte character
$ascii1 = ord ( $utf8 [ $i + 1 ]);
2011-04-12 10:02:20 +02:00
$ascii2 = @ ord ( $utf8 [ $i + 2 ]);
2010-11-02 11:57:33 +01:00
$unicode = ( 15 & $ascii ) * 4096 +
( 63 & $ascii1 ) * 64 +
( 63 & $ascii2 );
$result .= " &# $unicode ; " ;
$i += 2 ;
} else if ( $ascii < 248 ) {
// four-byte character
$ascii1 = ord ( $utf8 [ $i + 1 ]);
$ascii2 = ord ( $utf8 [ $i + 2 ]);
$ascii3 = ord ( $utf8 [ $i + 3 ]);
$unicode = ( 15 & $ascii ) * 262144 +
( 63 & $ascii1 ) * 4096 +
( 63 & $ascii2 ) * 64 +
( 63 & $ascii3 );
$result .= " &# $unicode ; " ;
$i += 3 ;
}
}
return $result ;
}
2010-11-04 15:39:02 +01:00
2010-12-16 06:36:14 +01:00
function buildThread ( $id , $return = false , $mod = false ) {
2011-05-19 13:42:53 +02:00
global $board , $config , $memcached ;
2010-11-02 11:57:33 +01:00
$id = round ( $id );
2010-12-16 06:36:14 +01:00
2011-05-20 07:37:56 +02:00
if ( $config [ 'memcached' ][ 'enabled' ] && ! $mod ) {
// Clear cache for index pages
2011-05-20 13:08:41 +02:00
$memcached -> delete ( " theadindex_ { $board [ 'uri' ] } _ { $id } " );
2011-05-19 13:42:53 +02:00
}
2011-05-18 09:05:48 +02:00
$query = prepare ( sprintf ( " SELECT * FROM `posts_%s` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`time` " , $board [ 'uri' ]));
2010-12-17 15:18:03 +01:00
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
while ( $post = $query -> fetch ()) {
2010-11-02 11:57:33 +01:00
if ( ! isset ( $thread )) {
2011-05-18 09:05:48 +02:00
$thread = new Thread ( $post [ 'id' ], $post [ 'subject' ], $post [ 'email' ], $post [ 'name' ], $post [ 'trip' ], $post [ 'capcode' ], $post [ 'body' ], $post [ 'time' ], $post [ 'thumb' ], $post [ 'thumbwidth' ], $post [ 'thumbheight' ], $post [ 'file' ], $post [ 'filewidth' ], $post [ 'fileheight' ], $post [ 'filesize' ], $post [ 'filename' ], $post [ 'ip' ], $post [ 'sticky' ], $post [ 'locked' ], $post [ 'embed' ], $mod ? '?/' : $config [ 'root' ], $mod );
2010-11-02 11:57:33 +01:00
} else {
2011-05-18 09:05:48 +02:00
$thread -> add ( new Post ( $post [ 'id' ], $thread -> id , $post [ 'subject' ], $post [ 'email' ], $post [ 'name' ], $post [ 'trip' ], $post [ 'capcode' ], $post [ 'body' ], $post [ 'time' ], $post [ 'thumb' ], $post [ 'thumbwidth' ], $post [ 'thumbheight' ], $post [ 'file' ], $post [ 'filewidth' ], $post [ 'fileheight' ], $post [ 'filesize' ], $post [ 'filename' ], $post [ 'ip' ], $post [ 'embed' ], $mod ? '?/' : $config [ 'root' ], $mod ));
2010-11-02 11:57:33 +01:00
}
2010-12-16 06:36:14 +01:00
}
2010-12-17 15:18:03 +01:00
// Check if any posts were found
2011-02-12 07:25:15 +01:00
if ( ! isset ( $thread )) error ( $config [ 'error' ][ 'nonexistant' ]);
2010-12-17 15:18:03 +01:00
$body = Element ( 'thread.html' , Array (
'board' => $board ,
'body' => $thread -> build (),
2011-03-26 08:23:15 +01:00
'config' => $config ,
2010-12-17 15:18:03 +01:00
'id' => $id ,
'mod' => $mod ,
2011-02-19 10:16:13 +01:00
'boardlist' => createBoardlist ( $mod ),
2011-02-17 12:03:52 +01:00
'hidden_inputs' => $content [ 'hidden_inputs' ] = createHiddenInputs (),
2011-02-12 07:25:15 +01:00
'return' => ( $mod ? '?' . $board [ 'url' ] . $config [ 'file_index' ] : $config [ 'root' ] . $board [ 'uri' ] . '/' . $config [ 'file_index' ])
2010-12-17 15:18:03 +01:00
));
2011-05-19 13:42:53 +02:00
2010-12-16 06:36:14 +01:00
if ( $return )
return $body ;
else
2011-05-20 09:19:27 +02:00
file_write ( $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] . sprintf ( $config [ 'file_page' ], $id ), $body );
2010-11-02 11:57:33 +01:00
}
2010-12-01 02:54:58 +01:00
2011-02-22 07:38:38 +01:00
function rrmdir ( $dir ) {
if ( is_dir ( $dir )) {
$objects = scandir ( $dir );
foreach ( $objects as $object ) {
if ( $object != " . " && $object != " .. " ) {
if ( filetype ( $dir . " / " . $object ) == " dir " )
rrmdir ( $dir . " / " . $object );
else
unlink ( $dir . " / " . $object );
}
}
reset ( $objects );
rmdir ( $dir );
}
2011-04-13 12:02:58 +02:00
}
function poster_id ( $ip , $thread ) {
global $config ;
// Confusing, hard to brute-force, but simple algorithm
return substr ( sha1 ( sha1 ( $ip . $config [ 'secure_trip_salt' ] . $thread ) . $config [ 'secure_trip_salt' ]), 0 , $config [ 'poster_id_length' ]);
}
2011-02-22 07:38:38 +01:00
2011-04-13 12:02:58 +02:00
function generate_tripcode ( $name , $length = 10 ){
2011-02-12 07:25:15 +01:00
global $config ;
2010-11-02 11:57:33 +01:00
$name = stripslashes ( $name );
$t = explode ( '#' , $name );
$nameo = $t [ 0 ];
if ( isset ( $t [ 1 ] ) || isset ( $t [ 2 ] ) ) {
$trip = ( ( strlen ( $t [ 1 ] ) > 0 ) ? $t [ 1 ] : $t [ 2 ] );
if ( ( function_exists ( 'mb_convert_encoding' ) ) ) {
# mb_substitute_character('none');
$recoded_cap = mb_convert_encoding ( $trip , 'Shift_JIS' , 'UTF-8' );
}
$trip = ( ( ! empty ( $recoded_cap ) ) ? $recoded_cap : $trip );
$salt = substr ( $trip . 'H.' , 1 , 2 );
$salt = preg_replace ( '/[^\.-z]/' , '.' , $salt );
$salt = strtr ( $salt , ':;<=>?@[\]^_`' , 'ABCDEFGabcdef' );
if ( isset ( $t [ 2 ] ) ) {
// secure
2011-02-12 07:25:15 +01:00
$trip = '!!' . substr ( crypt ( $trip , $config [ 'secure_trip_salt' ] ), ( - 1 * $length ) );
2010-11-02 11:57:33 +01:00
} else {
// insecure
$trip = '!' . substr ( crypt ( $trip , $salt ), ( - 1 * $length ) );
}
}
if ( isset ( $trip ) ) {
return array ( $nameo , $trip );
} else {
return array ( $nameo );
}
}
2010-11-04 15:39:02 +01:00
2010-11-04 05:40:39 +01:00
// Highest common factor
function hcf ( $a , $b ){
$gcd = 1 ;
if ( $a > $b ) {
$a = $a + $b ;
$b = $a - $b ;
$a = $a - $b ;
}
if ( $b == ( round ( $b / $a )) * $a )
$gcd = $a ;
else {
for ( $i = round ( $a / 2 ); $i ; $i -- ) {
if ( $a == round ( $a / $i ) * $i && $b == round ( $b / $i ) * $i ) {
$gcd = $i ;
$i = false ;
}
}
}
return $gcd ;
}
2010-11-03 17:10:47 +01:00
function fraction ( $numerator , $denominator , $sep ) {
2010-11-04 05:40:39 +01:00
$gcf = hcf ( $numerator , $denominator );
$numerator = $numerator / $gcf ;
$denominator = $denominator / $gcf ;
2010-11-04 15:39:02 +01:00
2010-11-04 05:40:39 +01:00
return " { $numerator } { $sep } { $denominator } " ;
2010-11-03 17:10:47 +01:00
}
2010-11-02 11:57:33 +01:00
/*********************************************/
/* Fonction: imagecreatefrombmp */
/* Author: DHKold */
/* Contact: admin@dhkold.com */
/* Date: The 15th of June 2005 */
/* Version: 2.0B */
/*********************************************/
function imagecreatefrombmp ( $filename ) {
if ( ! $f1 = fopen ( $filename , " rb " )) return FALSE ;
$FILE = unpack ( " vfile_type/Vfile_size/Vreserved/Vbitmap_offset " , fread ( $f1 , 14 ));
if ( $FILE [ 'file_type' ] != 19778 ) return FALSE ;
$BMP = unpack ( 'Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel' .
'/Vcompression/Vsize_bitmap/Vhoriz_resolution' .
'/Vvert_resolution/Vcolors_used/Vcolors_important' , fread ( $f1 , 40 ));
$BMP [ 'colors' ] = pow ( 2 , $BMP [ 'bits_per_pixel' ]);
if ( $BMP [ 'size_bitmap' ] == 0 ) $BMP [ 'size_bitmap' ] = $FILE [ 'file_size' ] - $FILE [ 'bitmap_offset' ];
$BMP [ 'bytes_per_pixel' ] = $BMP [ 'bits_per_pixel' ] / 8 ;
$BMP [ 'bytes_per_pixel2' ] = ceil ( $BMP [ 'bytes_per_pixel' ]);
$BMP [ 'decal' ] = ( $BMP [ 'width' ] * $BMP [ 'bytes_per_pixel' ] / 4 );
$BMP [ 'decal' ] -= floor ( $BMP [ 'width' ] * $BMP [ 'bytes_per_pixel' ] / 4 );
$BMP [ 'decal' ] = 4 - ( 4 * $BMP [ 'decal' ]);
if ( $BMP [ 'decal' ] == 4 ) $BMP [ 'decal' ] = 0 ;
2010-11-04 15:39:02 +01:00
2010-11-02 11:57:33 +01:00
$PALETTE = array ();
if ( $BMP [ 'colors' ] < 16777216 )
{
$PALETTE = unpack ( 'V' . $BMP [ 'colors' ], fread ( $f1 , $BMP [ 'colors' ] * 4 ));
}
2010-11-04 15:39:02 +01:00
2010-11-02 11:57:33 +01:00
$IMG = fread ( $f1 , $BMP [ 'size_bitmap' ]);
$VIDE = chr ( 0 );
$res = imagecreatetruecolor ( $BMP [ 'width' ], $BMP [ 'height' ]);
$P = 0 ;
$Y = $BMP [ 'height' ] - 1 ;
while ( $Y >= 0 )
{
$X = 0 ;
while ( $X < $BMP [ 'width' ])
{
if ( $BMP [ 'bits_per_pixel' ] == 24 )
$COLOR = unpack ( " V " , substr ( $IMG , $P , 3 ) . $VIDE );
elseif ( $BMP [ 'bits_per_pixel' ] == 16 )
{
$COLOR = unpack ( " n " , substr ( $IMG , $P , 2 ));
$COLOR [ 1 ] = $PALETTE [ $COLOR [ 1 ] + 1 ];
}
elseif ( $BMP [ 'bits_per_pixel' ] == 8 )
{
$COLOR = unpack ( " n " , $VIDE . substr ( $IMG , $P , 1 ));
$COLOR [ 1 ] = $PALETTE [ $COLOR [ 1 ] + 1 ];
}
elseif ( $BMP [ 'bits_per_pixel' ] == 4 )
{
$COLOR = unpack ( " n " , $VIDE . substr ( $IMG , floor ( $P ), 1 ));
if (( $P * 2 ) % 2 == 0 ) $COLOR [ 1 ] = ( $COLOR [ 1 ] >> 4 ) ; else $COLOR [ 1 ] = ( $COLOR [ 1 ] & 0x0F );
$COLOR [ 1 ] = $PALETTE [ $COLOR [ 1 ] + 1 ];
}
elseif ( $BMP [ 'bits_per_pixel' ] == 1 )
{
$COLOR = unpack ( " n " , $VIDE . substr ( $IMG , floor ( $P ), 1 ));
if (( $P * 8 ) % 8 == 0 ) $COLOR [ 1 ] = $COLOR [ 1 ] >> 7 ;
elseif (( $P * 8 ) % 8 == 1 ) $COLOR [ 1 ] = ( $COLOR [ 1 ] & 0x40 ) >> 6 ;
elseif (( $P * 8 ) % 8 == 2 ) $COLOR [ 1 ] = ( $COLOR [ 1 ] & 0x20 ) >> 5 ;
elseif (( $P * 8 ) % 8 == 3 ) $COLOR [ 1 ] = ( $COLOR [ 1 ] & 0x10 ) >> 4 ;
elseif (( $P * 8 ) % 8 == 4 ) $COLOR [ 1 ] = ( $COLOR [ 1 ] & 0x8 ) >> 3 ;
elseif (( $P * 8 ) % 8 == 5 ) $COLOR [ 1 ] = ( $COLOR [ 1 ] & 0x4 ) >> 2 ;
elseif (( $P * 8 ) % 8 == 6 ) $COLOR [ 1 ] = ( $COLOR [ 1 ] & 0x2 ) >> 1 ;
elseif (( $P * 8 ) % 8 == 7 ) $COLOR [ 1 ] = ( $COLOR [ 1 ] & 0x1 );
$COLOR [ 1 ] = $PALETTE [ $COLOR [ 1 ] + 1 ];
}
else
return FALSE ;
imagesetpixel ( $res , $X , $Y , $COLOR [ 1 ]);
$X ++ ;
$P += $BMP [ 'bytes_per_pixel' ];
}
$Y -- ;
$P += $BMP [ 'decal' ];
}
fclose ( $f1 );
return $res ;
}
2011-02-19 09:45:54 +01:00
function getPostByHash ( $hash ) {
global $board ;
$query = prepare ( sprintf ( " SELECT `id`,`thread` FROM `posts_%s` WHERE `filehash` = :hash " , $board [ 'uri' ]));
$query -> bindValue ( ':hash' , $hash , PDO :: PARAM_STR );
$query -> execute () or error ( db_error ( $query ));
if ( $post = $query -> fetch ()) {
return $post ;
}
return false ;
}
2011-02-19 09:28:07 +01:00
function undoImage ( $post ) {
2011-02-19 10:33:00 +01:00
if ( $post [ 'has_file' ])
@ unlink ( $post [ 'file' ]);
@ unlink ( $post [ 'thumb' ]);
2011-02-19 09:28:07 +01:00
}
2010-11-03 13:37:28 +01:00
function createimage ( $type , $source_pic ) {
2011-02-19 09:28:07 +01:00
global $config ;
2010-11-04 10:01:20 +01:00
$image = false ;
2010-11-02 11:57:33 +01:00
switch ( $type ) {
case 'jpg' :
2011-04-22 16:24:15 +02:00
case 'jpeg' :
2011-04-22 16:38:25 +02:00
if ( ! $image = @ imagecreatefromjpeg ( $source_pic )) {
2010-11-04 10:01:20 +01:00
unlink ( $source_pic );
2011-02-12 07:25:15 +01:00
error ( $config [ 'error' ][ 'invalidimg' ]);
2010-11-04 10:01:20 +01:00
}
2010-11-02 11:57:33 +01:00
break ;
case 'png' :
2010-11-04 10:01:20 +01:00
if ( ! $image = @ imagecreatefrompng ( $source_pic )) {
unlink ( $source_pic );
2011-02-12 07:25:15 +01:00
error ( $config [ 'error' ][ 'invalidimg' ]);
2010-11-04 10:01:20 +01:00
}
2010-11-02 11:57:33 +01:00
break ;
case 'gif' :
2010-11-04 10:01:20 +01:00
if ( ! $image = @ imagecreatefromgif ( $source_pic )) {
unlink ( $source_pic );
2011-02-12 07:25:15 +01:00
error ( $config [ 'error' ][ 'invalidimg' ]);
2010-11-04 10:01:20 +01:00
}
2010-11-02 11:57:33 +01:00
break ;
case 'bmp' :
2010-11-04 10:01:20 +01:00
if ( ! $image = @ imagecreatefrombmp ( $source_pic )) {
unlink ( $source_pic );
2011-02-12 07:25:15 +01:00
error ( $config [ 'error' ][ 'invalidimg' ]);
2010-11-04 10:01:20 +01:00
}
2010-11-02 11:57:33 +01:00
break ;
default :
2011-04-13 12:57:41 +02:00
error ( $config [ 'error' ][ 'unknownext' ]);
2010-11-02 11:57:33 +01:00
}
2010-11-04 10:01:20 +01:00
return $image ;
2010-11-03 13:37:28 +01:00
}
2010-11-04 15:39:02 +01:00
2011-04-13 12:57:41 +02:00
function resize ( $src , $width , $height , $destination_pic , $max_width , $max_height , $ext ) {
global $config ;
2010-11-03 13:37:28 +01:00
$return = Array ();
2010-11-02 11:57:33 +01:00
$x_ratio = $max_width / $width ;
$y_ratio = $max_height / $height ;
if (( $width <= $max_width ) && ( $height <= $max_height )) {
$tn_width = $width ;
$tn_height = $height ;
} elseif (( $x_ratio * $height ) < $max_height ) {
$tn_height = ceil ( $x_ratio * $height );
$tn_width = $max_width ;
} else {
$tn_width = ceil ( $y_ratio * $width );
$tn_height = $max_height ;
}
2010-11-04 15:39:02 +01:00
2010-11-02 11:57:33 +01:00
$return [ 'width' ] = $tn_width ;
$return [ 'height' ] = $tn_height ;
2010-11-04 15:39:02 +01:00
2010-11-02 14:08:03 +01:00
$tmp = imagecreatetruecolor ( $tn_width , $tn_height );
2011-04-12 20:08:59 +02:00
if ( $ext == 'png' || $ext == 'gif' ) {
imagecolortransparent ( $tmp , imagecolorallocatealpha ( $tmp , 0 , 0 , 0 , 0 ));
imagesavealpha ( $tmp , true );
}
if ( $ext == 'png' )
imagealphablending ( $tmp , false );
2010-11-02 14:08:03 +01:00
imagecopyresampled ( $tmp , $src , 0 , 0 , 0 , 0 , $tn_width , $tn_height , $width , $height );
2011-04-12 20:08:59 +02:00
switch ( $ext ) {
case 'jpg' :
case 'jpeg' :
imagejpeg ( $tmp , $destination_pic );
break ;
case 'png' :
imagepng ( $tmp , $destination_pic , $config [ 'thumb_quality' ]);
break ;
case 'gif' :
imagegif ( $tmp , $destination_pic );
break ;
case 'bmp' :
imagebmp ( $tmp , $destination_pic );
break ;
default :
2011-04-13 12:57:41 +02:00
error ( $config [ 'error' ][ 'unknownext' ]);
2011-04-12 20:08:59 +02:00
}
2010-11-02 11:57:33 +01:00
imagedestroy ( $src );
imagedestroy ( $tmp );
2010-11-04 15:39:02 +01:00
2010-11-02 11:57:33 +01:00
return $return ;
}
2010-11-04 15:39:02 +01:00
2010-11-04 09:40:51 +01:00
function imagebmp ( & $img , $filename = '' ) {
$widthOrig = imagesx ( $img );
$widthFloor = (( floor ( $widthOrig / 16 )) * 16 );
$widthCeil = (( ceil ( $widthOrig / 16 )) * 16 );
$height = imagesy ( $img );
2010-11-04 15:39:02 +01:00
2010-11-04 09:40:51 +01:00
$size = ( $widthCeil * $height * 3 ) + 54 ;
2010-11-04 15:39:02 +01:00
2010-11-04 09:40:51 +01:00
// Bitmap File Header
$result = 'BM' ; // header (2b)
$result .= int_to_dword ( $size ); // size of file (4b)
$result .= int_to_dword ( 0 ); // reserved (4b)
$result .= int_to_dword ( 54 ); // byte location in the file which is first byte of IMAGE (4b)
// Bitmap Info Header
$result .= int_to_dword ( 40 ); // Size of BITMAPINFOHEADER (4b)
$result .= int_to_dword ( $widthCeil ); // width of bitmap (4b)
$result .= int_to_dword ( $height ); // height of bitmap (4b)
$result .= int_to_word ( 1 ); // biPlanes = 1 (2b)
$result .= int_to_word ( 24 ); // biBitCount = {1 (mono) or 4 (16 clr ) or 8 (256 clr) or 24 (16 Mil)} (2b
$result .= int_to_dword ( 0 ); // RLE COMPRESSION (4b)
$result .= int_to_dword ( 0 ); // width x height (4b)
$result .= int_to_dword ( 0 ); // biXPelsPerMeter (4b)
$result .= int_to_dword ( 0 ); // biYPelsPerMeter (4b)
$result .= int_to_dword ( 0 ); // Number of palettes used (4b)
$result .= int_to_dword ( 0 ); // Number of important colour (4b)
2010-11-04 15:39:02 +01:00
2010-11-04 09:40:51 +01:00
// is faster than chr()
$arrChr = array ();
for ( $i = 0 ; $i < 256 ; $i ++ ){
$arrChr [ $i ] = chr ( $i );
}
2010-11-04 15:39:02 +01:00
2010-11-04 09:40:51 +01:00
// creates image data
$bgfillcolor = array ( 'red' => 0 , 'green' => 0 , 'blue' => 0 );
2010-11-04 15:39:02 +01:00
2010-11-04 09:40:51 +01:00
// bottom to top - left to right - attention blue green red !!!
$y = $height - 1 ;
for ( $y2 = 0 ; $y2 < $height ; $y2 ++ ) {
for ( $x = 0 ; $x < $widthFloor ; ) {
$rgb = imagecolorsforindex ( $img , imagecolorat ( $img , $x ++ , $y ));
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
$rgb = imagecolorsforindex ( $img , imagecolorat ( $img , $x ++ , $y ));
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
$rgb = imagecolorsforindex ( $img , imagecolorat ( $img , $x ++ , $y ));
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
$rgb = imagecolorsforindex ( $img , imagecolorat ( $img , $x ++ , $y ));
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
$rgb = imagecolorsforindex ( $img , imagecolorat ( $img , $x ++ , $y ));
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
$rgb = imagecolorsforindex ( $img , imagecolorat ( $img , $x ++ , $y ));
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
$rgb = imagecolorsforindex ( $img , imagecolorat ( $img , $x ++ , $y ));
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
$rgb = imagecolorsforindex ( $img , imagecolorat ( $img , $x ++ , $y ));
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
}
for ( $x = $widthFloor ; $x < $widthCeil ; $x ++ ) {
$rgb = ( $x < $widthOrig ) ? imagecolorsforindex ( $img , imagecolorat ( $img , $x , $y )) : $bgfillcolor ;
$result .= $arrChr [ $rgb [ 'blue' ]] . $arrChr [ $rgb [ 'green' ]] . $arrChr [ $rgb [ 'red' ]];
}
$y -- ;
}
2010-11-04 15:39:02 +01:00
2010-11-04 09:40:51 +01:00
// see imagegif
if ( $filename == '' ) {
echo $result ;
} else {
$file = fopen ( $filename , 'wb' );
fwrite ( $file , $result );
fclose ( $file );
}
}
// imagebmp helpers
2010-11-04 10:01:20 +01:00
function int_to_dword ( $n ) {
2010-11-04 09:40:51 +01:00
return chr ( $n & 255 ) . chr (( $n >> 8 ) & 255 ) . chr (( $n >> 16 ) & 255 ) . chr (( $n >> 24 ) & 255 );
}
2010-11-04 10:01:20 +01:00
function int_to_word ( $n ) {
2010-11-04 09:40:51 +01:00
return chr ( $n & 255 ) . chr (( $n >> 8 ) & 255 );
}
2011-01-02 17:27:34 +01:00
?>